summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2015-12-30 11:57:38 +0000
committerDimitry Andric <dim@FreeBSD.org>2015-12-30 11:57:38 +0000
commit5a5c549fe9a3fef595297bd21d36bed8409dc37d (patch)
treea964c8f5ac85b7b641cac022c5f9bf4eed3d2b9b
parentfb911942f1434f3d1750f83f25f5e42c80e60638 (diff)
downloadsrc-test2-5a5c549fe9a3fef595297bd21d36bed8409dc37d.tar.gz
src-test2-5a5c549fe9a3fef595297bd21d36bed8409dc37d.zip
Vendor import of lld trunk r256633:vendor/lld/lld-trunk-r256633
Notes
Notes: svn path=/vendor/lld/dist/; revision=292934 svn path=/vendor/lld/lld-trunk-r256633/; revision=292935; tag=vendor/lld/lld-trunk-r256633
-rw-r--r--CMakeLists.txt5
-rw-r--r--CODE_OWNERS.TXT19
-rw-r--r--COFF/CMakeLists.txt33
-rw-r--r--COFF/Chunks.cpp340
-rw-r--r--COFF/Chunks.h332
-rw-r--r--COFF/Config.h140
-rw-r--r--COFF/DLL.cpp556
-rw-r--r--COFF/DLL.h84
-rw-r--r--COFF/Driver.cpp677
-rw-r--r--COFF/Driver.h180
-rw-r--r--COFF/DriverUtils.cpp718
-rw-r--r--COFF/Error.cpp30
-rw-r--r--COFF/Error.h28
-rw-r--r--COFF/ICF.cpp244
-rw-r--r--COFF/InputFiles.cpp367
-rw-r--r--COFF/InputFiles.h222
-rw-r--r--COFF/MarkLive.cpp61
-rw-r--r--COFF/ModuleDef.cpp291
-rw-r--r--COFF/Options.td125
-rw-r--r--COFF/PDB.cpp60
-rw-r--r--COFF/README.md265
-rw-r--r--COFF/SymbolTable.cpp445
-rw-r--r--COFF/SymbolTable.h125
-rw-r--r--COFF/Symbols.cpp243
-rw-r--r--COFF/Symbols.h407
-rw-r--r--COFF/Writer.cpp765
-rw-r--r--COFF/Writer.h26
-rw-r--r--ELF/CMakeLists.txt26
-rw-r--r--ELF/Config.h84
-rw-r--r--ELF/Driver.cpp299
-rw-r--r--ELF/Driver.h67
-rw-r--r--ELF/DriverUtils.cpp120
-rw-r--r--ELF/Error.cpp38
-rw-r--r--ELF/Error.h32
-rw-r--r--ELF/InputFiles.cpp496
-rw-r--r--ELF/InputFiles.h211
-rw-r--r--ELF/InputSection.cpp399
-rw-r--r--ELF/InputSection.h187
-rw-r--r--ELF/LinkerScript.cpp318
-rw-r--r--ELF/MarkLive.cpp131
-rw-r--r--ELF/Options.td161
-rw-r--r--ELF/OutputSections.cpp1534
-rw-r--r--ELF/OutputSections.h485
-rw-r--r--ELF/README.md21
-rw-r--r--ELF/SymbolTable.cpp267
-rw-r--r--ELF/SymbolTable.h98
-rw-r--r--ELF/Symbols.cpp148
-rw-r--r--ELF/Symbols.h327
-rw-r--r--ELF/Target.cpp1481
-rw-r--r--ELF/Target.h117
-rw-r--r--ELF/Writer.cpp1282
-rw-r--r--ELF/Writer.h24
-rw-r--r--Makefile86
-rw-r--r--docs/Makefile155
-rw-r--r--docs/Readers.rst7
-rw-r--r--docs/design.rst55
-rw-r--r--docs/getting_started.rst4
-rw-r--r--docs/index.rst11
-rw-r--r--docs/open_projects.rst1
-rw-r--r--docs/windows_support.rst31
-rw-r--r--include/Makefile4
-rw-r--r--include/lld/Config/Makefile32
-rw-r--r--include/lld/Core/Alias.h10
-rw-r--r--include/lld/Core/DefinedAtom.h14
-rw-r--r--include/lld/Core/Error.h26
-rw-r--r--include/lld/Core/File.h178
-rw-r--r--include/lld/Core/LLVM.h2
-rw-r--r--include/lld/Core/LinkingContext.h15
-rw-r--r--include/lld/Core/Parallel.h106
-rw-r--r--include/lld/Core/Pass.h4
-rw-r--r--include/lld/Core/PassManager.h7
-rw-r--r--include/lld/Core/Reader.h19
-rw-r--r--include/lld/Core/Reference.h2
-rw-r--r--include/lld/Core/Resolver.h2
-rw-r--r--include/lld/Core/SharedLibraryFile.h16
-rw-r--r--include/lld/Core/Simple.h87
-rw-r--r--include/lld/Core/SymbolTable.h2
-rw-r--r--include/lld/Core/TODO.txt2
-rw-r--r--include/lld/Core/Writer.h12
-rw-r--r--include/lld/Driver/Driver.h48
-rw-r--r--include/lld/Driver/WinLinkModuleDef.h200
-rw-r--r--include/lld/Makefile44
-rw-r--r--include/lld/ReaderWriter/ELFLinkingContext.h268
-rw-r--r--include/lld/ReaderWriter/ELFTargets.h38
-rw-r--r--include/lld/ReaderWriter/LinkerScript.h187
-rw-r--r--include/lld/ReaderWriter/MachOLinkingContext.h76
-rw-r--r--include/lld/ReaderWriter/PECOFFLinkingContext.h463
-rw-r--r--include/lld/ReaderWriter/RelocationHelperFunctions.h57
-rw-r--r--include/lld/ReaderWriter/YamlContext.h12
-rw-r--r--lib/Config/Makefile13
-rw-r--r--lib/Core/DefinedAtom.cpp1
-rw-r--r--lib/Core/Error.cpp52
-rw-r--r--lib/Core/File.cpp8
-rw-r--r--lib/Core/LinkingContext.cpp8
-rw-r--r--lib/Core/Makefile13
-rw-r--r--lib/Core/Reader.cpp16
-rw-r--r--lib/Core/Resolver.cpp57
-rw-r--r--lib/Core/SymbolTable.cpp13
-rw-r--r--lib/Core/TODO.txt18
-rw-r--r--lib/Core/Writer.cpp4
-rw-r--r--lib/Driver/CMakeLists.txt9
-rw-r--r--lib/Driver/CoreDriver.cpp23
-rw-r--r--lib/Driver/DarwinLdDriver.cpp234
-rw-r--r--lib/Driver/DarwinLdOptions.td22
-rw-r--r--lib/Driver/Driver.cpp82
-rw-r--r--lib/Driver/GnuLdDriver.cpp263
-rw-r--r--lib/Driver/GnuLdOptions.td67
-rw-r--r--lib/Driver/Makefile38
-rw-r--r--lib/Driver/TODO.rst2
-rw-r--r--lib/Driver/UniversalDriver.cpp71
-rw-r--r--lib/Driver/WinLinkDriver.cpp1371
-rw-r--r--lib/Driver/WinLinkModuleDef.cpp295
-rw-r--r--lib/Driver/WinLinkOptions.td120
-rw-r--r--lib/Makefile16
-rw-r--r--lib/ReaderWriter/CMakeLists.txt2
-rw-r--r--lib/ReaderWriter/CoreLinkingContext.cpp135
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h50
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64ELFFile.h41
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64ELFReader.h62
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.cpp52
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h48
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp26
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h8
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp546
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h13
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp241
-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.cpp45
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h68
-rw-r--r--lib/ReaderWriter/ELF/AArch64/CMakeLists.txt2
-rw-r--r--lib/ReaderWriter/ELF/AArch64/Makefile15
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.cpp34
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.h41
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.cpp41
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.h36
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.cpp19
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.h31
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.cpp32
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.h32
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.cpp65
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.h80
-rw-r--r--lib/ReaderWriter/ELF/AMDGPU/CMakeLists.txt13
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMDynamicLibraryWriter.h49
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMELFFile.h143
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMELFReader.h62
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMELFWriters.h120
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h99
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp48
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h46
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp578
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h15
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp816
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h39
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp28
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h162
-rw-r--r--lib/ReaderWriter/ELF/ARM/Makefile15
-rw-r--r--lib/ReaderWriter/ELF/ARM/TODO.rst13
-rw-r--r--lib/ReaderWriter/ELF/Atoms.cpp297
-rw-r--r--lib/ReaderWriter/ELF/Atoms.h468
-rw-r--r--lib/ReaderWriter/ELF/CMakeLists.txt11
-rw-r--r--lib/ReaderWriter/ELF/Chunk.h73
-rw-r--r--lib/ReaderWriter/ELF/CreateELF.h118
-rw-r--r--lib/ReaderWriter/ELF/DefaultLayout.h1050
-rw-r--r--lib/ReaderWriter/ELF/DefaultTargetHandler.h38
-rw-r--r--lib/ReaderWriter/ELF/DynamicFile.cpp146
-rw-r--r--lib/ReaderWriter/ELF/DynamicFile.h92
-rw-r--r--lib/ReaderWriter/ELF/DynamicLibraryWriter.h40
-rw-r--r--lib/ReaderWriter/ELF/ELFFile.cpp829
-rw-r--r--lib/ReaderWriter/ELF/ELFFile.h946
-rw-r--r--lib/ReaderWriter/ELF/ELFLinkingContext.cpp86
-rw-r--r--lib/ReaderWriter/ELF/ELFReader.h85
-rw-r--r--lib/ReaderWriter/ELF/ExecutableWriter.h137
-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.h278
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonDynamicLibraryWriter.h62
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h127
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonELFReader.h62
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonELFWriters.h61
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonEncodings.h37
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonExecutableAtoms.h29
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonExecutableWriter.h75
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp34
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h22
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h49
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp328
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h14
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonSectionChunks.h86
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp146
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h123
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/Makefile16
-rw-r--r--lib/ReaderWriter/ELF/Layout.h59
-rw-r--r--lib/ReaderWriter/ELF/Makefile18
-rw-r--r--lib/ReaderWriter/ELF/Mips/CMakeLists.txt6
-rw-r--r--lib/ReaderWriter/ELF/Mips/Makefile15
-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.cpp7
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.h2
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h101
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h89
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp348
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsELFFile.h291
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.cpp149
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.h36
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsELFReader.h93
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp292
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsELFWriters.h122
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h154
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp97
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h22
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp687
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h14
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp783
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp264
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h174
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp171
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h224
-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.h5
-rw-r--r--lib/ReaderWriter/ELF/OutputELFWriter.cpp514
-rw-r--r--lib/ReaderWriter/ELF/OutputELFWriter.h488
-rw-r--r--lib/ReaderWriter/ELF/Reader.cpp6
-rw-r--r--lib/ReaderWriter/ELF/SectionChunks.cpp996
-rw-r--r--lib/ReaderWriter/ELF/SectionChunks.h1124
-rw-r--r--lib/ReaderWriter/ELF/SegmentChunks.cpp519
-rw-r--r--lib/ReaderWriter/ELF/SegmentChunks.h486
-rw-r--r--lib/ReaderWriter/ELF/TargetHandler.h67
-rw-r--r--lib/ReaderWriter/ELF/TargetLayout.cpp747
-rw-r--r--lib/ReaderWriter/ELF/TargetLayout.h317
-rw-r--r--lib/ReaderWriter/ELF/Writer.cpp4
-rw-r--r--lib/ReaderWriter/ELF/Writer.h7
-rw-r--r--lib/ReaderWriter/ELF/X86/Makefile15
-rw-r--r--lib/ReaderWriter/ELF/X86/X86DynamicLibraryWriter.h49
-rw-r--r--lib/ReaderWriter/ELF/X86/X86ELFFile.h41
-rw-r--r--lib/ReaderWriter/ELF/X86/X86ELFReader.h62
-rw-r--r--lib/ReaderWriter/ELF/X86/X86ExecutableWriter.h34
-rw-r--r--lib/ReaderWriter/ELF/X86/X86LinkingContext.cpp23
-rw-r--r--lib/ReaderWriter/ELF/X86/X86LinkingContext.h2
-rw-r--r--lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp17
-rw-r--r--lib/ReaderWriter/ELF/X86/X86RelocationHandler.h5
-rw-r--r--lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp29
-rw-r--r--lib/ReaderWriter/ELF/X86/X86TargetHandler.h35
-rw-r--r--lib/ReaderWriter/ELF/X86_64/CMakeLists.txt1
-rw-r--r--lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.cpp4
-rw-r--r--lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.cpp5
-rw-r--r--lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.h2
-rw-r--r--lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/Makefile15
-rw-r--r--lib/ReaderWriter/ELF/X86_64/Makefile19
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h38
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64ELFFile.h41
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64ELFReader.h62
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64ElfType.h21
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h54
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp22
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h7
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp54
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h10
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp62
-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.cpp30
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h83
-rw-r--r--lib/ReaderWriter/FileArchive.cpp106
-rw-r--r--lib/ReaderWriter/LinkerScript.cpp411
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler.h6
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler_arm.cpp52
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler_arm64.cpp23
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler_x86.cpp21
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp113
-rw-r--r--lib/ReaderWriter/MachO/Atoms.h36
-rw-r--r--lib/ReaderWriter/MachO/CMakeLists.txt1
-rw-r--r--lib/ReaderWriter/MachO/CompactUnwindPass.cpp85
-rw-r--r--lib/ReaderWriter/MachO/ExecutableAtoms.h133
-rw-r--r--lib/ReaderWriter/MachO/ExecutableAtoms.hpp136
-rw-r--r--lib/ReaderWriter/MachO/File.h40
-rw-r--r--lib/ReaderWriter/MachO/FlatNamespaceFile.h61
-rw-r--r--lib/ReaderWriter/MachO/GOTPass.cpp29
-rw-r--r--lib/ReaderWriter/MachO/LayoutPass.cpp22
-rw-r--r--lib/ReaderWriter/MachO/LayoutPass.h17
-rw-r--r--lib/ReaderWriter/MachO/MachOLinkingContext.cpp100
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFile.h59
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp52
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp75
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp202
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp302
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp6
-rw-r--r--lib/ReaderWriter/MachO/MachOPasses.h1
-rw-r--r--lib/ReaderWriter/MachO/Makefile14
-rw-r--r--lib/ReaderWriter/MachO/SectCreateFile.h93
-rw-r--r--lib/ReaderWriter/MachO/ShimPass.cpp23
-rw-r--r--lib/ReaderWriter/MachO/StubsPass.cpp70
-rw-r--r--lib/ReaderWriter/MachO/TLVPass.cpp137
-rw-r--r--lib/ReaderWriter/MachO/WriterMachO.cpp28
-rw-r--r--lib/ReaderWriter/Makefile16
-rw-r--r--lib/ReaderWriter/Native/CMakeLists.txt7
-rw-r--r--lib/ReaderWriter/Native/Makefile14
-rw-r--r--lib/ReaderWriter/Native/NativeFileFormat.h258
-rw-r--r--lib/ReaderWriter/Native/ReaderNative.cpp1013
-rw-r--r--lib/ReaderWriter/Native/WriterNative.cpp566
-rw-r--r--lib/ReaderWriter/PECOFF/Atoms.h312
-rw-r--r--lib/ReaderWriter/PECOFF/CMakeLists.txt16
-rw-r--r--lib/ReaderWriter/PECOFF/EdataPass.cpp227
-rw-r--r--lib/ReaderWriter/PECOFF/EdataPass.h99
-rw-r--r--lib/ReaderWriter/PECOFF/IdataPass.cpp345
-rw-r--r--lib/ReaderWriter/PECOFF/IdataPass.h218
-rw-r--r--lib/ReaderWriter/PECOFF/InferSubsystemPass.h66
-rw-r--r--lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.cpp48
-rw-r--r--lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h309
-rw-r--r--lib/ReaderWriter/PECOFF/LoadConfigPass.cpp75
-rw-r--r--lib/ReaderWriter/PECOFF/LoadConfigPass.h63
-rw-r--r--lib/ReaderWriter/PECOFF/Makefile14
-rw-r--r--lib/ReaderWriter/PECOFF/OrderPass.h67
-rw-r--r--lib/ReaderWriter/PECOFF/PDBPass.h43
-rw-r--r--lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp352
-rw-r--r--lib/ReaderWriter/PECOFF/Pass.cpp95
-rw-r--r--lib/ReaderWriter/PECOFF/Pass.h34
-rw-r--r--lib/ReaderWriter/PECOFF/ReaderCOFF.cpp1140
-rw-r--r--lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp389
-rw-r--r--lib/ReaderWriter/PECOFF/WriterImportLibrary.cpp118
-rw-r--r--lib/ReaderWriter/PECOFF/WriterImportLibrary.h23
-rw-r--r--lib/ReaderWriter/PECOFF/WriterPECOFF.cpp1417
-rw-r--r--lib/ReaderWriter/YAML/Makefile14
-rw-r--r--lib/ReaderWriter/YAML/ReaderWriterYAML.cpp137
-rw-r--r--test/CMakeLists.txt4
-rw-r--r--test/COFF/Inputs/armnt-executable.obj.yaml29
-rw-r--r--test/COFF/Inputs/armnt-executable.s13
-rw-r--r--test/COFF/Inputs/conflict.ll6
-rw-r--r--test/COFF/Inputs/entry-mangled.ll6
-rw-r--r--test/COFF/Inputs/export.ll18
-rw-r--r--test/COFF/Inputs/export.yaml57
-rw-r--r--test/COFF/Inputs/export2.yaml29
-rw-r--r--test/COFF/Inputs/hello32.yaml82
-rw-r--r--test/COFF/Inputs/hello64.asm24
-rw-r--r--test/COFF/Inputs/hello64.objbin0 -> 682 bytes
-rw-r--r--test/COFF/Inputs/import.yaml41
-rw-r--r--test/COFF/Inputs/imports-mangle.libbin0 -> 2114 bytes
-rw-r--r--test/COFF/Inputs/include1a.yaml33
-rw-r--r--test/COFF/Inputs/include1b.yaml33
-rw-r--r--test/COFF/Inputs/include1c.yaml29
-rwxr-xr-xtest/COFF/Inputs/library.lib (renamed from test/pecoff/Inputs/library.lib)bin1694 -> 1694 bytes
-rw-r--r--test/COFF/Inputs/lto-chkstk-chkstk.s3
-rw-r--r--test/COFF/Inputs/lto-chkstk-foo.s3
-rw-r--r--test/COFF/Inputs/lto-comdat1.ll13
-rw-r--r--test/COFF/Inputs/lto-comdat2.ll13
-rw-r--r--test/COFF/Inputs/lto-dep.ll10
-rw-r--r--test/COFF/Inputs/machine-x64.yaml29
-rw-r--r--test/COFF/Inputs/machine-x86.yaml29
-rw-r--r--[-rwxr-xr-x]test/COFF/Inputs/resource.res (renamed from test/pecoff/Inputs/resource.res)bin108 -> 108 bytes
-rw-r--r--test/COFF/Inputs/ret42.libbin0 -> 550 bytes
-rw-r--r--test/COFF/Inputs/ret42.objbin0 -> 408 bytes
-rw-r--r--test/COFF/Inputs/ret42.yaml45
-rw-r--r--test/COFF/Inputs/std32.libbin0 -> 1898 bytes
-rw-r--r--test/COFF/Inputs/std64.libbin0 -> 2068 bytes
-rw-r--r--test/COFF/Inputs/weak-external.ll6
-rw-r--r--test/COFF/Inputs/weak-external2.ll6
-rw-r--r--test/COFF/Inputs/weak-external3.ll8
-rw-r--r--test/COFF/alternatename.test61
-rw-r--r--test/COFF/ar-comdat.test38
-rw-r--r--test/COFF/armnt-blx23t.test66
-rw-r--r--test/COFF/armnt-branch24t.test59
-rw-r--r--test/COFF/armnt-entry-point.test5
-rw-r--r--test/COFF/armnt-imports.test51
-rw-r--r--test/COFF/armnt-mov32t-exec.test60
-rw-r--r--test/COFF/armnt-movt32t.test72
-rw-r--r--test/COFF/base.test57
-rw-r--r--test/COFF/baserel.test215
-rw-r--r--test/COFF/common.test102
-rw-r--r--test/COFF/conflict.test41
-rw-r--r--test/COFF/debug.test38
-rw-r--r--test/COFF/defparser.test13
-rw-r--r--test/COFF/delayimports.test41
-rw-r--r--test/COFF/delayimports32.test86
-rw-r--r--test/COFF/dll.test53
-rw-r--r--test/COFF/dllorder.test65
-rw-r--r--test/COFF/driver.test3
-rw-r--r--test/COFF/entry-inference.test50
-rw-r--r--test/COFF/entry-inference2.test39
-rw-r--r--test/COFF/entry-inference32.test35
-rw-r--r--test/COFF/entry-mangled.test35
-rw-r--r--test/COFF/entrylib.ll11
-rw-r--r--test/COFF/export-exe.test11
-rw-r--r--test/COFF/export.test82
-rw-r--r--test/COFF/export32.test133
-rw-r--r--test/COFF/failifmismatch.test11
-rw-r--r--test/COFF/filetype.test4
-rw-r--r--test/COFF/force.test43
-rw-r--r--test/COFF/heap.test25
-rw-r--r--test/COFF/hello32.test129
-rw-r--r--test/COFF/help.test3
-rw-r--r--test/COFF/icf-circular.test81
-rw-r--r--test/COFF/icf-circular2.test69
-rw-r--r--test/COFF/icf-different-align.test61
-rw-r--r--test/COFF/icf-local.test66
-rw-r--r--test/COFF/icf-simple.test71
-rw-r--r--test/COFF/imports-mangle.test66
-rw-r--r--test/COFF/imports.test35
-rw-r--r--test/COFF/include.test83
-rw-r--r--test/COFF/include2.test14
-rw-r--r--test/COFF/internal.test42
-rw-r--r--test/COFF/invalid-obj.test14
-rw-r--r--test/COFF/largeaddressaware.test21
-rw-r--r--test/COFF/libpath.test18
-rw-r--r--test/COFF/linkenv.test4
-rw-r--r--test/COFF/lldmap.test8
-rw-r--r--test/COFF/loadcfg.ll15
-rw-r--r--test/COFF/loadcfg.test59
-rw-r--r--test/COFF/loadcfg32.test42
-rw-r--r--test/COFF/locally-imported.test61
-rw-r--r--test/COFF/locally-imported32.test50
-rw-r--r--test/COFF/long-section-name.test58
-rw-r--r--test/COFF/lto-chkstk.ll17
-rw-r--r--test/COFF/lto-comdat.ll131
-rw-r--r--test/COFF/lto-linker-opts.ll11
-rw-r--r--test/COFF/lto-new-symbol.ll16
-rw-r--r--test/COFF/lto-opt-level.ll21
-rw-r--r--test/COFF/lto-parallel.ll20
-rw-r--r--test/COFF/lto.ll130
-rw-r--r--test/COFF/machine.test30
-rw-r--r--test/COFF/manifest.test61
-rw-r--r--test/COFF/merge.test53
-rw-r--r--test/COFF/nodefaultlib.test30
-rw-r--r--test/COFF/noentry.test11
-rw-r--r--test/COFF/opt.test69
-rw-r--r--test/COFF/options.test51
-rw-r--r--test/COFF/order.test15
-rw-r--r--test/COFF/out.test16
-rw-r--r--test/COFF/reloc-arm.test71
-rw-r--r--test/COFF/reloc-x64.test102
-rw-r--r--test/COFF/reloc-x86.test82
-rw-r--r--test/COFF/resource.test14
-rw-r--r--test/COFF/responsefile.test7
-rw-r--r--test/COFF/safeseh.test51
-rw-r--r--test/COFF/seh.test70
-rw-r--r--test/COFF/sort-debug.test296
-rw-r--r--test/COFF/stack.test25
-rw-r--r--test/COFF/subsystem-inference.test74
-rw-r--r--test/COFF/subsystem.test19
-rw-r--r--test/COFF/symtab.test254
-rw-r--r--test/COFF/tls.test43
-rw-r--r--test/COFF/tls32.test43
-rw-r--r--test/COFF/unwind.test198
-rw-r--r--test/COFF/version.test19
-rw-r--r--test/COFF/weak-external.test36
-rw-r--r--test/COFF/weak-external2.test30
-rw-r--r--test/COFF/weak-external3.test32
-rw-r--r--test/Driver/def-lib-search.test4
-rw-r--r--test/Driver/flavor-option.test2
-rw-r--r--test/Driver/lib-search.test10
-rw-r--r--test/Driver/so-whole-archive.test4
-rw-r--r--test/Driver/trivial-driver.test2
-rw-r--r--test/Driver/undef-basic.objtxt2
-rw-r--r--test/ELF/Inputs/abs.s4
-rw-r--r--test/ELF/Inputs/abs255.s2
-rw-r--r--test/ELF/Inputs/abs256.s2
-rw-r--r--test/ELF/Inputs/abs257.s2
-rw-r--r--test/ELF/Inputs/allow-multiple-definition.s4
-rw-r--r--test/ELF/Inputs/allow-shlib-undefined.s3
-rw-r--r--test/ELF/Inputs/archive.s5
-rw-r--r--test/ELF/Inputs/archive2.s2
-rw-r--r--test/ELF/Inputs/archive3.s2
-rw-r--r--test/ELF/Inputs/archive4.s1
-rw-r--r--test/ELF/Inputs/comdat.s3
-rw-r--r--test/ELF/Inputs/common.s3
-rw-r--r--test/ELF/Inputs/discard-merge-unnamed.obin0 -> 584 bytes
-rw-r--r--test/ELF/Inputs/dynamic-reloc.s2
-rw-r--r--test/ELF/Inputs/invalid-binding.elfbin0 -> 536 bytes
-rw-r--r--test/ELF/Inputs/invalid-data-encoding.abin0 -> 156 bytes
-rw-r--r--test/ELF/Inputs/invalid-file-class.abin0 -> 156 bytes
-rw-r--r--test/ELF/Inputs/invalid-multiple-eh-relocs.elfbin0 -> 784 bytes
-rw-r--r--test/ELF/Inputs/invalid-section-index.elfbin0 -> 544 bytes
-rw-r--r--test/ELF/Inputs/invalid-shentsize-zero.elfbin0 -> 512 bytes
-rwxr-xr-xtest/ELF/Inputs/invalid-shstrndx.sobin0 -> 13032 bytes
-rw-r--r--test/ELF/Inputs/invalid-symtab-sh_info.elfbin0 -> 512 bytes
-rw-r--r--test/ELF/Inputs/libsearch-dyn.s3
-rw-r--r--test/ELF/Inputs/libsearch-st.s3
-rw-r--r--test/ELF/Inputs/merge.s6
-rw-r--r--test/ELF/Inputs/mips-dynamic.s4
-rw-r--r--test/ELF/Inputs/no-symtab.o (renamed from test/elf/Inputs/stripped-empty.x86_64)bin416 -> 416 bytes
-rw-r--r--test/ELF/Inputs/relocation-copy-align.s9
-rw-r--r--test/ELF/Inputs/relocation-copy.s22
-rw-r--r--test/ELF/Inputs/relocation-size-shared.s6
-rw-r--r--test/ELF/Inputs/resolution.s107
-rw-r--r--test/ELF/Inputs/shared-ppc64.s9
-rw-r--r--test/ELF/Inputs/shared.s6
-rw-r--r--test/ELF/Inputs/shared2.s6
-rw-r--r--test/ELF/Inputs/shared3.s3
-rw-r--r--test/ELF/Inputs/tls-got.s14
-rw-r--r--test/ELF/Inputs/tls-mismatch.s4
-rw-r--r--test/ELF/Inputs/tls-opt-gdie.s20
-rw-r--r--test/ELF/Inputs/tls-opt-gdiele-i686.s20
-rw-r--r--test/ELF/Inputs/tls-opt-iele-i686-nopic.s15
-rw-r--r--test/ELF/Inputs/visibility.s13
-rw-r--r--test/ELF/Inputs/whole-archive.s2
-rw-r--r--test/ELF/aarch64-abs16.s27
-rw-r--r--test/ELF/aarch64-abs32.s27
-rw-r--r--test/ELF/aarch64-call26-error.s11
-rw-r--r--test/ELF/aarch64-copy.s93
-rw-r--r--test/ELF/aarch64-data-relocs.s23
-rw-r--r--test/ELF/aarch64-fpic-abs16.s7
-rw-r--r--test/ELF/aarch64-fpic-add_abs_lo12_nc.s10
-rw-r--r--test/ELF/aarch64-fpic-adr_prel_lo21.s10
-rw-r--r--test/ELF/aarch64-fpic-adr_prel_pg_hi21.s10
-rw-r--r--test/ELF/aarch64-fpic-ldst32_abs_lo12_nc.s10
-rw-r--r--test/ELF/aarch64-fpic-ldst64_abs_lo12_nc.s10
-rw-r--r--test/ELF/aarch64-fpic-ldst8_abs_lo12_nc.s10
-rw-r--r--test/ELF/aarch64-fpic-prel16.s7
-rw-r--r--test/ELF/aarch64-fpic-prel32.s7
-rw-r--r--test/ELF/aarch64-fpic-prel64.s7
-rw-r--r--test/ELF/aarch64-hi21-error.s10
-rw-r--r--test/ELF/aarch64-jump26-error.s11
-rw-r--r--test/ELF/aarch64-lo21-error.s10
-rw-r--r--test/ELF/aarch64-prel16.s31
-rw-r--r--test/ELF/aarch64-prel32.s31
-rw-r--r--test/ELF/aarch64-relocs.s122
-rw-r--r--test/ELF/allow-multiple-definition.s29
-rw-r--r--test/ELF/allow-shlib-undefined.s25
-rw-r--r--test/ELF/archive.s36
-rw-r--r--test/ELF/as-needed.s44
-rw-r--r--test/ELF/basic-aarch64.s193
-rw-r--r--test/ELF/basic-freebsd.s25
-rw-r--r--test/ELF/basic-mips.s272
-rw-r--r--test/ELF/basic.s216
-rw-r--r--test/ELF/basic32.s163
-rw-r--r--test/ELF/basic64be.s260
-rw-r--r--test/ELF/bss.s27
-rw-r--r--test/ELF/comdat.s72
-rw-r--r--test/ELF/common.s56
-rw-r--r--test/ELF/default-output.s16
-rw-r--r--test/ELF/discard-locals.s50
-rw-r--r--test/ELF/discard-merge-locals.s24
-rw-r--r--test/ELF/discard-merge-unnamed.s16
-rw-r--r--test/ELF/discard-none.s54
-rw-r--r--test/ELF/dt_flags.s21
-rw-r--r--test/ELF/duplicate-internal.s11
-rw-r--r--test/ELF/dynamic-reloc-index.s21
-rw-r--r--test/ELF/dynamic-reloc-weak.s33
-rw-r--r--test/ELF/dynamic-reloc.s64
-rw-r--r--test/ELF/eh-align-cie.s57
-rw-r--r--test/ELF/eh-frame-merge.s58
-rw-r--r--test/ELF/eh-frame-plt.s16
-rw-r--r--test/ELF/eh-frame-rel.s7
-rw-r--r--test/ELF/eh-frame-type.test16
-rw-r--r--test/ELF/ehframe-relocation.s29
-rw-r--r--test/ELF/empty-archive.s3
-rw-r--r--test/ELF/emulation.s177
-rw-r--r--test/ELF/end-preserve.s16
-rw-r--r--test/ELF/end-update.s29
-rw-r--r--test/ELF/end.s79
-rw-r--r--test/ELF/entry.s21
-rw-r--r--test/ELF/gc-sections-eh.s19
-rw-r--r--test/ELF/gc-sections-print.s23
-rw-r--r--test/ELF/gc-sections.s102
-rw-r--r--test/ELF/global_offset_table.s5
-rw-r--r--test/ELF/gnu-hash-table.s195
-rw-r--r--test/ELF/gnu-ifunc-i386.s130
-rw-r--r--test/ELF/gnu-ifunc-nosym-i386.s29
-rw-r--r--test/ELF/gnu-ifunc-nosym.s29
-rw-r--r--test/ELF/gnu-ifunc.s126
-rw-r--r--test/ELF/gnu-unique.s24
-rw-r--r--test/ELF/gnustack.s30
-rw-r--r--test/ELF/got-aarch64.s40
-rw-r--r--test/ELF/got-i386.s56
-rw-r--r--test/ELF/got.s45
-rw-r--r--test/ELF/incompatible-ar-first.s11
-rw-r--r--test/ELF/incompatible.s58
-rw-r--r--test/ELF/init-fini.s43
-rw-r--r--test/ELF/invalid-cie-length.s9
-rw-r--r--test/ELF/invalid-cie-length2.s9
-rw-r--r--test/ELF/invalid-cie-length3.s9
-rw-r--r--test/ELF/invalid-cie-length4.s10
-rw-r--r--test/ELF/invalid-cie-length5.s10
-rw-r--r--test/ELF/invalid-cie-reference.s32
-rw-r--r--test/ELF/invalid-elf.test34
-rw-r--r--test/ELF/invalid-fde-rel.s32
-rw-r--r--test/ELF/invalid-relocations.test22
-rw-r--r--test/ELF/libsearch.s83
-rw-r--r--test/ELF/linkerscript-ouputformat.s10
-rw-r--r--test/ELF/linkerscript-outputarch.s10
-rw-r--r--test/ELF/linkerscript-sections.s119
-rw-r--r--test/ELF/linkerscript.s114
-rw-r--r--test/ELF/linkerscript2.s11
-rw-r--r--test/ELF/lit.local.cfg2
-rw-r--r--test/ELF/local-dynamic.s83
-rw-r--r--test/ELF/local-got-shared.s35
-rw-r--r--test/ELF/local-got.s48
-rw-r--r--test/ELF/local.s82
-rw-r--r--test/ELF/many-sections.s116
-rw-r--r--test/ELF/merge-invalid-size.s7
-rw-r--r--test/ELF/merge-shared.s26
-rw-r--r--test/ELF/merge-string-align.s39
-rw-r--r--test/ELF/merge-string-error.s11
-rw-r--r--test/ELF/merge-string-no-null.s8
-rw-r--r--test/ELF/merge-string.s85
-rw-r--r--test/ELF/merge-sym.s21
-rw-r--r--test/ELF/merge.s109
-rw-r--r--test/ELF/mips-call16.s40
-rw-r--r--test/ELF/mips-dynamic.s91
-rw-r--r--test/ELF/mips-dynsym-sort.s43
-rw-r--r--test/ELF/mips-elf-flags.s27
-rw-r--r--test/ELF/mips-gnu-hash.s15
-rw-r--r--test/ELF/mips-got-relocs.s99
-rw-r--r--test/ELF/mips-gprel32-relocs.s31
-rw-r--r--test/ELF/mips-hilo-gp-disp.s42
-rw-r--r--test/ELF/mips-hilo-hi-only.s28
-rw-r--r--test/ELF/mips-hilo.s53
-rw-r--r--test/ELF/mips-jalr.test47
-rw-r--r--test/ELF/mips-pc-relocs.s38
-rw-r--r--test/ELF/mips-reginfo.s26
-rw-r--r--test/ELF/mips-relocs.s42
-rw-r--r--test/ELF/new-dtags.test15
-rw-r--r--test/ELF/no-inhibit-exec.s15
-rw-r--r--test/ELF/no-obj.s8
-rw-r--r--test/ELF/no-symtab.s4
-rw-r--r--test/ELF/no-undefined.s7
-rw-r--r--test/ELF/output-section.s34
-rw-r--r--test/ELF/plt-aarch64.s205
-rw-r--r--test/ELF/plt-i686.s158
-rw-r--r--test/ELF/plt.s119
-rw-r--r--test/ELF/ppc64-addr16-error.s7
-rw-r--r--test/ELF/ppc64-rel-calls.s42
-rw-r--r--test/ELF/ppc64-relocs.s130
-rw-r--r--test/ELF/ppc64-shared-rel-toc.s27
-rw-r--r--test/ELF/ppc64-toc-restore.s62
-rw-r--r--test/ELF/ppc64-weak-undef-call-shared.s16
-rw-r--r--test/ELF/ppc64-weak-undef-call.s27
-rw-r--r--test/ELF/pre_init_fini_array.s140
-rw-r--r--test/ELF/pre_init_fini_array_missing.s30
-rw-r--r--test/ELF/progname.s20
-rw-r--r--test/ELF/program-header-layout.s98
-rw-r--r--test/ELF/relative-dynamic-reloc-ppc64.s66
-rw-r--r--test/ELF/relative-dynamic-reloc.s69
-rw-r--r--test/ELF/relocatable.s9
-rw-r--r--test/ELF/relocation-absolute.s12
-rw-r--r--test/ELF/relocation-common.s14
-rw-r--r--test/ELF/relocation-copy-align.s31
-rw-r--r--test/ELF/relocation-copy-i686.s63
-rw-r--r--test/ELF/relocation-copy.s63
-rw-r--r--test/ELF/relocation-i686.s84
-rw-r--r--test/ELF/relocation-in-merge.s7
-rw-r--r--test/ELF/relocation-local.s38
-rw-r--r--test/ELF/relocation-past-merge-end.s7
-rw-r--r--test/ELF/relocation-size-shared.s78
-rw-r--r--test/ELF/relocation-size.s123
-rw-r--r--test/ELF/relocation-undefined-weak.s27
-rw-r--r--test/ELF/relocation.s117
-rw-r--r--test/ELF/relro.s242
-rw-r--r--test/ELF/resolution.s430
-rw-r--r--test/ELF/section-align-0.test19
-rw-r--r--test/ELF/section-layout.s54
-rw-r--r--test/ELF/section-name.s37
-rw-r--r--test/ELF/section-symbol.s29
-rw-r--r--test/ELF/shared-be.s35
-rw-r--r--test/ELF/shared.s294
-rw-r--r--test/ELF/soname.s11
-rw-r--r--test/ELF/soname2.s8
-rw-r--r--test/ELF/startstop-shared.s18
-rw-r--r--test/ELF/startstop.s61
-rw-r--r--test/ELF/string-table.s80
-rw-r--r--test/ELF/strip-all.s25
-rw-r--r--test/ELF/symbols.s182
-rw-r--r--test/ELF/sysroot.s36
-rw-r--r--test/ELF/tls-align.s21
-rw-r--r--test/ELF/tls-dynamic-i686.s92
-rw-r--r--test/ELF/tls-dynamic.s81
-rw-r--r--test/ELF/tls-error.s12
-rw-r--r--test/ELF/tls-got.s58
-rw-r--r--test/ELF/tls-i686.s69
-rw-r--r--test/ELF/tls-mismatch.s9
-rw-r--r--test/ELF/tls-opt-gdie.s55
-rw-r--r--test/ELF/tls-opt-gdiele-i686.s59
-rw-r--r--test/ELF/tls-opt-i686.s69
-rw-r--r--test/ELF/tls-opt-iele-i686-nopic.s159
-rw-r--r--test/ELF/tls-opt-local.s52
-rw-r--r--test/ELF/tls-opt.s93
-rw-r--r--test/ELF/tls-static.s13
-rw-r--r--test/ELF/tls.s170
-rw-r--r--test/ELF/undef-start.s4
-rw-r--r--test/ELF/undef.s8
-rw-r--r--test/ELF/undefined-opt.s55
-rw-r--r--test/ELF/valid-cie-length-dw64.s13
-rw-r--r--test/ELF/visibility.s108
-rw-r--r--test/ELF/whole-archive.s34
-rw-r--r--test/ELF/writable-merge.s6
-rw-r--r--test/ELF/x86-64-reloc-32-error.s8
-rw-r--r--test/ELF/x86-64-reloc-32S-error.s7
-rw-r--r--test/LinkerScript/phdrs-sections.test29
-rw-r--r--test/LinkerScript/sections.test6
-rw-r--r--test/Makefile71
-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/archive-basic.objtxt23
-rw-r--r--test/core/archive-chain.objtxt49
-rw-r--r--test/core/archive-tentdef-search.objtxt16
-rw-r--r--test/core/associates.objtxt11
-rw-r--r--test/core/auto-hide-coalesce.objtxt23
-rw-r--r--test/core/code-model-attributes.objtxt27
-rw-r--r--test/core/constants-coalesce.objtxt22
-rw-r--r--test/core/cstring-coalesce.objtxt12
-rw-r--r--test/core/custom-section-coalesce.objtxt32
-rw-r--r--test/core/dead-strip-attributes.objtxt11
-rw-r--r--test/core/dead-strip-basic.objtxt21
-rw-r--r--test/core/dead-strip-globals.objtxt21
-rw-r--r--test/core/error-duplicate-absolutes.objtxt7
-rw-r--r--test/core/gnulinkonce-rearrange-resolve.objtxt28
-rw-r--r--test/core/gnulinkonce-remaining-undef.objtxt41
-rw-r--r--test/core/gnulinkonce-resolve.objtxt28
-rw-r--r--test/core/gnulinkonce-simple.objtxt6
-rw-r--r--test/core/inline-coalesce.objtxt14
-rw-r--r--test/core/multiple-def-error.objtxt7
-rw-r--r--test/core/sectiongroup-deadstrip.objtxt6
-rw-r--r--test/core/sectiongroup-gnulinkonce-error.objtxt28
-rw-r--r--test/core/sectiongroup-rearrange-resolve.objtxt28
-rw-r--r--test/core/sectiongroup-remaining-undef.objtxt40
-rw-r--r--test/core/sectiongroup-resolve.objtxt26
-rw-r--r--test/core/sectiongroup-simple.objtxt4
-rw-r--r--test/core/shared-library-coalesce.objtxt31
-rw-r--r--test/core/tent-merge.objtxt8
-rw-r--r--test/core/undef-coalesce-error.objtxt20
-rw-r--r--test/core/undef-coalesce.objtxt18
-rw-r--r--test/core/undef-fallback.objtxt10
-rw-r--r--test/core/undef-weak-coalesce.objtxt22
-rw-r--r--test/core/weak-coalesce.objtxt18
-rw-r--r--test/darwin/Inputs/native-and-mach-o.objtxt17
-rw-r--r--test/darwin/Inputs/native-and-mach-o2.objtxt19
-rw-r--r--test/darwin/native-and-mach-o.objtxt44
-rw-r--r--test/elf/AArch64/defsym.test22
-rw-r--r--test/elf/AArch64/dontignorezerosize-sections.test9
-rw-r--r--test/elf/AArch64/dynlib-nointerp-section.test5
-rw-r--r--test/elf/AArch64/initfini.test23
-rw-r--r--test/elf/AArch64/rel-abs32-overflow.test53
-rw-r--r--test/elf/AArch64/rel-abs32.test59
-rw-r--r--test/elf/AArch64/rel-abs64.test59
-rw-r--r--test/elf/AArch64/rel-bad.test44
-rw-r--r--test/elf/ARM/arm-symbols.test52
-rw-r--r--test/elf/ARM/defsym.test51
-rw-r--r--test/elf/ARM/entry-point.test77
-rw-r--r--test/elf/ARM/missing-symbol.test39
-rw-r--r--test/elf/ARM/rel-abs32.test59
-rw-r--r--test/elf/ARM/rel-arm-call.test60
-rw-r--r--test/elf/ARM/rel-arm-jump24-veneer-b.test101
-rw-r--r--test/elf/ARM/rel-arm-jump24-veneer-bl.test100
-rw-r--r--test/elf/ARM/rel-arm-jump24.test58
-rw-r--r--test/elf/ARM/rel-arm-mov.test64
-rw-r--r--test/elf/ARM/rel-arm-prel31.test47
-rw-r--r--test/elf/ARM/rel-arm-thm-interwork.test123
-rw-r--r--test/elf/ARM/rel-rel32.test57
-rw-r--r--test/elf/ARM/rel-thm-call.test61
-rw-r--r--test/elf/ARM/rel-thm-jump11.test141
-rw-r--r--test/elf/ARM/rel-thm-jump24-veneer.test100
-rw-r--r--test/elf/ARM/rel-thm-jump24.test59
-rw-r--r--test/elf/ARM/rel-thm-mov.test70
-rw-r--r--test/elf/ARM/rel-tls-ie32.test109
-rw-r--r--test/elf/ARM/rel-tls-le32.test61
-rw-r--r--test/elf/ARM/thm-symbols.test52
-rw-r--r--test/elf/ARM/undef-lazy-symbol.test135
-rw-r--r--test/elf/Hexagon/dynlib-data.test9
-rw-r--r--test/elf/Hexagon/dynlib-gotoff.test128
-rw-r--r--test/elf/Hexagon/dynlib-hash.test9
-rw-r--r--test/elf/Hexagon/dynlib-rela.test9
-rw-r--r--test/elf/Hexagon/dynlib-syms.test7
-rw-r--r--test/elf/Hexagon/dynlib.test36
-rw-r--r--test/elf/Hexagon/hexagon-got-plt-order.test5
-rw-r--r--test/elf/Hexagon/hexagon-plt-setup.test12
-rw-r--r--test/elf/Hexagon/maxalignment.test8
-rw-r--r--test/elf/Hexagon/rela-order.test9
-rw-r--r--test/elf/Hexagon/sda-base.test4
-rw-r--r--test/elf/Hexagon/zerofillquick-sdata.test18
-rw-r--r--test/elf/Inputs/consecutive-weak-defs.o.yaml66
-rw-r--r--test/elf/Inputs/init_array.x86-64bin3440 -> 0 bytes
-rw-r--r--test/elf/Inputs/main-with-global-def.o.yaml56
-rw-r--r--test/elf/Inputs/undef2-so.o.yaml50
-rw-r--r--test/elf/Mips/base-address-64.test78
-rw-r--r--test/elf/Mips/base-address.test109
-rw-r--r--test/elf/Mips/ctors-order.test163
-rw-r--r--test/elf/Mips/dt-textrel-64.test74
-rw-r--r--test/elf/Mips/dt-textrel.test74
-rw-r--r--test/elf/Mips/dynlib-dynamic.test110
-rw-r--r--test/elf/Mips/dynlib-dynsym-micro.test208
-rw-r--r--test/elf/Mips/dynlib-dynsym.test202
-rw-r--r--test/elf/Mips/dynlib-fileheader-64.test72
-rw-r--r--test/elf/Mips/dynlib-fileheader-micro-64.test75
-rw-r--r--test/elf/Mips/dynlib-fileheader-micro.test82
-rw-r--r--test/elf/Mips/dynlib-fileheader.test80
-rw-r--r--test/elf/Mips/dynsym-table-1.test127
-rw-r--r--test/elf/Mips/dynsym-table-2.test105
-rw-r--r--test/elf/Mips/e-flags-merge-1-64.test30
-rw-r--r--test/elf/Mips/e-flags-merge-1.test56
-rw-r--r--test/elf/Mips/e-flags-merge-10.test43
-rw-r--r--test/elf/Mips/e-flags-merge-11.test43
-rw-r--r--test/elf/Mips/e-flags-merge-2-64.test33
-rw-r--r--test/elf/Mips/e-flags-merge-2.test35
-rw-r--r--test/elf/Mips/e-flags-merge-3-64.test130
-rw-r--r--test/elf/Mips/e-flags-merge-3.test134
-rw-r--r--test/elf/Mips/e-flags-merge-4-64.test64
-rw-r--r--test/elf/Mips/e-flags-merge-4.test65
-rw-r--r--test/elf/Mips/e-flags-merge-5-64.test42
-rw-r--r--test/elf/Mips/e-flags-merge-5.test42
-rw-r--r--test/elf/Mips/e-flags-merge-6-64.test79
-rw-r--r--test/elf/Mips/e-flags-merge-6.test80
-rw-r--r--test/elf/Mips/e-flags-merge-7-64.test42
-rw-r--r--test/elf/Mips/e-flags-merge-7.test42
-rw-r--r--test/elf/Mips/e-flags-merge-8.test65
-rw-r--r--test/elf/Mips/e-flags-merge-9.test43
-rw-r--r--test/elf/Mips/entry-name.test26
-rw-r--r--test/elf/Mips/exe-dynamic.test108
-rw-r--r--test/elf/Mips/exe-dynsym-micro.test94
-rw-r--r--test/elf/Mips/exe-dynsym.test91
-rw-r--r--test/elf/Mips/exe-fileheader-64.test66
-rw-r--r--test/elf/Mips/exe-fileheader-micro-64.test68
-rw-r--r--test/elf/Mips/exe-fileheader-micro.test69
-rw-r--r--test/elf/Mips/exe-fileheader.test105
-rw-r--r--test/elf/Mips/exe-got-micro.test115
-rw-r--r--test/elf/Mips/exe-got.test116
-rw-r--r--test/elf/Mips/got-page-32.test203
-rw-r--r--test/elf/Mips/got-page-64.test203
-rw-r--r--test/elf/Mips/got16-2.test73
-rw-r--r--test/elf/Mips/got16-micro.test165
-rw-r--r--test/elf/Mips/got16.test196
-rw-r--r--test/elf/Mips/gotsym.test43
-rw-r--r--test/elf/Mips/gp-sym-1-micro.test88
-rw-r--r--test/elf/Mips/gp-sym-1.test86
-rw-r--r--test/elf/Mips/gp-sym-2.test103
-rw-r--r--test/elf/Mips/hilo16-1.test44
-rw-r--r--test/elf/Mips/hilo16-2.test68
-rw-r--r--test/elf/Mips/hilo16-3.test45
-rw-r--r--test/elf/Mips/hilo16-4.test93
-rw-r--r--test/elf/Mips/hilo16-5.test103
-rw-r--r--test/elf/Mips/hilo16-8-micro.test81
-rw-r--r--test/elf/Mips/hilo16-9-micro.test68
-rw-r--r--test/elf/Mips/initfini-micro.test45
-rw-r--r--test/elf/Mips/interpreter-64.test26
-rw-r--r--test/elf/Mips/interpreter.test26
-rw-r--r--test/elf/Mips/invalid-reginfo.test28
-rw-r--r--test/elf/Mips/jalx-align-err.test46
-rw-r--r--test/elf/Mips/jump-fix-err.test45
-rw-r--r--test/elf/Mips/la25-stub-micro.test140
-rw-r--r--test/elf/Mips/la25-stub.test133
-rw-r--r--test/elf/Mips/mips-options-gp0.test78
-rw-r--r--test/elf/Mips/n64-rel-chain.test134
-rw-r--r--test/elf/Mips/opt-emulation.test41
-rw-r--r--test/elf/Mips/pc23-range.test56
-rw-r--r--test/elf/Mips/plt-entry-mixed-1.test114
-rw-r--r--test/elf/Mips/plt-entry-mixed-2.test93
-rw-r--r--test/elf/Mips/plt-entry-mixed-3.test98
-rw-r--r--test/elf/Mips/plt-entry-mixed-4.test85
-rw-r--r--test/elf/Mips/plt-entry-r6.test109
-rw-r--r--test/elf/Mips/plt-header-micro.test108
-rw-r--r--test/elf/Mips/plt-header-mixed.test105
-rw-r--r--test/elf/Mips/plt-header.test99
-rw-r--r--test/elf/Mips/r26-1-micro.test131
-rw-r--r--test/elf/Mips/r26-1.test132
-rw-r--r--test/elf/Mips/r26-2-micro.test88
-rw-r--r--test/elf/Mips/r26-2.test82
-rw-r--r--test/elf/Mips/rel-32.test59
-rw-r--r--test/elf/Mips/rel-64.test61
-rw-r--r--test/elf/Mips/rel-copy-micro.test159
-rw-r--r--test/elf/Mips/rel-copy-pc.test113
-rw-r--r--test/elf/Mips/rel-copy.test177
-rw-r--r--test/elf/Mips/rel-dynamic-01-micro.test201
-rw-r--r--test/elf/Mips/rel-dynamic-01.test237
-rw-r--r--test/elf/Mips/rel-dynamic-02.test82
-rw-r--r--test/elf/Mips/rel-dynamic-03-micro.test133
-rw-r--r--test/elf/Mips/rel-dynamic-03.test129
-rw-r--r--test/elf/Mips/rel-dynamic-04-micro.test211
-rw-r--r--test/elf/Mips/rel-dynamic-04.test206
-rw-r--r--test/elf/Mips/rel-dynamic-05-micro.test192
-rw-r--r--test/elf/Mips/rel-dynamic-05.test188
-rw-r--r--test/elf/Mips/rel-dynamic-06-64.test101
-rw-r--r--test/elf/Mips/rel-dynamic-06.test103
-rw-r--r--test/elf/Mips/rel-dynamic-07-64.test261
-rw-r--r--test/elf/Mips/rel-dynamic-07.test276
-rw-r--r--test/elf/Mips/rel-dynamic-08-64.test233
-rw-r--r--test/elf/Mips/rel-dynamic-08-micro.test236
-rw-r--r--test/elf/Mips/rel-dynamic-08.test233
-rw-r--r--test/elf/Mips/rel-dynamic-09-micro.test109
-rw-r--r--test/elf/Mips/rel-dynamic-09.test107
-rw-r--r--test/elf/Mips/rel-dynamic-10-micro.test166
-rw-r--r--test/elf/Mips/rel-dynamic-10.test160
-rw-r--r--test/elf/Mips/rel-dynamic-11.test110
-rw-r--r--test/elf/Mips/rel-dynamic-12.test213
-rw-r--r--test/elf/Mips/rel-gprel16.test104
-rw-r--r--test/elf/Mips/rel-gprel32-64.test70
-rw-r--r--test/elf/Mips/rel-gprel32.test84
-rw-r--r--test/elf/Mips/rel-pc-hilo.test70
-rw-r--r--test/elf/Mips/rel-pc18-s3.test54
-rw-r--r--test/elf/Mips/rel-pc19-s2.test54
-rw-r--r--test/elf/Mips/rel-pc21-s2.test54
-rw-r--r--test/elf/Mips/rel-pc26-s2.test54
-rw-r--r--test/elf/Mips/rel-pc32.test59
-rw-r--r--test/elf/Mips/rel-pc7-10-16-23.test86
-rw-r--r--test/elf/Mips/rel-sub.test61
-rw-r--r--test/elf/Mips/st-other.test90
-rw-r--r--test/elf/Mips/tls-1-micro.test65
-rw-r--r--test/elf/Mips/tls-1.test63
-rw-r--r--test/elf/Mips/tls-2-64.test69
-rw-r--r--test/elf/Mips/tls-2-micro.test70
-rw-r--r--test/elf/Mips/tls-2.test69
-rw-r--r--test/elf/Mips/tls-3-micro.test183
-rw-r--r--test/elf/Mips/tls-3.test180
-rw-r--r--test/elf/Mips/tls-4-micro.test126
-rw-r--r--test/elf/Mips/tls-4.test123
-rw-r--r--test/elf/Mips/tls-5-64.test71
-rw-r--r--test/elf/Mips/tls-5-micro.test70
-rw-r--r--test/elf/Mips/tls-5.test69
-rw-r--r--test/elf/X86_64/ExampleTarget/triple.test32
-rw-r--r--test/elf/X86_64/Inputs/generaltls-so.o.yaml68
-rw-r--r--test/elf/X86_64/alignoffset.test119
-rw-r--r--test/elf/X86_64/debug.test57
-rw-r--r--test/elf/X86_64/defsym.test22
-rw-r--r--test/elf/X86_64/demangle.test12
-rw-r--r--test/elf/X86_64/dontignorezerosize-sections.test9
-rw-r--r--test/elf/X86_64/dynamicvars.test124
-rw-r--r--test/elf/X86_64/dynlib-nointerp-section.test4
-rw-r--r--test/elf/X86_64/dynlib-search.test6
-rw-r--r--test/elf/X86_64/dynsym-weak.test118
-rw-r--r--test/elf/X86_64/extern-tls.test16
-rw-r--r--test/elf/X86_64/general-dynamic-tls.test129
-rw-r--r--test/elf/X86_64/imagebase.test94
-rw-r--r--test/elf/X86_64/initfini-order.test10
-rw-r--r--test/elf/X86_64/initfini.test23
-rw-r--r--test/elf/X86_64/largebss.test20
-rw-r--r--test/elf/X86_64/layoutpass-order.test14
-rw-r--r--test/elf/X86_64/maxpagesize.test113
-rw-r--r--test/elf/X86_64/mergesimilarstrings.test47
-rw-r--r--test/elf/X86_64/multi-weak-layout.test52
-rw-r--r--test/elf/X86_64/multi-weak-override.test16
-rw-r--r--test/elf/X86_64/multi-weak-syms-order.test13
-rw-r--r--test/elf/X86_64/nmagic.test91
-rw-r--r--test/elf/X86_64/noalignsegments.test95
-rw-r--r--test/elf/X86_64/note-sections-ro_plus_rw.test42
-rw-r--r--test/elf/X86_64/note-sections.test23
-rw-r--r--test/elf/X86_64/omagic.test237
-rw-r--r--test/elf/X86_64/outputsegments.test189
-rw-r--r--test/elf/X86_64/reloc_r_x86_64_16.test60
-rw-r--r--test/elf/X86_64/reloc_r_x86_64_pc16.test61
-rw-r--r--test/elf/X86_64/reloc_r_x86_64_pc64.test61
-rw-r--r--test/elf/X86_64/rodata.test9
-rw-r--r--test/elf/X86_64/sectionchoice.test7
-rw-r--r--test/elf/X86_64/sectionmap.test22
-rw-r--r--test/elf/X86_64/startGroupEndGroup.test48
-rw-r--r--test/elf/X86_64/startGroupEndGroupWithDynlib.test10
-rw-r--r--test/elf/X86_64/staticlib-search.test6
-rw-r--r--test/elf/X86_64/undef.test18
-rw-r--r--test/elf/X86_64/underscore-end.test81
-rw-r--r--test/elf/X86_64/weak-override.test45
-rw-r--r--test/elf/X86_64/weak-zero-sized.test26
-rw-r--r--test/elf/X86_64/weaksym.test78
-rw-r--r--test/elf/X86_64/yamlinput.test166
-rw-r--r--test/elf/abs-dup.objtxt19
-rw-r--r--test/elf/abs.test19
-rw-r--r--test/elf/allowduplicates.objtxt51
-rw-r--r--test/elf/archive-elf-forceload.test43
-rw-r--r--test/elf/archive-elf.test38
-rw-r--r--test/elf/as-needed.test15
-rw-r--r--test/elf/branch.test34
-rw-r--r--test/elf/check.test39
-rw-r--r--test/elf/checkrodata.test9
-rw-r--r--test/elf/common.test10
-rw-r--r--test/elf/consecutive-weak-sym-defs.test81
-rw-r--r--test/elf/defsym.objtxt28
-rw-r--r--test/elf/dynamic-segorder.test17
-rw-r--r--test/elf/dynamic-undef.test34
-rw-r--r--test/elf/dynamic.test80
-rw-r--r--test/elf/eh_frame_hdr.test30
-rw-r--r--test/elf/entry.objtxt58
-rw-r--r--test/elf/export-dynamic.test99
-rw-r--r--test/elf/filenotfound.test3
-rw-r--r--test/elf/gnulinkonce/gnulinkonce-report-discarded-reference.test147
-rw-r--r--test/elf/gnulinkonce/gnulinkonce-report-undef.test129
-rw-r--r--test/elf/gnulinkonce/gnulinkonce.test151
-rw-r--r--test/elf/gotpcrel.test21
-rw-r--r--test/elf/gottpoff.test120
-rw-r--r--test/elf/group-cmd-search.test134
-rw-r--r--test/elf/hexagon-quickdata-sort.test12
-rw-r--r--test/elf/hexagon-quickdata-sortcommon.test16
-rw-r--r--test/elf/ifunc.test69
-rw-r--r--test/elf/ignore-unknownoption.test5
-rw-r--r--test/elf/init_array-order.test67
-rw-r--r--test/elf/init_array.test6
-rw-r--r--test/elf/initfini-options.test-1.test33
-rw-r--r--test/elf/initfini-options.test-2.test47
-rw-r--r--test/elf/initfini-options.test-3.test53
-rw-r--r--test/elf/librarynotfound.test5
-rw-r--r--test/elf/linker-as-ld.test16
-rw-r--r--test/elf/linkerscript/Inputs/prog1.o.yaml88
-rw-r--r--test/elf/linkerscript/Inputs/prog2.o.yaml89
-rw-r--r--test/elf/linkerscript/Inputs/prog3.o.yaml52
-rw-r--r--test/elf/linkerscript/Inputs/simple.o.yaml52
-rw-r--r--test/elf/linkerscript/externs.objtxt21
-rw-r--r--test/elf/linkerscript/invalid-script-cli-1.test10
-rw-r--r--test/elf/linkerscript/invalid-script-cli-2.test6
-rw-r--r--test/elf/linkerscript/invalid.test5
-rw-r--r--test/elf/linkerscript/sections-order.test97
-rw-r--r--test/elf/linkerscript/sections-with-wildcards.test88
-rw-r--r--test/elf/linkerscript/symbol-definition.test54
-rw-r--r--test/elf/linkerscript/valid-script-cli.objtxt23
-rw-r--r--test/elf/loginputfiles.test28
-rw-r--r--test/elf/mergeatoms.test6
-rw-r--r--test/elf/mergeconstants.test20
-rw-r--r--test/elf/mergeglobalatoms.test11
-rw-r--r--test/elf/note.test49
-rw-r--r--test/elf/options/dynamic-linker.test17
-rw-r--r--test/elf/phdr.test99
-rw-r--r--test/elf/quickdata.test15
-rw-r--r--test/elf/reloc.test38
-rw-r--r--test/elf/responsefile.test6
-rw-r--r--test/elf/rodata.test5
-rw-r--r--test/elf/rosegment.test26
-rw-r--r--test/elf/sectionGroups/sectiongroup-new-members.test153
-rw-r--r--test/elf/sectionGroups/sectiongroup-simple.test146
-rw-r--r--test/elf/sectionGroups/sectiongroup-undef-member-other.test158
-rw-r--r--test/elf/sectionGroups/sectiongroup-undef-member.test144
-rw-r--r--test/elf/sectionGroups/sectiongroup-with-globalsymbols.test253
-rw-r--r--test/elf/sectionGroups/sectiongroup-with-undef-external-reference.test239
-rw-r--r--test/elf/sectionGroups/sectiongroup-with-undef-signature.test222
-rw-r--r--test/elf/sections.test142
-rw-r--r--test/elf/sh_addralign.test38
-rw-r--r--test/elf/soname.test6
-rw-r--r--test/elf/strip-all.test107
-rw-r--r--test/elf/stripped-empty.test4
-rw-r--r--test/elf/symbols.test33
-rw-r--r--test/elf/tls.test43
-rw-r--r--test/elf/tlsAddr.test7
-rw-r--r--test/elf/undef-from-dso-to-main.test52
-rw-r--r--test/elf/undef-from-main-dso.test43
-rw-r--r--test/elf/weaksym.test7
-rw-r--r--test/elf/wrap.test279
-rw-r--r--test/elf/x86-64-dynamic-relocs.test26
-rw-r--r--test/elf/x86-64-dynamic.test79
-rw-r--r--test/elf/x86.test38
-rw-r--r--test/elf/x86_64-kinds.test23
-rw-r--r--test/lit.cfg87
-rw-r--r--test/mach-o/Inputs/PIE.yaml6
-rw-r--r--test/mach-o/Inputs/arm-interworking.yaml83
-rw-r--r--test/mach-o/Inputs/arm-shims.yaml60
-rw-r--r--test/mach-o/Inputs/cstring-sections.yaml25
-rw-r--r--test/mach-o/Inputs/got-order.yaml53
-rw-r--r--test/mach-o/Inputs/got-order2.yaml11
-rw-r--r--test/mach-o/Inputs/hello-world-arm64.yaml8
-rw-r--r--test/mach-o/Inputs/hello-world-armv6.yaml7
-rw-r--r--test/mach-o/Inputs/hello-world-armv7.yaml7
-rw-r--r--test/mach-o/Inputs/hello-world-x86.yaml7
-rw-r--r--test/mach-o/Inputs/hello-world-x86_64.yaml8
-rw-r--r--test/mach-o/Inputs/hw.raw_bytes1
-rw-r--r--test/mach-o/Inputs/interposing-section.yaml6
-rw-r--r--test/mach-o/Inputs/lazy-bind-x86_64-2.yaml8
-rw-r--r--test/mach-o/Inputs/lazy-bind-x86_64-3.yaml8
-rw-r--r--test/mach-o/Inputs/lazy-bind-x86_64.yaml8
-rw-r--r--test/mach-o/Inputs/linker-as-ld.yaml6
-rw-r--r--test/mach-o/Inputs/re-exported-dylib-ordinal.yaml21
-rw-r--r--test/mach-o/Inputs/re-exported-dylib-ordinal2.yaml18
-rw-r--r--test/mach-o/Inputs/re-exported-dylib-ordinal3.yaml19
-rw-r--r--test/mach-o/Inputs/unwind-info-simple-arm64.yaml13
-rw-r--r--test/mach-o/Inputs/use-simple-dylib.yaml58
-rw-r--r--test/mach-o/Inputs/write-final-sections.yaml20
-rw-r--r--test/mach-o/Inputs/wrong-arch-error.yaml24
-rw-r--r--test/mach-o/PIE.yaml16
-rw-r--r--test/mach-o/align_text.yaml10
-rw-r--r--test/mach-o/arm-interworking-movw.yaml20
-rw-r--r--test/mach-o/arm-interworking.yaml160
-rw-r--r--test/mach-o/arm-shims.yaml83
-rw-r--r--test/mach-o/arm-subsections-via-symbols.yaml4
-rw-r--r--test/mach-o/arm64-reloc-negDelta32-fixup.yaml124
-rw-r--r--test/mach-o/arm64-relocs-errors-delta64-offset.yaml65
-rw-r--r--test/mach-o/cstring-sections.yaml26
-rw-r--r--test/mach-o/data-only-dylib.yaml2
-rw-r--r--test/mach-o/demangle.yaml2
-rw-r--r--test/mach-o/dylib-exports.yaml41
-rw-r--r--test/mach-o/executable-exports.yaml46
-rw-r--r--test/mach-o/exported_symbols_list-dylib.yaml2
-rw-r--r--test/mach-o/exported_symbols_list-obj.yaml2
-rw-r--r--test/mach-o/exported_symbols_list-undef.yaml2
-rw-r--r--test/mach-o/fat-archive.yaml8
-rw-r--r--test/mach-o/flat_namespace_undef_error.yaml17
-rw-r--r--test/mach-o/flat_namespace_undef_suppress.yaml17
-rw-r--r--test/mach-o/force_load-dylib.yaml4
-rw-r--r--test/mach-o/force_load-x86_64.yaml4
-rw-r--r--test/mach-o/framework-user-paths.yaml2
-rw-r--r--test/mach-o/gcc_except_tab-got-arm64.yaml53
-rw-r--r--test/mach-o/got-order.yaml85
-rw-r--r--test/mach-o/hello-world-arm64.yaml14
-rw-r--r--test/mach-o/hello-world-armv6.yaml10
-rw-r--r--test/mach-o/hello-world-armv7.yaml25
-rw-r--r--test/mach-o/hello-world-x86.yaml19
-rw-r--r--test/mach-o/hello-world-x86_64.yaml55
-rw-r--r--test/mach-o/image-base.yaml13
-rw-r--r--test/mach-o/infer-arch.yaml2
-rw-r--r--test/mach-o/interposing-section.yaml25
-rw-r--r--test/mach-o/keep_private_externs.yaml2
-rw-r--r--test/mach-o/lazy-bind-x86_64.yaml31
-rw-r--r--test/mach-o/library-order.yaml6
-rw-r--r--test/mach-o/library-rescan.yaml6
-rw-r--r--test/mach-o/linker-as-ld.yaml11
-rw-r--r--test/mach-o/objc_export_list.yaml18
-rw-r--r--test/mach-o/parse-aliases.yaml2
-rw-r--r--test/mach-o/parse-arm-relocs.yaml14
-rw-r--r--test/mach-o/parse-cfstring64.yaml8
-rw-r--r--test/mach-o/parse-data-in-code-armv7.yaml12
-rw-r--r--test/mach-o/parse-data-relocs-x86_64.yaml184
-rw-r--r--test/mach-o/parse-eh-frame-relocs-x86_64.yaml176
-rw-r--r--test/mach-o/parse-eh-frame-x86-anon.yaml50
-rw-r--r--test/mach-o/parse-eh-frame-x86-labeled.yaml58
-rw-r--r--test/mach-o/parse-function.yaml6
-rw-r--r--test/mach-o/parse-initializers64.yaml10
-rw-r--r--test/mach-o/parse-literals-error.yaml2
-rw-r--r--test/mach-o/parse-literals.yaml22
-rw-r--r--test/mach-o/parse-relocs-x86.yaml30
-rw-r--r--test/mach-o/parse-tentative-defs.yaml10
-rw-r--r--test/mach-o/parse-text-relocs-x86_64.yaml42
-rw-r--r--test/mach-o/parse-tlv-relocs-x86-64.yaml100
-rw-r--r--test/mach-o/re-exported-dylib-ordinal.yaml67
-rw-r--r--test/mach-o/rpath.yaml2
-rw-r--r--test/mach-o/run-tlv-pass-x86-64.yaml144
-rw-r--r--test/mach-o/sectalign.yaml4
-rw-r--r--test/mach-o/sectcreate.yaml12
-rw-r--r--test/mach-o/stack-size.yaml24
-rw-r--r--test/mach-o/twolevel_namespace_undef_dynamic_lookup.yaml17
-rw-r--r--test/mach-o/twolevel_namespace_undef_warning_suppress.yaml23
-rw-r--r--test/mach-o/unwind-info-simple-arm64.yaml89
-rw-r--r--test/mach-o/unwind-info-simple-x86_64.yaml23
-rw-r--r--test/mach-o/upward-dylib-load-command.yaml4
-rw-r--r--test/mach-o/use-simple-dylib.yaml62
-rw-r--r--test/mach-o/write-final-sections.yaml48
-rw-r--r--test/mach-o/wrong-arch-error.yaml25
-rw-r--r--test/old-elf/AArch64/Inputs/fn.c (renamed from test/elf/AArch64/Inputs/fn.c)0
-rw-r--r--test/old-elf/AArch64/Inputs/fn.o (renamed from test/elf/AArch64/Inputs/fn.o)bin899 -> 899 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/general-dyn-tls-0.yaml64
-rw-r--r--test/old-elf/AArch64/Inputs/initfini-option.c (renamed from test/elf/AArch64/Inputs/initfini-option.c)0
-rw-r--r--test/old-elf/AArch64/Inputs/initfini-option.o (renamed from test/elf/AArch64/Inputs/initfini-option.o)bin1552 -> 1552 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/initfini.c (renamed from test/elf/AArch64/Inputs/initfini.c)0
-rw-r--r--test/old-elf/AArch64/Inputs/initfini.o (renamed from test/elf/AArch64/Inputs/initfini.o)bin2056 -> 2056 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/initial-exec-tls-1.yaml77
-rw-r--r--test/old-elf/AArch64/Inputs/main.c (renamed from test/elf/AArch64/Inputs/main.c)0
-rw-r--r--test/old-elf/AArch64/Inputs/main.o (renamed from test/elf/AArch64/Inputs/main.o)bin1064 -> 1064 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/no-interp-section.c (renamed from test/elf/AArch64/Inputs/no-interp-section.c)0
-rw-r--r--test/old-elf/AArch64/Inputs/no-interp-section.o (renamed from test/elf/AArch64/Inputs/no-interp-section.o)bin903 -> 903 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/zerosizedsection.o (renamed from test/elf/AArch64/Inputs/zerosizedsection.o)bin816 -> 816 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/zerosizedsection.s (renamed from test/elf/AArch64/Inputs/zerosizedsection.s)0
-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/AMDGPU/hsa.test53
-rw-r--r--test/old-elf/ARM/Inputs/fn.c1
-rwxr-xr-xtest/old-elf/ARM/Inputs/libfn.sobin0 -> 4972 bytes
-rwxr-xr-xtest/old-elf/ARM/Inputs/libobj.sobin0 -> 5067 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.c (renamed from test/elf/Hexagon/Inputs/dynobj-data.c)0
-rw-r--r--test/old-elf/Hexagon/Inputs/dynobj-data.o (renamed from test/elf/Hexagon/Inputs/dynobj-data.o)bin916 -> 916 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/dynobj.c (renamed from test/elf/Hexagon/Inputs/dynobj.c)0
-rw-r--r--test/old-elf/Hexagon/Inputs/dynobj.o (renamed from test/elf/Hexagon/Inputs/dynobj.o)bin1288 -> 1288 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/got-plt-order.c (renamed from test/elf/Hexagon/Inputs/got-plt-order.c)0
-rw-r--r--test/old-elf/Hexagon/Inputs/got-plt-order.o (renamed from test/elf/Hexagon/Inputs/got-plt-order.o)bin964 -> 964 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/libMaxAlignment.a (renamed from test/elf/Hexagon/Inputs/libMaxAlignment.a)bin1010 -> 1010 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/sda-base.o (renamed from test/elf/Hexagon/Inputs/sda-base.o)bin1469 -> 1469 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/sdata1.c (renamed from test/elf/Hexagon/Inputs/sdata1.c)0
-rw-r--r--test/old-elf/Hexagon/Inputs/sdata1.o (renamed from test/elf/Hexagon/Inputs/sdata1.o)bin684 -> 684 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/sdata2.c (renamed from test/elf/Hexagon/Inputs/sdata2.c)0
-rw-r--r--test/old-elf/Hexagon/Inputs/sdata2.o (renamed from test/elf/Hexagon/Inputs/sdata2.o)bin829 -> 829 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/use-shared.hexagon (renamed from test/elf/Hexagon/Inputs/use-shared.hexagon)bin872 -> 872 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.i386 (renamed from test/elf/Inputs/abs-test.i386)bin504 -> 504 bytes
-rw-r--r--test/old-elf/Inputs/allowduplicates.objtxt12
-rw-r--r--test/old-elf/Inputs/bar.o.x86-64 (renamed from test/elf/Inputs/bar.o.x86-64)bin1240 -> 1240 bytes
-rw-r--r--test/old-elf/Inputs/branch-test.hexagon (renamed from test/elf/Inputs/branch-test.hexagon)bin700 -> 700 bytes
-rw-r--r--test/old-elf/Inputs/branch-test.ppc (renamed from test/elf/Inputs/branch-test.ppc)bin852 -> 852 bytes
-rw-r--r--test/old-elf/Inputs/consecutive-weak-defs.o.yaml65
-rw-r--r--test/old-elf/Inputs/constants-merge.x86-64 (renamed from test/elf/Inputs/constants-merge.x86-64)bin1232 -> 1232 bytes
-rw-r--r--test/old-elf/Inputs/constdata.x86-64 (renamed from test/elf/Inputs/constdata.x86-64)bin1688 -> 1688 bytes
-rw-r--r--test/old-elf/Inputs/foo.o.x86-64 (renamed from test/elf/Inputs/foo.o.x86-64)bin1240 -> 1240 bytes
-rw-r--r--test/old-elf/Inputs/globalconst.c (renamed from test/elf/Inputs/globalconst.c)0
-rw-r--r--test/old-elf/Inputs/globalconst.o.x86-64 (renamed from test/elf/Inputs/globalconst.o.x86-64)bin1072 -> 1072 bytes
-rw-r--r--test/old-elf/Inputs/gotpcrel.S (renamed from test/elf/Inputs/gotpcrel.S)0
-rw-r--r--test/old-elf/Inputs/gotpcrel.x86-64 (renamed from test/elf/Inputs/gotpcrel.x86-64)bin904 -> 904 bytes
-rw-r--r--test/old-elf/Inputs/group-cmd-search-1.ls (renamed from test/elf/Inputs/group-cmd-search-1.ls)0
-rw-r--r--test/old-elf/Inputs/group-cmd-search-2.ls (renamed from test/elf/Inputs/group-cmd-search-2.ls)0
-rw-r--r--test/old-elf/Inputs/group-cmd-search-3.ls (renamed from test/elf/Inputs/group-cmd-search-3.ls)0
-rw-r--r--test/old-elf/Inputs/ifunc.S (renamed from test/elf/Inputs/ifunc.S)0
-rw-r--r--test/old-elf/Inputs/ifunc.cpp (renamed from test/elf/Inputs/ifunc.cpp)0
-rw-r--r--test/old-elf/Inputs/ifunc.cpp.x86-64 (renamed from test/elf/Inputs/ifunc.cpp.x86-64)bin1224 -> 1224 bytes
-rw-r--r--test/old-elf/Inputs/ifunc.x86-64 (renamed from test/elf/Inputs/ifunc.x86-64)bin912 -> 912 bytes
-rw-r--r--test/old-elf/Inputs/libfnarchive.a (renamed from test/elf/Inputs/libfnarchive.a)bin2656 -> 2656 bytes
-rw-r--r--test/old-elf/Inputs/libifunc.x86-64.so (renamed from test/elf/Inputs/libifunc.x86-64.so)bin2512 -> 2512 bytes
-rw-r--r--test/old-elf/Inputs/libundef.so (renamed from test/elf/Inputs/libundef.so)bin11128 -> 11128 bytes
-rwxr-xr-xtest/old-elf/Inputs/libweaksym.so (renamed from test/elf/Inputs/libweaksym.so)bin2160 -> 2160 bytes
-rw-r--r--test/old-elf/Inputs/main-with-global-def.o.yaml55
-rw-r--r--test/old-elf/Inputs/mainobj.x86_64 (renamed from test/elf/Inputs/mainobj.x86_64)bin1360 -> 1360 bytes
-rw-r--r--test/old-elf/Inputs/no-unique-section-names.x86-64bin0 -> 2128 bytes
-rw-r--r--test/old-elf/Inputs/object-test.elf-hexagon (renamed from test/elf/Inputs/object-test.elf-hexagon)bin1532 -> 1532 bytes
-rw-r--r--test/old-elf/Inputs/object-test.elf-i386 (renamed from test/elf/Inputs/object-test.elf-i386)bin1784 -> 1784 bytes
-rw-r--r--test/old-elf/Inputs/phdr.i386 (renamed from test/elf/Inputs/phdr.i386)bin17536 -> 17536 bytes
-rw-r--r--test/old-elf/Inputs/quickdata-sort-test.o.elf-hexagon (renamed from test/elf/Inputs/quickdata-sort-test.o.elf-hexagon)bin1385 -> 1385 bytes
-rw-r--r--test/old-elf/Inputs/quickdata-sortcommon-test.o.elf-hexagon (renamed from test/elf/Inputs/quickdata-sortcommon-test.o.elf-hexagon)bin1469 -> 1469 bytes
-rw-r--r--test/old-elf/Inputs/quickdata-test.elf-hexagon (renamed from test/elf/Inputs/quickdata-test.elf-hexagon)bin891 -> 891 bytes
-rw-r--r--test/old-elf/Inputs/reloc-test.elf-i386 (renamed from test/elf/Inputs/reloc-test.elf-i386)bin1076 -> 1076 bytes
-rw-r--r--test/old-elf/Inputs/reloc-xb.x86 (renamed from test/elf/Inputs/reloc-xb.x86)bin568 -> 568 bytes
-rw-r--r--test/old-elf/Inputs/reloc-xt.x86 (renamed from test/elf/Inputs/reloc-xt.x86)bin548 -> 548 bytes
-rw-r--r--test/old-elf/Inputs/relocs-dynamic.x86-64 (renamed from test/elf/Inputs/relocs-dynamic.x86-64)bin864 -> 864 bytes
-rw-r--r--test/old-elf/Inputs/relocs.x86-64 (renamed from test/elf/Inputs/relocs.x86-64)bin1536 -> 1536 bytes
-rw-r--r--test/old-elf/Inputs/responsefile (renamed from test/elf/Inputs/responsefile)0
-rw-r--r--test/old-elf/Inputs/rodata-test.hexagon (renamed from test/elf/Inputs/rodata-test.hexagon)bin669 -> 669 bytes
-rw-r--r--test/old-elf/Inputs/rodata-test.i386 (renamed from test/elf/Inputs/rodata-test.i386)bin537 -> 537 bytes
-rw-r--r--test/old-elf/Inputs/rodata.c (renamed from test/elf/Inputs/rodata.c)0
-rw-r--r--test/old-elf/Inputs/rodata.o (renamed from test/elf/Inputs/rodata.o)bin1568 -> 1568 bytes
-rw-r--r--test/old-elf/Inputs/section-test.i386 (renamed from test/elf/Inputs/section-test.i386)bin717 -> 717 bytes
-rw-r--r--test/old-elf/Inputs/shared.c (renamed from test/elf/Inputs/shared.c)0
-rw-r--r--test/old-elf/Inputs/shared.so-x86-64 (renamed from test/elf/Inputs/shared.so-x86-64)bin7536 -> 7536 bytes
-rw-r--r--test/old-elf/Inputs/shndx.o-x86_64bin0 -> 624 bytes
-rw-r--r--test/old-elf/Inputs/stripped-empty.x86_64bin0 -> 416 bytes
-rw-r--r--test/old-elf/Inputs/target-test.hexagon (renamed from test/elf/Inputs/target-test.hexagon)bin676 -> 676 bytes
-rw-r--r--test/old-elf/Inputs/target-test.ppc (renamed from test/elf/Inputs/target-test.ppc)bin552 -> 552 bytes
-rw-r--r--test/old-elf/Inputs/tls-tbss-size.yaml59
-rw-r--r--test/old-elf/Inputs/tls.S (renamed from test/elf/Inputs/tls.S)0
-rw-r--r--test/old-elf/Inputs/tls.c (renamed from test/elf/Inputs/tls.c)0
-rw-r--r--test/old-elf/Inputs/tls.x86-64 (renamed from test/elf/Inputs/tls.x86-64)bin1424 -> 1424 bytes
-rw-r--r--test/old-elf/Inputs/tlsAddr.x86-64 (renamed from test/elf/Inputs/tlsAddr.x86-64)bin1752 -> 1752 bytes
-rw-r--r--test/old-elf/Inputs/tlsaddr.c (renamed from test/elf/Inputs/tlsaddr.c)0
-rw-r--r--test/old-elf/Inputs/undef-from-main-so.c (renamed from test/elf/Inputs/undef-from-main-so.c)0
-rw-r--r--test/old-elf/Inputs/undef-from-main.c (renamed from test/elf/Inputs/undef-from-main.c)0
-rw-r--r--test/old-elf/Inputs/undef-pc32.o (renamed from test/elf/Inputs/undef-pc32.o)bin1248 -> 1248 bytes
-rw-r--r--test/old-elf/Inputs/undef.o (renamed from test/elf/Inputs/undef.o)bin1264 -> 1264 bytes
-rw-r--r--test/old-elf/Inputs/undef2-so.o.yaml49
-rw-r--r--test/old-elf/Inputs/use-shared-32s.c (renamed from test/elf/Inputs/use-shared-32s.c)0
-rw-r--r--test/old-elf/Inputs/use-shared-32s.x86-64 (renamed from test/elf/Inputs/use-shared-32s.x86-64)bin1336 -> 1336 bytes
-rw-r--r--test/old-elf/Inputs/use-shared.c (renamed from test/elf/Inputs/use-shared.c)0
-rw-r--r--test/old-elf/Inputs/use-shared.x86-64 (renamed from test/elf/Inputs/use-shared.x86-64)bin1376 -> 1376 bytes
-rw-r--r--test/old-elf/Inputs/weaksym.o (renamed from test/elf/Inputs/weaksym.o)bin840 -> 840 bytes
-rw-r--r--test/old-elf/Inputs/writersyms.o (renamed from test/elf/Inputs/writersyms.o)bin868 -> 868 bytes
-rw-r--r--test/old-elf/Inputs/x86-64-relocs.S (renamed from test/elf/Inputs/x86-64-relocs.S)0
-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.c (renamed from test/elf/X86_64/Inputs/constint.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/constint.o (renamed from test/elf/X86_64/Inputs/constint.o)bin1062 -> 1062 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/debug0.c (renamed from test/elf/X86_64/Inputs/debug0.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/debug0.x86-64 (renamed from test/elf/X86_64/Inputs/debug0.x86-64)bin2704 -> 2704 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/debug1.c (renamed from test/elf/X86_64/Inputs/debug1.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/debug1.x86-64 (renamed from test/elf/X86_64/Inputs/debug1.x86-64)bin2584 -> 2584 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/externtls.c (renamed from test/elf/X86_64/Inputs/externtls.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/externtls.x86-64 (renamed from test/elf/X86_64/Inputs/externtls.x86-64)bin1424 -> 1424 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/fn.c (renamed from test/elf/X86_64/Inputs/fn.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/fn.o (renamed from test/elf/X86_64/Inputs/fn.o)bin1072 -> 1072 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.c (renamed from test/elf/X86_64/Inputs/group/1.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/group/1.o (renamed from test/elf/X86_64/Inputs/group/1.o)bin1456 -> 1456 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn.c (renamed from test/elf/X86_64/Inputs/group/fn.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn.o (renamed from test/elf/X86_64/Inputs/group/fn.o)bin1360 -> 1360 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn1.c (renamed from test/elf/X86_64/Inputs/group/fn1.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn1.o (renamed from test/elf/X86_64/Inputs/group/fn1.o)bin1352 -> 1352 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn2.c (renamed from test/elf/X86_64/Inputs/group/fn2.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn2.o (renamed from test/elf/X86_64/Inputs/group/fn2.o)bin1224 -> 1224 bytes
-rwxr-xr-xtest/old-elf/X86_64/Inputs/group/group.sh (renamed from test/elf/X86_64/Inputs/group/group.sh)0
-rw-r--r--test/old-elf/X86_64/Inputs/group/libfn.a (renamed from test/elf/X86_64/Inputs/group/libfn.a)bin2792 -> 2792 bytes
-rwxr-xr-xtest/old-elf/X86_64/Inputs/group/libfn.so (renamed from test/elf/X86_64/Inputs/group/libfn.so)bin2516 -> 2516 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/group/libfn1.a (renamed from test/elf/X86_64/Inputs/group/libfn1.a)bin1492 -> 1492 bytes
-rwxr-xr-xtest/old-elf/X86_64/Inputs/group/libfn2.so (renamed from test/elf/X86_64/Inputs/group/libfn2.so)bin9624 -> 9624 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/initfini-option.c (renamed from test/elf/X86_64/Inputs/initfini-option.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/initfini-option.o (renamed from test/elf/X86_64/Inputs/initfini-option.o)bin1824 -> 1824 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/initfini.c (renamed from test/elf/X86_64/Inputs/initfini.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/initfini.o (renamed from test/elf/X86_64/Inputs/initfini.o)bin2256 -> 2256 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/largebss.c (renamed from test/elf/X86_64/Inputs/largebss.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/largebss.o (renamed from test/elf/X86_64/Inputs/largebss.o)bin1131 -> 1131 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/1.c (renamed from test/elf/X86_64/Inputs/layoutpass/1.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/1.o (renamed from test/elf/X86_64/Inputs/layoutpass/1.o)bin1448 -> 1448 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/2.c (renamed from test/elf/X86_64/Inputs/layoutpass/2.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/2.o (renamed from test/elf/X86_64/Inputs/layoutpass/2.o)bin1320 -> 1320 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/3.c (renamed from test/elf/X86_64/Inputs/layoutpass/3.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/3.o (renamed from test/elf/X86_64/Inputs/layoutpass/3.o)bin1216 -> 1216 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/lib2.a (renamed from test/elf/X86_64/Inputs/layoutpass/lib2.a)bin1464 -> 1464 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/libfn.a (renamed from test/elf/X86_64/Inputs/libfn.a)bin1364 -> 1364 bytes
-rwxr-xr-xtest/old-elf/X86_64/Inputs/libfn.so (renamed from test/elf/X86_64/Inputs/libfn.so)bin2008 -> 2008 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/main.c (renamed from test/elf/X86_64/Inputs/main.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/main.o (renamed from test/elf/X86_64/Inputs/main.o)bin1360 -> 1360 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/multi-ovrd.c (renamed from test/elf/X86_64/Inputs/multi-ovrd.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/multi-ovrd.o (renamed from test/elf/X86_64/Inputs/multi-ovrd.o)bin1648 -> 1648 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/multi-weak.c (renamed from test/elf/X86_64/Inputs/multi-weak.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/multi-weak.o (renamed from test/elf/X86_64/Inputs/multi-weak.o)bin1856 -> 1856 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/multiweaksyms.o (renamed from test/elf/X86_64/Inputs/multiweaksyms.o)bin928 -> 928 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/nmagic.c (renamed from test/elf/X86_64/Inputs/nmagic.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/nmagic.o (renamed from test/elf/X86_64/Inputs/nmagic.o)bin1528 -> 1528 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/no-interp-section.c (renamed from test/elf/X86_64/Inputs/no-interp-section.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/no-interp-section.o (renamed from test/elf/X86_64/Inputs/no-interp-section.o)bin975 -> 975 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/note.o (renamed from test/elf/X86_64/Inputs/note.o)bin785 -> 785 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/note.s (renamed from test/elf/X86_64/Inputs/note.s)0
-rw-r--r--test/old-elf/X86_64/Inputs/note_ro_rw.o (renamed from test/elf/X86_64/Inputs/note_ro_rw.o)bin905 -> 905 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/note_ro_rw.s (renamed from test/elf/X86_64/Inputs/note_ro_rw.s)0
-rw-r--r--test/old-elf/X86_64/Inputs/ovrd.c (renamed from test/elf/X86_64/Inputs/ovrd.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/ovrd.o (renamed from test/elf/X86_64/Inputs/ovrd.o)bin1488 -> 1488 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/rodata.c (renamed from test/elf/X86_64/Inputs/rodata.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/rodata.o (renamed from test/elf/X86_64/Inputs/rodata.o)bin1584 -> 1584 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/rodata.s (renamed from test/elf/X86_64/Inputs/rodata.s)0
-rw-r--r--test/old-elf/X86_64/Inputs/rwint.c (renamed from test/elf/X86_64/Inputs/rwint.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/rwint.o (renamed from test/elf/X86_64/Inputs/rwint.o)bin963 -> 963 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/sectionmap.c (renamed from test/elf/X86_64/Inputs/sectionmap.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/sectionmap.o (renamed from test/elf/X86_64/Inputs/sectionmap.o)bin1478 -> 1478 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/undefcpp.c (renamed from test/elf/X86_64/Inputs/undefcpp.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/undefcpp.o (renamed from test/elf/X86_64/Inputs/undefcpp.o)bin1344 -> 1344 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/weak-zero-sized.o (renamed from test/elf/X86_64/Inputs/weak-zero-sized.o)bin688 -> 688 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/weak.c (renamed from test/elf/X86_64/Inputs/weak.c)0
-rw-r--r--test/old-elf/X86_64/Inputs/weak.o (renamed from test/elf/X86_64/Inputs/weak.o)bin1712 -> 1712 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/weak.s (renamed from test/elf/X86_64/Inputs/weak.s)0
-rw-r--r--test/old-elf/X86_64/Inputs/zerosizedsection.o (renamed from test/elf/X86_64/Inputs/zerosizedsection.o)bin760 -> 760 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/zerosizedsection.s (renamed from test/elf/X86_64/Inputs/zerosizedsection.s)0
-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.ls (renamed from test/elf/linkerscript/Inputs/externs.ls)0
-rw-r--r--test/old-elf/linkerscript/Inputs/invalid.ls (renamed from test/elf/linkerscript/Inputs/invalid.ls)0
-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.ls (renamed from test/elf/linkerscript/Inputs/valid.ls)0
-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--test/pecoff/Inputs/abs.obj.yaml11
-rw-r--r--test/pecoff/Inputs/alignment.obj.yaml103
-rw-r--r--test/pecoff/Inputs/alternatename1.obj.yaml23
-rw-r--r--test/pecoff/Inputs/alternatename2.obj.yaml23
-rw-r--r--test/pecoff/Inputs/alternatename3.obj.yaml39
-rw-r--r--test/pecoff/Inputs/armnt-ImageBase.obj.yaml39
-rw-r--r--test/pecoff/Inputs/armnt-ImageBase.s16
-rw-r--r--test/pecoff/Inputs/armnt-addr32-exec.obj.yaml55
-rw-r--r--test/pecoff/Inputs/armnt-addr32-exec.s24
-rw-r--r--test/pecoff/Inputs/armnt-addr32.obj.yaml39
-rw-r--r--test/pecoff/Inputs/armnt-addr32.s18
-rw-r--r--test/pecoff/Inputs/armnt-blx23t.obj.yaml39
-rw-r--r--test/pecoff/Inputs/armnt-blx23t.s33
-rw-r--r--test/pecoff/Inputs/armnt-branch24t.obj.yaml39
-rw-r--r--test/pecoff/Inputs/armnt-branch24t.s26
-rw-r--r--test/pecoff/Inputs/armnt-exports.def4
-rw-r--r--test/pecoff/Inputs/armnt-exports.obj.yaml35
-rw-r--r--test/pecoff/Inputs/armnt-import.obj.yaml39
-rw-r--r--test/pecoff/Inputs/armnt-import.s21
-rw-r--r--test/pecoff/Inputs/armnt-mov32t-exec.obj.yaml39
-rw-r--r--test/pecoff/Inputs/armnt-mov32t-exec.s30
-rw-r--r--test/pecoff/Inputs/armnt-mov32t.obj.yaml55
-rw-r--r--test/pecoff/Inputs/armnt-mov32t.s24
-rw-r--r--test/pecoff/Inputs/armnt-obj.s12
-rw-r--r--test/pecoff/Inputs/armnt-obj.yaml29
-rw-r--r--test/pecoff/Inputs/associative1.obj.yaml53
-rw-r--r--test/pecoff/Inputs/associative3.obj.yaml33
-rw-r--r--test/pecoff/Inputs/basereloc.obj.yaml164
-rw-r--r--test/pecoff/Inputs/bss.asm20
-rw-r--r--test/pecoff/Inputs/bss.objbin683 -> 0 bytes
-rw-r--r--test/pecoff/Inputs/comdat.obj.yaml53
-rw-r--r--test/pecoff/Inputs/common-symbol.obj.yaml85
-rw-r--r--test/pecoff/Inputs/drectve.obj.yaml79
-rw-r--r--test/pecoff/Inputs/drectve2.obj.yaml45
-rw-r--r--test/pecoff/Inputs/drectve3.libbin462 -> 0 bytes
-rw-r--r--test/pecoff/Inputs/entry.obj.yaml40
-rw-r--r--test/pecoff/Inputs/executable.obj.yaml29
-rw-r--r--test/pecoff/Inputs/executable.s17
-rw-r--r--test/pecoff/Inputs/export.obj.yaml69
-rw-r--r--test/pecoff/Inputs/exports.def6
-rw-r--r--test/pecoff/Inputs/exports2.def6
-rw-r--r--test/pecoff/Inputs/grouped-sections.asm18
-rw-r--r--test/pecoff/Inputs/grouped-sections.obj.yaml83
-rw-r--r--test/pecoff/Inputs/hello.asm24
-rw-r--r--test/pecoff/Inputs/hello.obj.yaml111
-rw-r--r--test/pecoff/Inputs/hello64.asm22
-rw-r--r--test/pecoff/Inputs/hello64.obj.yaml110
-rw-r--r--test/pecoff/Inputs/hello64lib.asm14
-rw-r--r--test/pecoff/Inputs/hello64lib.libbin1938 -> 0 bytes
-rw-r--r--test/pecoff/Inputs/imagebase.obj.yaml55
-rw-r--r--test/pecoff/Inputs/machine-type-unknown.obj.yaml38
-rw-r--r--test/pecoff/Inputs/main.obj.yaml70
-rw-r--r--test/pecoff/Inputs/merge-largest1.obj.yaml30
-rw-r--r--test/pecoff/Inputs/merge-largest2.obj.yaml30
-rw-r--r--test/pecoff/Inputs/merge-same-size1.obj.yaml30
-rw-r--r--test/pecoff/Inputs/merge-same-size2.obj.yaml30
-rw-r--r--test/pecoff/Inputs/merge-same-size3.obj.yaml30
-rw-r--r--test/pecoff/Inputs/nonstandard-sections.obj.yaml53
-rw-r--r--test/pecoff/Inputs/nop.asm9
-rw-r--r--test/pecoff/Inputs/nop.obj.yaml51
-rw-r--r--test/pecoff/Inputs/nop64.obj.yaml67
-rw-r--r--test/pecoff/Inputs/reloc.obj.yaml82
-rw-r--r--test/pecoff/Inputs/reloc64.obj.yaml63
-rw-r--r--test/pecoff/Inputs/resource.rc4
-rw-r--r--test/pecoff/Inputs/responsefile.txt1
-rw-r--r--test/pecoff/Inputs/secrel1.obj.yaml69
-rw-r--r--test/pecoff/Inputs/secrel2.obj.yaml47
-rw-r--r--test/pecoff/Inputs/seh.c13
-rw-r--r--test/pecoff/Inputs/seh.obj.yaml387
-rw-r--r--test/pecoff/Inputs/static-data1.obj.yaml67
-rw-r--r--test/pecoff/Inputs/static-data2.obj.yaml67
-rw-r--r--test/pecoff/Inputs/static.libbin1120 -> 0 bytes
-rw-r--r--test/pecoff/Inputs/subsystem.main.yaml35
-rw-r--r--test/pecoff/Inputs/subsystem.winmain.yaml35
-rw-r--r--test/pecoff/Inputs/tlsused.obj.yaml29
-rw-r--r--test/pecoff/Inputs/unknown-drectve.obj.yaml42
-rw-r--r--test/pecoff/Inputs/unwind.obj.yaml129
-rw-r--r--test/pecoff/Inputs/vars-main-x64.obj.yaml63
-rw-r--r--test/pecoff/Inputs/vars-main-x86.obj.yaml69
-rw-r--r--test/pecoff/Inputs/vars-main.c7
-rw-r--r--test/pecoff/Inputs/vars.c20
-rw-r--r--test/pecoff/Inputs/vars.dll.yaml19
-rw-r--r--test/pecoff/Inputs/vars.libbin1994 -> 0 bytes
-rw-r--r--test/pecoff/Inputs/vars64.libbin2016 -> 0 bytes
-rw-r--r--test/pecoff/Inputs/weak-externals.asm25
-rw-r--r--test/pecoff/Inputs/weak-externals.obj.yaml91
-rw-r--r--test/pecoff/alignment.test22
-rw-r--r--test/pecoff/alternatename.test44
-rw-r--r--test/pecoff/armnt-ImageBase.test14
-rw-r--r--test/pecoff/armnt-addr32-exec.test11
-rw-r--r--test/pecoff/armnt-addr32.test11
-rw-r--r--test/pecoff/armnt-address-of-entry-point.test6
-rw-r--r--test/pecoff/armnt-blx23t.test27
-rw-r--r--test/pecoff/armnt-branch24t.test20
-rw-r--r--test/pecoff/armnt-exports.s28
-rw-r--r--test/pecoff/armnt-exports.test10
-rw-r--r--test/pecoff/armnt-imports.test11
-rw-r--r--test/pecoff/armnt-mov32t-exec.test21
-rw-r--r--test/pecoff/armnt-movt32t.test17
-rw-r--r--test/pecoff/armnt.test6
-rw-r--r--test/pecoff/associative.test10
-rw-r--r--test/pecoff/base-reloc.test78
-rw-r--r--test/pecoff/baseaddr.test18
-rw-r--r--test/pecoff/bss-section.test21
-rw-r--r--test/pecoff/comdat.test12
-rw-r--r--test/pecoff/common-symbol.test14
-rw-r--r--test/pecoff/conflicting-machine.test6
-rw-r--r--test/pecoff/delayimport.test54
-rw-r--r--test/pecoff/dll.test7
-rw-r--r--test/pecoff/dosstub.test11
-rw-r--r--test/pecoff/drectve.test39
-rw-r--r--test/pecoff/dynamic.test11
-rw-r--r--test/pecoff/dynamicbase.test24
-rw-r--r--test/pecoff/entry.test41
-rw-r--r--test/pecoff/export-warning.test19
-rw-r--r--test/pecoff/export.test90
-rw-r--r--test/pecoff/exportlib.test32
-rw-r--r--test/pecoff/exportlib2.test21
-rw-r--r--test/pecoff/grouped-sections.test17
-rw-r--r--test/pecoff/hello.test51
-rw-r--r--test/pecoff/hello64.test22
-rw-r--r--test/pecoff/help.test4
-rw-r--r--test/pecoff/imagebase.test15
-rw-r--r--test/pecoff/importlib.test55
-rw-r--r--test/pecoff/include.test8
-rw-r--r--test/pecoff/lib.test15
-rw-r--r--test/pecoff/libarg.test9
-rw-r--r--test/pecoff/localyimported.test15
-rw-r--r--test/pecoff/long-section-name.test7
-rw-r--r--test/pecoff/machinetype.test13
-rw-r--r--test/pecoff/manifest.test63
-rw-r--r--test/pecoff/merge-largest.test24
-rw-r--r--test/pecoff/merge-same-size.test32
-rw-r--r--test/pecoff/multi.test17
-rw-r--r--test/pecoff/noentry.test10
-rw-r--r--test/pecoff/nonstandard-sections.test75
-rw-r--r--test/pecoff/options.test40
-rw-r--r--test/pecoff/pe32plus.test87
-rw-r--r--test/pecoff/reloc.test16
-rw-r--r--test/pecoff/reloc64.test20
-rw-r--r--test/pecoff/resource.test16
-rw-r--r--test/pecoff/responsefile.test7
-rw-r--r--test/pecoff/safeseh.test9
-rw-r--r--test/pecoff/secrel.test16
-rw-r--r--test/pecoff/section-attribute.test45
-rw-r--r--test/pecoff/section-renaming.test61
-rw-r--r--test/pecoff/seh.test31
-rw-r--r--test/pecoff/seh64.test57
-rw-r--r--test/pecoff/subsystem.test12
-rw-r--r--test/pecoff/tls.test14
-rw-r--r--test/pecoff/trivial.test103
-rw-r--r--test/pecoff/unknown-drectve.test6
-rw-r--r--test/pecoff/weak-external.test9
-rw-r--r--tools/Makefile17
-rw-r--r--tools/linker-script-test/Makefile24
-rw-r--r--tools/lld/CMakeLists.txt22
-rw-r--r--tools/lld/Makefile30
-rw-r--r--tools/lld/lld.cpp5
-rw-r--r--unittests/CoreTests/Makefile14
-rw-r--r--unittests/DriverTests/CMakeLists.txt4
-rw-r--r--unittests/DriverTests/DarwinLdDriverTest.cpp6
-rw-r--r--unittests/DriverTests/DriverTest.h2
-rw-r--r--unittests/DriverTests/GnuLdDriverTest.cpp21
-rw-r--r--unittests/DriverTests/Makefile20
-rw-r--r--unittests/DriverTests/UniversalDriverTest.cpp4
-rw-r--r--unittests/DriverTests/WinLinkDriverTest.cpp728
-rw-r--r--unittests/DriverTests/WinLinkModuleDefTest.cpp155
-rw-r--r--unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp16
-rw-r--r--unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp17
-rw-r--r--unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp2
-rw-r--r--unittests/MachOTests/MachONormalizedFileYAMLTests.cpp36
-rw-r--r--unittests/Makefile31
-rw-r--r--utils/astyle-options7
1988 files changed, 86158 insertions, 53349 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 30ef47a692d2..6b64301d1ad8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -89,10 +89,11 @@ endif()
add_subdirectory(lib)
add_subdirectory(tools)
-add_subdirectory(test)
-
if (LLVM_INCLUDE_TESTS)
+ add_subdirectory(test)
add_subdirectory(unittests)
endif()
add_subdirectory(docs)
+add_subdirectory(COFF)
+add_subdirectory(ELF)
diff --git a/CODE_OWNERS.TXT b/CODE_OWNERS.TXT
new file mode 100644
index 000000000000..292967e588f0
--- /dev/null
+++ b/CODE_OWNERS.TXT
@@ -0,0 +1,19 @@
+This file is a list of the people responsible for ensuring that patches for a
+particular part of LLD are reviewed, either by themself or by someone else.
+They are also the gatekeepers for their part of LLD, with the final word on
+what goes in or not.
+
+The list is sorted by surname and formatted to allow easy grepping and
+beautification by scripts. The fields are: name (N), email (E), web-address
+(W), PGP key ID and fingerprint (P), description (D), and snail-mail address
+(S). Each entry should contain at least the (N), (E) and (D) fields.
+
+
+N: Rui Ueyama
+E: ruiu@google.com
+D: COFF, ELF backends (COFF/* ELF/*)
+
+N: Lang Hames, Nick Kledzik
+E: lhames@gmail.com, kledzik@apple.com
+D: Mach-O backend
+
diff --git a/COFF/CMakeLists.txt b/COFF/CMakeLists.txt
new file mode 100644
index 000000000000..78dc34eff96e
--- /dev/null
+++ b/COFF/CMakeLists.txt
@@ -0,0 +1,33 @@
+set(LLVM_TARGET_DEFINITIONS Options.td)
+tablegen(LLVM Options.inc -gen-opt-parser-defs)
+add_public_tablegen_target(COFFOptionsTableGen)
+
+add_llvm_library(lldCOFF
+ Chunks.cpp
+ DLL.cpp
+ Driver.cpp
+ DriverUtils.cpp
+ Error.cpp
+ ICF.cpp
+ InputFiles.cpp
+ MarkLive.cpp
+ ModuleDef.cpp
+ PDB.cpp
+ SymbolTable.cpp
+ Symbols.cpp
+ Writer.cpp
+
+ LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
+ Core
+ LTO
+ LibDriver
+ Object
+ MC
+ MCDisassembler
+ Target
+ Option
+ Support
+ )
+
+add_dependencies(lldCOFF COFFOptionsTableGen)
diff --git a/COFF/Chunks.cpp b/COFF/Chunks.cpp
new file mode 100644
index 000000000000..50bf55be269b
--- /dev/null
+++ b/COFF/Chunks.cpp
@@ -0,0 +1,340 @@
+//===- Chunks.cpp ---------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Chunks.h"
+#include "Error.h"
+#include "InputFiles.h"
+#include "Symbols.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/COFF.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::support::endian;
+using namespace llvm::COFF;
+using llvm::support::ulittle32_t;
+
+namespace lld {
+namespace coff {
+
+SectionChunk::SectionChunk(ObjectFile *F, const coff_section *H)
+ : Chunk(SectionKind), Repl(this), File(F), Header(H),
+ Relocs(File->getCOFFObj()->getRelocations(Header)),
+ NumRelocs(std::distance(Relocs.begin(), Relocs.end())) {
+ // 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);
+
+ // Only COMDAT sections are subject of dead-stripping.
+ Live = !isCOMDAT();
+}
+
+static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); }
+static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); }
+static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); }
+static void or16(uint8_t *P, uint16_t V) { write16le(P, read16le(P) | V); }
+
+void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, Defined *Sym,
+ uint64_t P) const {
+ uint64_t S = Sym->getRVA();
+ switch (Type) {
+ case IMAGE_REL_AMD64_ADDR32: add32(Off, S + Config->ImageBase); break;
+ case IMAGE_REL_AMD64_ADDR64: add64(Off, S + Config->ImageBase); break;
+ case IMAGE_REL_AMD64_ADDR32NB: add32(Off, S); break;
+ case IMAGE_REL_AMD64_REL32: add32(Off, S - P - 4); break;
+ case IMAGE_REL_AMD64_REL32_1: add32(Off, S - P - 5); break;
+ case IMAGE_REL_AMD64_REL32_2: add32(Off, S - P - 6); break;
+ case IMAGE_REL_AMD64_REL32_3: add32(Off, S - P - 7); break;
+ case IMAGE_REL_AMD64_REL32_4: add32(Off, S - P - 8); break;
+ case IMAGE_REL_AMD64_REL32_5: add32(Off, S - P - 9); break;
+ 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");
+ }
+}
+
+void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, Defined *Sym,
+ uint64_t P) const {
+ uint64_t S = Sym->getRVA();
+ switch (Type) {
+ case IMAGE_REL_I386_ABSOLUTE: break;
+ case IMAGE_REL_I386_DIR32: add32(Off, S + Config->ImageBase); break;
+ case IMAGE_REL_I386_DIR32NB: add32(Off, S); break;
+ case IMAGE_REL_I386_REL32: add32(Off, S - P - 4); break;
+ 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");
+ }
+}
+
+static void applyMOV(uint8_t *Off, uint16_t V) {
+ or16(Off, ((V & 0x800) >> 1) | ((V >> 12) & 0xf));
+ or16(Off + 2, ((V & 0x700) << 4) | (V & 0xff));
+}
+
+static void applyMOV32T(uint8_t *Off, uint32_t V) {
+ applyMOV(Off, V); // set MOVW operand
+ applyMOV(Off + 4, V >> 16); // set MOVT operand
+}
+
+static void applyBranch20T(uint8_t *Off, int32_t V) {
+ uint32_t S = V < 0 ? 1 : 0;
+ uint32_t J1 = (V >> 19) & 1;
+ uint32_t J2 = (V >> 18) & 1;
+ or16(Off, (S << 10) | ((V >> 12) & 0x3f));
+ or16(Off + 2, (J1 << 13) | (J2 << 11) | ((V >> 1) & 0x7ff));
+}
+
+static void applyBranch24T(uint8_t *Off, int32_t V) {
+ uint32_t S = V < 0 ? 1 : 0;
+ uint32_t J1 = ((~V >> 23) & 1) ^ S;
+ uint32_t J2 = ((~V >> 22) & 1) ^ S;
+ or16(Off, (S << 10) | ((V >> 12) & 0x3ff));
+ or16(Off + 2, (J1 << 13) | (J2 << 11) | ((V >> 1) & 0x7ff));
+}
+
+void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, Defined *Sym,
+ uint64_t P) const {
+ uint64_t S = Sym->getRVA();
+ // Pointer to thumb code must have the LSB set.
+ if (Sym->isExecutable())
+ S |= 1;
+ switch (Type) {
+ case IMAGE_REL_ARM_ADDR32: add32(Off, S + Config->ImageBase); break;
+ case IMAGE_REL_ARM_ADDR32NB: add32(Off, S); break;
+ case IMAGE_REL_ARM_MOV32T: applyMOV32T(Off, S + Config->ImageBase); break;
+ case IMAGE_REL_ARM_BRANCH20T: applyBranch20T(Off, S - P - 4); break;
+ 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");
+ }
+}
+
+void SectionChunk::writeTo(uint8_t *Buf) const {
+ if (!hasData())
+ return;
+ // Copy section contents from source object file to output file.
+ ArrayRef<uint8_t> A = getContents();
+ memcpy(Buf + OutputSectionOff, A.data(), A.size());
+
+ // Apply relocations.
+ for (const coff_relocation &Rel : Relocs) {
+ uint8_t *Off = Buf + OutputSectionOff + Rel.VirtualAddress;
+ SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex)->repl();
+ Defined *Sym = cast<Defined>(Body);
+ uint64_t P = RVA + Rel.VirtualAddress;
+ switch (Config->Machine) {
+ case AMD64:
+ applyRelX64(Off, Rel.Type, Sym, P);
+ break;
+ case I386:
+ applyRelX86(Off, Rel.Type, Sym, P);
+ break;
+ case ARMNT:
+ applyRelARM(Off, Rel.Type, Sym, P);
+ break;
+ default:
+ llvm_unreachable("unknown machine type");
+ }
+ }
+}
+
+void SectionChunk::addAssociative(SectionChunk *Child) {
+ AssocChildren.push_back(Child);
+}
+
+static uint8_t getBaserelType(const coff_relocation &Rel) {
+ switch (Config->Machine) {
+ case AMD64:
+ if (Rel.Type == IMAGE_REL_AMD64_ADDR64)
+ return IMAGE_REL_BASED_DIR64;
+ return IMAGE_REL_BASED_ABSOLUTE;
+ case I386:
+ if (Rel.Type == IMAGE_REL_I386_DIR32)
+ return IMAGE_REL_BASED_HIGHLOW;
+ return IMAGE_REL_BASED_ABSOLUTE;
+ case ARMNT:
+ if (Rel.Type == IMAGE_REL_ARM_ADDR32)
+ return IMAGE_REL_BASED_HIGHLOW;
+ if (Rel.Type == IMAGE_REL_ARM_MOV32T)
+ return IMAGE_REL_BASED_ARM_MOV32T;
+ return IMAGE_REL_BASED_ABSOLUTE;
+ default:
+ llvm_unreachable("unknown machine type");
+ }
+}
+
+// Windows-specific.
+// Collect all locations that contain absolute addresses, which need to be
+// fixed by the loader if load-time relocation is needed.
+// Only called when base relocation is enabled.
+void SectionChunk::getBaserels(std::vector<Baserel> *Res) {
+ for (const coff_relocation &Rel : Relocs) {
+ uint8_t Ty = getBaserelType(Rel);
+ if (Ty == IMAGE_REL_BASED_ABSOLUTE)
+ continue;
+ SymbolBody *Body = File->getSymbolBody(Rel.SymbolTableIndex)->repl();
+ if (isa<DefinedAbsolute>(Body))
+ continue;
+ Res->emplace_back(RVA + Rel.VirtualAddress, Ty);
+ }
+}
+
+bool SectionChunk::hasData() const {
+ return !(Header->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA);
+}
+
+uint32_t SectionChunk::getPermissions() const {
+ return Header->Characteristics & PermMask;
+}
+
+bool SectionChunk::isCOMDAT() const {
+ return Header->Characteristics & IMAGE_SCN_LNK_COMDAT;
+}
+
+void SectionChunk::printDiscardedMessage() const {
+ // Removed by dead-stripping. If it's removed by ICF, ICF already
+ // printed out the name, so don't repeat that here.
+ if (Sym && this == Repl)
+ llvm::outs() << "Discarded " << Sym->getName() << "\n";
+}
+
+StringRef SectionChunk::getDebugName() {
+ if (Sym)
+ return Sym->getName();
+ return "";
+}
+
+ArrayRef<uint8_t> SectionChunk::getContents() const {
+ ArrayRef<uint8_t> A;
+ File->getCOFFObj()->getSectionContents(Header, A);
+ return A;
+}
+
+void SectionChunk::replace(SectionChunk *Other) {
+ Other->Repl = Repl;
+ Other->Live = false;
+}
+
+CommonChunk::CommonChunk(const COFFSymbolRef S) : Sym(S) {
+ // Common symbols are aligned on natural boundaries up to 32 bytes.
+ // This is what MSVC link.exe does.
+ Align = std::min(uint64_t(32), NextPowerOf2(Sym.getValue()));
+}
+
+uint32_t CommonChunk::getPermissions() const {
+ return IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ |
+ IMAGE_SCN_MEM_WRITE;
+}
+
+void StringChunk::writeTo(uint8_t *Buf) const {
+ memcpy(Buf + OutputSectionOff, Str.data(), Str.size());
+}
+
+ImportThunkChunkX64::ImportThunkChunkX64(Defined *S) : ImpSymbol(S) {
+ // Intel Optimization Manual says that all branch targets
+ // should be 16-byte aligned. MSVC linker does this too.
+ Align = 16;
+}
+
+void ImportThunkChunkX64::writeTo(uint8_t *Buf) const {
+ memcpy(Buf + OutputSectionOff, ImportThunkX86, sizeof(ImportThunkX86));
+ // The first two bytes is a JMP instruction. Fill its operand.
+ write32le(Buf + OutputSectionOff + 2, ImpSymbol->getRVA() - RVA - getSize());
+}
+
+void ImportThunkChunkX86::getBaserels(std::vector<Baserel> *Res) {
+ Res->emplace_back(getRVA() + 2);
+}
+
+void ImportThunkChunkX86::writeTo(uint8_t *Buf) const {
+ memcpy(Buf + OutputSectionOff, ImportThunkX86, sizeof(ImportThunkX86));
+ // The first two bytes is a JMP instruction. Fill its operand.
+ write32le(Buf + OutputSectionOff + 2,
+ ImpSymbol->getRVA() + Config->ImageBase);
+}
+
+void ImportThunkChunkARM::getBaserels(std::vector<Baserel> *Res) {
+ Res->emplace_back(getRVA(), IMAGE_REL_BASED_ARM_MOV32T);
+}
+
+void ImportThunkChunkARM::writeTo(uint8_t *Buf) const {
+ memcpy(Buf + OutputSectionOff, ImportThunkARM, sizeof(ImportThunkARM));
+ // Fix mov.w and mov.t operands.
+ applyMOV32T(Buf + OutputSectionOff, ImpSymbol->getRVA() + Config->ImageBase);
+}
+
+void LocalImportChunk::getBaserels(std::vector<Baserel> *Res) {
+ Res->emplace_back(getRVA());
+}
+
+size_t LocalImportChunk::getSize() const {
+ return Config->is64() ? 8 : 4;
+}
+
+void LocalImportChunk::writeTo(uint8_t *Buf) const {
+ if (Config->is64()) {
+ write64le(Buf + OutputSectionOff, Sym->getRVA() + Config->ImageBase);
+ } else {
+ write32le(Buf + OutputSectionOff, Sym->getRVA() + Config->ImageBase);
+ }
+}
+
+void SEHTableChunk::writeTo(uint8_t *Buf) const {
+ ulittle32_t *Begin = reinterpret_cast<ulittle32_t *>(Buf + OutputSectionOff);
+ size_t Cnt = 0;
+ for (Defined *D : Syms)
+ Begin[Cnt++] = D->getRVA();
+ std::sort(Begin, Begin + Cnt);
+}
+
+// Windows-specific.
+// This class represents a block in .reloc section.
+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(RoundUpToAlignment((End - Begin) * 2 + 8, 4));
+ uint8_t *P = Data.data();
+ write32le(P, Page);
+ write32le(P + 4, Data.size());
+ P += 8;
+ for (Baserel *I = Begin; I != End; ++I) {
+ write16le(P, (I->Type << 12) | (I->RVA - Page));
+ P += 2;
+ }
+}
+
+void BaserelChunk::writeTo(uint8_t *Buf) const {
+ memcpy(Buf + OutputSectionOff, Data.data(), Data.size());
+}
+
+uint8_t Baserel::getDefaultType() {
+ switch (Config->Machine) {
+ case AMD64:
+ return IMAGE_REL_BASED_DIR64;
+ case I386:
+ return IMAGE_REL_BASED_HIGHLOW;
+ default:
+ llvm_unreachable("unknown machine type");
+ }
+}
+
+} // namespace coff
+} // namespace lld
diff --git a/COFF/Chunks.h b/COFF/Chunks.h
new file mode 100644
index 000000000000..60b8e76f8230
--- /dev/null
+++ b/COFF/Chunks.h
@@ -0,0 +1,332 @@
+//===- Chunks.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_CHUNKS_H
+#define LLD_COFF_CHUNKS_H
+
+#include "Config.h"
+#include "InputFiles.h"
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/iterator.h"
+#include "llvm/ADT/iterator_range.h"
+#include "llvm/Object/COFF.h"
+#include <atomic>
+#include <vector>
+
+namespace lld {
+namespace coff {
+
+using llvm::COFF::ImportDirectoryTableEntry;
+using llvm::object::COFFSymbolRef;
+using llvm::object::SectionRef;
+using llvm::object::coff_relocation;
+using llvm::object::coff_section;
+using llvm::sys::fs::file_magic;
+
+class Baserel;
+class Defined;
+class DefinedImportData;
+class DefinedRegular;
+class ObjectFile;
+class OutputSection;
+class SymbolBody;
+
+// Mask for section types (code, data, bss, disacardable, etc.)
+// and permissions (writable, readable or executable).
+const uint32_t PermMask = 0xFF0000F0;
+
+// A Chunk represents a chunk of data that will occupy space in the
+// output (if the resolver chose that). It may or may not be backed by
+// a section of an input file. It could be linker-created data, or
+// doesn't even have actual data (if common or bss).
+class Chunk {
+public:
+ enum Kind { SectionKind, OtherKind };
+ Kind kind() const { return ChunkKind; }
+ virtual ~Chunk() = default;
+
+ // Returns the size of this chunk (even if this is a common or BSS.)
+ virtual size_t getSize() const = 0;
+
+ // Write this chunk to a mmap'ed file, assuming Buf is pointing to
+ // beginning of the file. Because this function may use RVA values
+ // of other chunks for relocations, you need to set them properly
+ // before calling this function.
+ virtual void writeTo(uint8_t *Buf) const {}
+
+ // The writer sets and uses the addresses.
+ uint64_t getRVA() const { return RVA; }
+ uint32_t getAlign() const { return Align; }
+ void setRVA(uint64_t V) { RVA = V; }
+ void setOutputSectionOff(uint64_t V) { OutputSectionOff = V; }
+
+ // Returns true if this has non-zero data. BSS chunks return
+ // false. If false is returned, the space occupied by this chunk
+ // will be filled with zeros.
+ virtual bool hasData() const { return true; }
+
+ // Returns readable/writable/executable bits.
+ virtual uint32_t getPermissions() const { return 0; }
+
+ // Returns the section name if this is a section chunk.
+ // It is illegal to call this function on non-section chunks.
+ virtual StringRef getSectionName() const {
+ llvm_unreachable("unimplemented getSectionName");
+ }
+
+ // An output section has pointers to chunks in the section, and each
+ // chunk has a back pointer to an output section.
+ void setOutputSection(OutputSection *O) { Out = O; }
+ OutputSection *getOutputSection() { return Out; }
+
+ // Windows-specific.
+ // Collect all locations that contain absolute addresses for base relocations.
+ virtual void getBaserels(std::vector<Baserel> *Res) {}
+
+ // Returns a human-readable name of this chunk. Chunks are unnamed chunks of
+ // bytes, so this is used only for logging or debugging.
+ virtual StringRef getDebugName() { return ""; }
+
+protected:
+ Chunk(Kind K = OtherKind) : ChunkKind(K) {}
+ const Kind ChunkKind;
+
+ // The RVA of this chunk in the output. The writer sets a value.
+ uint64_t RVA = 0;
+
+ // The offset from beginning of the output section. The writer sets a value.
+ uint64_t OutputSectionOff = 0;
+
+ // The output section for this chunk.
+ OutputSection *Out = nullptr;
+
+ // The alignment of this chunk. The writer uses the value.
+ uint32_t Align = 1;
+};
+
+// A chunk corresponding a section of an input file.
+class SectionChunk : public Chunk {
+ // Identical COMDAT Folding feature accesses section internal data.
+ friend class ICF;
+
+public:
+ class symbol_iterator : public llvm::iterator_adaptor_base<
+ symbol_iterator, const coff_relocation *,
+ std::random_access_iterator_tag, SymbolBody *> {
+ friend SectionChunk;
+
+ ObjectFile *File;
+
+ symbol_iterator(ObjectFile *File, const coff_relocation *I)
+ : symbol_iterator::iterator_adaptor_base(I), File(File) {}
+
+ public:
+ symbol_iterator() = default;
+
+ SymbolBody *operator*() const {
+ return File->getSymbolBody(I->SymbolTableIndex);
+ }
+ };
+
+ 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; }
+ void writeTo(uint8_t *Buf) const override;
+ bool hasData() const override;
+ uint32_t getPermissions() const override;
+ StringRef getSectionName() const override { return SectionName; }
+ void getBaserels(std::vector<Baserel> *Res) override;
+ bool isCOMDAT() const;
+ void applyRelX64(uint8_t *Off, uint16_t Type, Defined *Sym, uint64_t P) const;
+ void applyRelX86(uint8_t *Off, uint16_t Type, Defined *Sym, uint64_t P) const;
+ void applyRelARM(uint8_t *Off, uint16_t Type, Defined *Sym, uint64_t P) const;
+
+ // Called if the garbage collector decides to not include this chunk
+ // in a final output. It's supposed to print out a log message to stdout.
+ void printDiscardedMessage() const;
+
+ // Adds COMDAT associative sections to this COMDAT section. A chunk
+ // and its children are treated as a group by the garbage collector.
+ void addAssociative(SectionChunk *Child);
+
+ StringRef getDebugName() override;
+ void setSymbol(DefinedRegular *S) { if (!Sym) Sym = S; }
+
+ // Used by the garbage collector.
+ bool isLive() { return !Config->DoGC || Live; }
+ void markLive() {
+ assert(!isLive() && "Cannot mark an already live section!");
+ Live = true;
+ }
+
+ // Allow iteration over the bodies of this chunk's relocated symbols.
+ llvm::iterator_range<symbol_iterator> symbols() const {
+ return llvm::make_range(symbol_iterator(File, Relocs.begin()),
+ symbol_iterator(File, Relocs.end()));
+ }
+
+ // Allow iteration over the associated child chunks for this section.
+ ArrayRef<SectionChunk *> children() const { return AssocChildren; }
+
+ // A pointer pointing to a replacement for this chunk.
+ // Initially it points to "this" object. If this chunk is merged
+ // with other chunk by ICF, it points to another chunk,
+ // and this chunk is considrered as dead.
+ SectionChunk *Repl;
+
+ // The CRC of the contents as described in the COFF spec 4.5.5.
+ // Auxiliary Format 5: Section Definitions. Used for ICF.
+ uint32_t Checksum = 0;
+
+private:
+ ArrayRef<uint8_t> getContents() const;
+
+ // A file this chunk was created from.
+ ObjectFile *File;
+
+ const coff_section *Header;
+ StringRef SectionName;
+ std::vector<SectionChunk *> AssocChildren;
+ llvm::iterator_range<const coff_relocation *> Relocs;
+ size_t NumRelocs;
+
+ // Used by the garbage collector.
+ bool Live;
+
+ // Used for ICF (Identical COMDAT Folding)
+ void replace(SectionChunk *Other);
+ std::atomic<uint64_t> GroupID = { 0 };
+
+ // Sym points to a section symbol if this is a COMDAT chunk.
+ DefinedRegular *Sym = nullptr;
+};
+
+// A chunk for common symbols. Common chunks don't have actual data.
+class CommonChunk : public Chunk {
+public:
+ CommonChunk(const COFFSymbolRef Sym);
+ size_t getSize() const override { return Sym.getValue(); }
+ bool hasData() const override { return false; }
+ uint32_t getPermissions() const override;
+ StringRef getSectionName() const override { return ".bss"; }
+
+private:
+ const COFFSymbolRef Sym;
+};
+
+// A chunk for linker-created strings.
+class StringChunk : public Chunk {
+public:
+ explicit StringChunk(StringRef S) : Str(S) {}
+ size_t getSize() const override { return Str.size() + 1; }
+ void writeTo(uint8_t *Buf) const override;
+
+private:
+ StringRef Str;
+};
+
+static const uint8_t ImportThunkX86[] = {
+ 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // JMP *0x0
+};
+
+static const uint8_t ImportThunkARM[] = {
+ 0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0
+ 0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0
+ 0xdc, 0xf8, 0x00, 0xf0, // ldr.w pc, [ip]
+};
+
+// Windows-specific.
+// A chunk for DLL import jump table entry. In a final output, it's
+// contents will be a JMP instruction to some __imp_ symbol.
+class ImportThunkChunkX64 : public Chunk {
+public:
+ explicit ImportThunkChunkX64(Defined *S);
+ size_t getSize() const override { return sizeof(ImportThunkX86); }
+ void writeTo(uint8_t *Buf) const override;
+
+private:
+ Defined *ImpSymbol;
+};
+
+class ImportThunkChunkX86 : public Chunk {
+public:
+ explicit ImportThunkChunkX86(Defined *S) : ImpSymbol(S) {}
+ size_t getSize() const override { return sizeof(ImportThunkX86); }
+ void getBaserels(std::vector<Baserel> *Res) override;
+ void writeTo(uint8_t *Buf) const override;
+
+private:
+ Defined *ImpSymbol;
+};
+
+class ImportThunkChunkARM : public Chunk {
+public:
+ explicit ImportThunkChunkARM(Defined *S) : ImpSymbol(S) {}
+ size_t getSize() const override { return sizeof(ImportThunkARM); }
+ void getBaserels(std::vector<Baserel> *Res) override;
+ void writeTo(uint8_t *Buf) const override;
+
+private:
+ Defined *ImpSymbol;
+};
+
+// Windows-specific.
+// See comments for DefinedLocalImport class.
+class LocalImportChunk : public Chunk {
+public:
+ explicit LocalImportChunk(Defined *S) : Sym(S) {}
+ size_t getSize() const override;
+ void getBaserels(std::vector<Baserel> *Res) override;
+ void writeTo(uint8_t *Buf) const override;
+
+private:
+ Defined *Sym;
+};
+
+// Windows-specific.
+// A chunk for SEH table which contains RVAs of safe exception handler
+// functions. x86-only.
+class SEHTableChunk : public Chunk {
+public:
+ explicit SEHTableChunk(std::set<Defined *> S) : Syms(S) {}
+ size_t getSize() const override { return Syms.size() * 4; }
+ void writeTo(uint8_t *Buf) const override;
+
+private:
+ std::set<Defined *> Syms;
+};
+
+// Windows-specific.
+// This class represents a block in .reloc section.
+// See the PE/COFF spec 5.6 for details.
+class BaserelChunk : public Chunk {
+public:
+ BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End);
+ size_t getSize() const override { return Data.size(); }
+ void writeTo(uint8_t *Buf) const override;
+
+private:
+ std::vector<uint8_t> Data;
+};
+
+class Baserel {
+public:
+ Baserel(uint32_t V, uint8_t Ty) : RVA(V), Type(Ty) {}
+ explicit Baserel(uint32_t V) : Baserel(V, getDefaultType()) {}
+ uint8_t getDefaultType();
+
+ uint32_t RVA;
+ uint8_t Type;
+};
+
+} // namespace coff
+} // namespace lld
+
+#endif
diff --git a/COFF/Config.h b/COFF/Config.h
new file mode 100644
index 000000000000..409ede648636
--- /dev/null
+++ b/COFF/Config.h
@@ -0,0 +1,140 @@
+//===- Config.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_CONFIG_H
+#define LLD_COFF_CONFIG_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Object/COFF.h"
+#include <cstdint>
+#include <map>
+#include <set>
+#include <string>
+
+namespace lld {
+namespace coff {
+
+using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN;
+using llvm::COFF::WindowsSubsystem;
+using llvm::StringRef;
+class DefinedAbsolute;
+class DefinedRelative;
+class Undefined;
+
+// Short aliases.
+static const auto AMD64 = llvm::COFF::IMAGE_FILE_MACHINE_AMD64;
+static const auto ARMNT = llvm::COFF::IMAGE_FILE_MACHINE_ARMNT;
+static const auto I386 = llvm::COFF::IMAGE_FILE_MACHINE_I386;
+
+// Represents an /export option.
+struct Export {
+ StringRef Name; // N in /export:N or /export:E=N
+ StringRef ExtName; // E in /export:E=N
+ Undefined *Sym = nullptr;
+ uint16_t Ordinal = 0;
+ bool Noname = false;
+ bool Data = false;
+ bool Private = false;
+
+ // True if this /export option was in .drectves section.
+ bool Directives = false;
+ StringRef SymbolName;
+ StringRef ExportName; // Name in DLL
+
+ bool operator==(const Export &E) {
+ return (Name == E.Name && ExtName == E.ExtName &&
+ Ordinal == E.Ordinal && Noname == E.Noname &&
+ Data == E.Data && Private == E.Private);
+ }
+};
+
+// Global configuration.
+struct Configuration {
+ enum ManifestKind { SideBySide, Embed, No };
+ bool is64() { return Machine == AMD64; }
+
+ llvm::COFF::MachineTypes Machine = IMAGE_FILE_MACHINE_UNKNOWN;
+ bool Verbose = false;
+ WindowsSubsystem Subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN;
+ Undefined *Entry = nullptr;
+ bool NoEntry = false;
+ std::string OutputFile;
+ bool DoGC = true;
+ bool DoICF = true;
+ bool Relocatable = true;
+ bool Force = false;
+ bool Debug = false;
+ bool WriteSymtab = true;
+
+ // Symbols in this set are considered as live by the garbage collector.
+ std::set<Undefined *> GCRoot;
+
+ std::set<StringRef> NoDefaultLibs;
+ bool NoDefaultLibAll = false;
+
+ // True if we are creating a DLL.
+ bool DLL = false;
+ StringRef Implib;
+ std::vector<Export> Exports;
+ std::set<std::string> DelayLoads;
+ std::map<std::string, int> DLLOrder;
+ Undefined *DelayLoadHelper = nullptr;
+
+ // Used for SafeSEH.
+ DefinedRelative *SEHTable = nullptr;
+ DefinedAbsolute *SEHCount = nullptr;
+
+ // Used for /opt:lldlto=N
+ unsigned LTOOptLevel = 2;
+
+ // Used for /opt:lldltojobs=N
+ unsigned LTOJobs = 1;
+
+ // Used for /merge:from=to (e.g. /merge:.rdata=.text)
+ std::map<StringRef, StringRef> Merge;
+
+ // Options for manifest files.
+ ManifestKind Manifest = SideBySide;
+ int ManifestID = 1;
+ StringRef ManifestDependency;
+ bool ManifestUAC = true;
+ StringRef ManifestLevel = "'asInvoker'";
+ StringRef ManifestUIAccess = "'false'";
+ StringRef ManifestFile;
+
+ // Used for /failifmismatch.
+ std::map<StringRef, StringRef> MustMatch;
+
+ // Used for /alternatename.
+ std::map<StringRef, StringRef> AlternateNames;
+
+ uint64_t ImageBase = -1;
+ uint64_t StackReserve = 1024 * 1024;
+ uint64_t StackCommit = 4096;
+ uint64_t HeapReserve = 1024 * 1024;
+ uint64_t HeapCommit = 4096;
+ uint32_t MajorImageVersion = 0;
+ uint32_t MinorImageVersion = 0;
+ uint32_t MajorOSVersion = 6;
+ uint32_t MinorOSVersion = 0;
+ bool DynamicBase = true;
+ bool AllowBind = true;
+ bool NxCompat = true;
+ bool AllowIsolation = true;
+ bool TerminalServerAware = true;
+ bool LargeAddressAware = false;
+ bool HighEntropyVA = false;
+};
+
+extern Configuration *Config;
+
+} // namespace coff
+} // namespace lld
+
+#endif
diff --git a/COFF/DLL.cpp b/COFF/DLL.cpp
new file mode 100644
index 000000000000..40ca5cf61dc2
--- /dev/null
+++ b/COFF/DLL.cpp
@@ -0,0 +1,556 @@
+//===- DLL.cpp ------------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file defines various types of chunks for the DLL import or export
+// descriptor tables. They are inherently Windows-specific.
+// You need to read Microsoft PE/COFF spec to understand details
+// about the data structures.
+//
+// If you are not particularly interested in linking against Windows
+// DLL, you can skip this file, and you should still be able to
+// understand the rest of the linker.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Chunks.h"
+#include "DLL.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Path.h"
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::support::endian;
+using namespace llvm::COFF;
+
+namespace lld {
+namespace coff {
+namespace {
+
+// Import table
+
+static int ptrSize() { return Config->is64() ? 8 : 4; }
+
+// A chunk for the import descriptor table.
+class HintNameChunk : public Chunk {
+public:
+ HintNameChunk(StringRef N, uint16_t H) : Name(N), Hint(H) {}
+
+ 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 RoundUpToAlignment(Name.size() + 3, 2);
+ }
+
+ void writeTo(uint8_t *Buf) const override {
+ write16le(Buf + OutputSectionOff, Hint);
+ memcpy(Buf + OutputSectionOff + 2, Name.data(), Name.size());
+ }
+
+private:
+ StringRef Name;
+ uint16_t Hint;
+};
+
+// A chunk for the import descriptor table.
+class LookupChunk : public Chunk {
+public:
+ explicit LookupChunk(Chunk *C) : HintName(C) {}
+ size_t getSize() const override { return ptrSize(); }
+
+ void writeTo(uint8_t *Buf) const override {
+ write32le(Buf + OutputSectionOff, HintName->getRVA());
+ }
+
+ Chunk *HintName;
+};
+
+// A chunk for the import descriptor table.
+// This chunk represent import-by-ordinal symbols.
+// See Microsoft PE/COFF spec 7.1. Import Header for details.
+class OrdinalOnlyChunk : public Chunk {
+public:
+ explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {}
+ size_t getSize() const override { return ptrSize(); }
+
+ void writeTo(uint8_t *Buf) const override {
+ // An import-by-ordinal slot has MSB 1 to indicate that
+ // this is import-by-ordinal (and not import-by-name).
+ if (Config->is64()) {
+ write64le(Buf + OutputSectionOff, (1ULL << 63) | Ordinal);
+ } else {
+ write32le(Buf + OutputSectionOff, (1ULL << 31) | Ordinal);
+ }
+ }
+
+ uint16_t Ordinal;
+};
+
+// A chunk for the import descriptor table.
+class ImportDirectoryChunk : public Chunk {
+public:
+ explicit ImportDirectoryChunk(Chunk *N) : DLLName(N) {}
+ size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
+
+ void writeTo(uint8_t *Buf) const override {
+ auto *E = (coff_import_directory_table_entry *)(Buf + OutputSectionOff);
+ E->ImportLookupTableRVA = LookupTab->getRVA();
+ E->NameRVA = DLLName->getRVA();
+ E->ImportAddressTableRVA = AddressTab->getRVA();
+ }
+
+ Chunk *DLLName;
+ Chunk *LookupTab;
+ Chunk *AddressTab;
+};
+
+// A chunk representing null terminator in the import table.
+// Contents of this chunk is always null bytes.
+class NullChunk : public Chunk {
+public:
+ explicit NullChunk(size_t N) : Size(N) {}
+ bool hasData() const override { return false; }
+ size_t getSize() const override { return Size; }
+ void setAlign(size_t N) { Align = N; }
+
+private:
+ size_t Size;
+};
+
+static std::vector<std::vector<DefinedImportData *>>
+binImports(const std::vector<DefinedImportData *> &Imports) {
+ // Group DLL-imported symbols by DLL name because that's how
+ // symbols are layed out in the import descriptor table.
+ auto Less = [](const std::string &A, const std::string &B) {
+ return Config->DLLOrder[A] < Config->DLLOrder[B];
+ };
+ std::map<std::string, std::vector<DefinedImportData *>,
+ bool(*)(const std::string &, const std::string &)> M(Less);
+ for (DefinedImportData *Sym : Imports)
+ M[Sym->getDLLName().lower()].push_back(Sym);
+
+ std::vector<std::vector<DefinedImportData *>> V;
+ for (auto &P : M) {
+ // Sort symbols by name for each group.
+ std::vector<DefinedImportData *> &Syms = P.second;
+ std::sort(Syms.begin(), Syms.end(),
+ [](DefinedImportData *A, DefinedImportData *B) {
+ return A->getName() < B->getName();
+ });
+ V.push_back(std::move(Syms));
+ }
+ return V;
+}
+
+// Export table
+// See Microsoft PE/COFF spec 4.3 for details.
+
+// A chunk for the delay import descriptor table etnry.
+class DelayDirectoryChunk : public Chunk {
+public:
+ explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {}
+
+ size_t getSize() const override {
+ return sizeof(delay_import_directory_table_entry);
+ }
+
+ void writeTo(uint8_t *Buf) const override {
+ auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff);
+ E->Attributes = 1;
+ E->Name = DLLName->getRVA();
+ E->ModuleHandle = ModuleHandle->getRVA();
+ E->DelayImportAddressTable = AddressTab->getRVA();
+ E->DelayImportNameTable = NameTab->getRVA();
+ }
+
+ Chunk *DLLName;
+ Chunk *ModuleHandle;
+ Chunk *AddressTab;
+ Chunk *NameTab;
+};
+
+// Initial contents for delay-loaded functions.
+// This code calls __delayLoadHelper2 function to resolve a symbol
+// and then overwrites its jump table slot with the result
+// for subsequent function calls.
+static const uint8_t ThunkX64[] = {
+ 0x51, // push rcx
+ 0x52, // push rdx
+ 0x41, 0x50, // push r8
+ 0x41, 0x51, // push r9
+ 0x48, 0x83, 0xEC, 0x48, // sub rsp, 48h
+ 0x66, 0x0F, 0x7F, 0x04, 0x24, // movdqa xmmword ptr [rsp], xmm0
+ 0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa xmmword ptr [rsp+10h], xmm1
+ 0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h], xmm2
+ 0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h], xmm3
+ 0x48, 0x8D, 0x15, 0, 0, 0, 0, // lea rdx, [__imp_<FUNCNAME>]
+ 0x48, 0x8D, 0x0D, 0, 0, 0, 0, // lea rcx, [___DELAY_IMPORT_...]
+ 0xE8, 0, 0, 0, 0, // call __delayLoadHelper2
+ 0x66, 0x0F, 0x6F, 0x04, 0x24, // movdqa xmm0, xmmword ptr [rsp]
+ 0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa xmm1, xmmword ptr [rsp+10h]
+ 0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa xmm2, xmmword ptr [rsp+20h]
+ 0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa xmm3, xmmword ptr [rsp+30h]
+ 0x48, 0x83, 0xC4, 0x48, // add rsp, 48h
+ 0x41, 0x59, // pop r9
+ 0x41, 0x58, // pop r8
+ 0x5A, // pop rdx
+ 0x59, // pop rcx
+ 0xFF, 0xE0, // jmp rax
+};
+
+static const uint8_t ThunkX86[] = {
+ 0x51, // push ecx
+ 0x52, // push edx
+ 0x68, 0, 0, 0, 0, // push offset ___imp__<FUNCNAME>
+ 0x68, 0, 0, 0, 0, // push offset ___DELAY_IMPORT_DESCRIPTOR_<DLLNAME>_dll
+ 0xE8, 0, 0, 0, 0, // call ___delayLoadHelper2@8
+ 0x5A, // pop edx
+ 0x59, // pop ecx
+ 0xFF, 0xE0, // jmp eax
+};
+
+// A chunk for the delay import thunk.
+class ThunkChunkX64 : public Chunk {
+public:
+ ThunkChunkX64(Defined *I, Chunk *D, Defined *H)
+ : Imp(I), Desc(D), Helper(H) {}
+
+ size_t getSize() const override { return sizeof(ThunkX64); }
+
+ void writeTo(uint8_t *Buf) const override {
+ memcpy(Buf + OutputSectionOff, ThunkX64, sizeof(ThunkX64));
+ write32le(Buf + OutputSectionOff + 36, Imp->getRVA() - RVA - 40);
+ write32le(Buf + OutputSectionOff + 43, Desc->getRVA() - RVA - 47);
+ write32le(Buf + OutputSectionOff + 48, Helper->getRVA() - RVA - 52);
+ }
+
+ Defined *Imp = nullptr;
+ Chunk *Desc = nullptr;
+ Defined *Helper = nullptr;
+};
+
+class ThunkChunkX86 : public Chunk {
+public:
+ ThunkChunkX86(Defined *I, Chunk *D, Defined *H)
+ : Imp(I), Desc(D), Helper(H) {}
+
+ size_t getSize() const override { return sizeof(ThunkX86); }
+
+ void writeTo(uint8_t *Buf) const override {
+ memcpy(Buf + OutputSectionOff, ThunkX86, sizeof(ThunkX86));
+ write32le(Buf + OutputSectionOff + 3, Imp->getRVA() + Config->ImageBase);
+ write32le(Buf + OutputSectionOff + 8, Desc->getRVA() + Config->ImageBase);
+ write32le(Buf + OutputSectionOff + 13, Helper->getRVA() - RVA - 17);
+ }
+
+ void getBaserels(std::vector<Baserel> *Res) override {
+ Res->emplace_back(RVA + 3);
+ Res->emplace_back(RVA + 8);
+ }
+
+ Defined *Imp = nullptr;
+ Chunk *Desc = nullptr;
+ Defined *Helper = nullptr;
+};
+
+// A chunk for the import descriptor table.
+class DelayAddressChunk : public Chunk {
+public:
+ explicit DelayAddressChunk(Chunk *C) : Thunk(C) {}
+ size_t getSize() const override { return ptrSize(); }
+
+ void writeTo(uint8_t *Buf) const override {
+ if (Config->is64()) {
+ write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);
+ } else {
+ write32le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);
+ }
+ }
+
+ void getBaserels(std::vector<Baserel> *Res) override {
+ Res->emplace_back(RVA);
+ }
+
+ Chunk *Thunk;
+};
+
+// Export table
+// Read Microsoft PE/COFF spec 5.3 for details.
+
+// A chunk for the export descriptor table.
+class ExportDirectoryChunk : public Chunk {
+public:
+ ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O)
+ : MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N),
+ OrdinalTab(O) {}
+
+ size_t getSize() const override {
+ return sizeof(export_directory_table_entry);
+ }
+
+ void writeTo(uint8_t *Buf) const override {
+ auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff);
+ E->NameRVA = DLLName->getRVA();
+ E->OrdinalBase = 0;
+ E->AddressTableEntries = MaxOrdinal + 1;
+ E->NumberOfNamePointers = NameTabSize;
+ E->ExportAddressTableRVA = AddressTab->getRVA();
+ E->NamePointerRVA = NameTab->getRVA();
+ E->OrdinalTableRVA = OrdinalTab->getRVA();
+ }
+
+ uint16_t MaxOrdinal;
+ uint16_t NameTabSize;
+ Chunk *DLLName;
+ Chunk *AddressTab;
+ Chunk *NameTab;
+ Chunk *OrdinalTab;
+};
+
+class AddressTableChunk : public Chunk {
+public:
+ explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {}
+ size_t getSize() const override { return Size * 4; }
+
+ void writeTo(uint8_t *Buf) const override {
+ for (Export &E : Config->Exports) {
+ auto *D = cast<Defined>(E.Sym->repl());
+ write32le(Buf + OutputSectionOff + E.Ordinal * 4, D->getRVA());
+ }
+ }
+
+private:
+ size_t Size;
+};
+
+class NamePointersChunk : public Chunk {
+public:
+ explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {}
+ size_t getSize() const override { return Chunks.size() * 4; }
+
+ void writeTo(uint8_t *Buf) const override {
+ uint8_t *P = Buf + OutputSectionOff;
+ for (Chunk *C : Chunks) {
+ write32le(P, C->getRVA());
+ P += 4;
+ }
+ }
+
+private:
+ std::vector<Chunk *> Chunks;
+};
+
+class ExportOrdinalChunk : public Chunk {
+public:
+ explicit ExportOrdinalChunk(size_t I) : Size(I) {}
+ size_t getSize() const override { return Size * 2; }
+
+ void writeTo(uint8_t *Buf) const override {
+ uint8_t *P = Buf + OutputSectionOff;
+ for (Export &E : Config->Exports) {
+ if (E.Noname)
+ continue;
+ write16le(P, E.Ordinal);
+ P += 2;
+ }
+ }
+
+private:
+ size_t Size;
+};
+
+} // anonymous namespace
+
+uint64_t IdataContents::getDirSize() {
+ return Dirs.size() * sizeof(ImportDirectoryTableEntry);
+}
+
+uint64_t IdataContents::getIATSize() {
+ return Addresses.size() * ptrSize();
+}
+
+// Returns a list of .idata contents.
+// See Microsoft PE/COFF spec 5.4 for details.
+std::vector<Chunk *> IdataContents::getChunks() {
+ create();
+ std::vector<Chunk *> V;
+ // The loader assumes a specific order of data.
+ // Add each type in the correct order.
+ for (std::unique_ptr<Chunk> &C : Dirs)
+ V.push_back(C.get());
+ for (std::unique_ptr<Chunk> &C : Lookups)
+ V.push_back(C.get());
+ for (std::unique_ptr<Chunk> &C : Addresses)
+ V.push_back(C.get());
+ for (std::unique_ptr<Chunk> &C : Hints)
+ V.push_back(C.get());
+ for (auto &P : DLLNames) {
+ std::unique_ptr<Chunk> &C = P.second;
+ V.push_back(C.get());
+ }
+ return V;
+}
+
+void IdataContents::create() {
+ std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
+
+ // Create .idata contents for each DLL.
+ for (std::vector<DefinedImportData *> &Syms : V) {
+ StringRef Name = Syms[0]->getDLLName();
+
+ // Create lookup and address tables. If they have external names,
+ // we need to create HintName chunks to store the names.
+ // If they don't (if they are import-by-ordinals), we store only
+ // ordinal values to the table.
+ size_t Base = Lookups.size();
+ for (DefinedImportData *S : Syms) {
+ uint16_t Ord = S->getOrdinal();
+ if (S->getExternalName().empty()) {
+ Lookups.push_back(make_unique<OrdinalOnlyChunk>(Ord));
+ Addresses.push_back(make_unique<OrdinalOnlyChunk>(Ord));
+ continue;
+ }
+ auto C = make_unique<HintNameChunk>(S->getExternalName(), Ord);
+ Lookups.push_back(make_unique<LookupChunk>(C.get()));
+ Addresses.push_back(make_unique<LookupChunk>(C.get()));
+ Hints.push_back(std::move(C));
+ }
+ // Terminate with null values.
+ Lookups.push_back(make_unique<NullChunk>(ptrSize()));
+ Addresses.push_back(make_unique<NullChunk>(ptrSize()));
+
+ for (int I = 0, E = Syms.size(); I < E; ++I)
+ Syms[I]->setLocation(Addresses[Base + I].get());
+
+ // Create the import table header.
+ if (!DLLNames.count(Name))
+ DLLNames[Name] = make_unique<StringChunk>(Name);
+ auto Dir = make_unique<ImportDirectoryChunk>(DLLNames[Name].get());
+ Dir->LookupTab = Lookups[Base].get();
+ Dir->AddressTab = Addresses[Base].get();
+ Dirs.push_back(std::move(Dir));
+ }
+ // Add null terminator.
+ Dirs.push_back(make_unique<NullChunk>(sizeof(ImportDirectoryTableEntry)));
+}
+
+std::vector<Chunk *> DelayLoadContents::getChunks() {
+ std::vector<Chunk *> V;
+ for (std::unique_ptr<Chunk> &C : Dirs)
+ V.push_back(C.get());
+ for (std::unique_ptr<Chunk> &C : Names)
+ V.push_back(C.get());
+ for (std::unique_ptr<Chunk> &C : HintNames)
+ V.push_back(C.get());
+ for (auto &P : DLLNames) {
+ std::unique_ptr<Chunk> &C = P.second;
+ V.push_back(C.get());
+ }
+ return V;
+}
+
+std::vector<Chunk *> DelayLoadContents::getDataChunks() {
+ std::vector<Chunk *> V;
+ for (std::unique_ptr<Chunk> &C : ModuleHandles)
+ V.push_back(C.get());
+ for (std::unique_ptr<Chunk> &C : Addresses)
+ V.push_back(C.get());
+ return V;
+}
+
+uint64_t DelayLoadContents::getDirSize() {
+ return Dirs.size() * sizeof(delay_import_directory_table_entry);
+}
+
+void DelayLoadContents::create(Defined *H) {
+ Helper = H;
+ std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);
+
+ // Create .didat contents for each DLL.
+ for (std::vector<DefinedImportData *> &Syms : V) {
+ StringRef Name = Syms[0]->getDLLName();
+
+ // Create the delay import table header.
+ if (!DLLNames.count(Name))
+ DLLNames[Name] = make_unique<StringChunk>(Name);
+ auto Dir = make_unique<DelayDirectoryChunk>(DLLNames[Name].get());
+
+ size_t Base = Addresses.size();
+ for (DefinedImportData *S : Syms) {
+ Chunk *T = newThunkChunk(S, Dir.get());
+ auto A = make_unique<DelayAddressChunk>(T);
+ Addresses.push_back(std::move(A));
+ Thunks.push_back(std::unique_ptr<Chunk>(T));
+ StringRef ExtName = S->getExternalName();
+ if (ExtName.empty()) {
+ Names.push_back(make_unique<OrdinalOnlyChunk>(S->getOrdinal()));
+ } else {
+ auto C = make_unique<HintNameChunk>(ExtName, 0);
+ Names.push_back(make_unique<LookupChunk>(C.get()));
+ HintNames.push_back(std::move(C));
+ }
+ }
+ // Terminate with null values.
+ Addresses.push_back(make_unique<NullChunk>(8));
+ Names.push_back(make_unique<NullChunk>(8));
+
+ for (int I = 0, E = Syms.size(); I < E; ++I)
+ Syms[I]->setLocation(Addresses[Base + I].get());
+ auto *MH = new NullChunk(8);
+ MH->setAlign(8);
+ ModuleHandles.push_back(std::unique_ptr<Chunk>(MH));
+
+ // Fill the delay import table header fields.
+ Dir->ModuleHandle = MH;
+ Dir->AddressTab = Addresses[Base].get();
+ Dir->NameTab = Names[Base].get();
+ Dirs.push_back(std::move(Dir));
+ }
+ // Add null terminator.
+ Dirs.push_back(
+ make_unique<NullChunk>(sizeof(delay_import_directory_table_entry)));
+}
+
+Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) {
+ switch (Config->Machine) {
+ case AMD64:
+ return new ThunkChunkX64(S, Dir, Helper);
+ case I386:
+ return new ThunkChunkX86(S, Dir, Helper);
+ default:
+ llvm_unreachable("unsupported machine type");
+ }
+}
+
+EdataContents::EdataContents() {
+ uint16_t MaxOrdinal = 0;
+ for (Export &E : Config->Exports)
+ MaxOrdinal = std::max(MaxOrdinal, E.Ordinal);
+
+ auto *DLLName = new StringChunk(sys::path::filename(Config->OutputFile));
+ auto *AddressTab = new AddressTableChunk(MaxOrdinal);
+ std::vector<Chunk *> Names;
+ for (Export &E : Config->Exports)
+ if (!E.Noname)
+ Names.push_back(new StringChunk(E.ExportName));
+ auto *NameTab = new NamePointersChunk(Names);
+ auto *OrdinalTab = new ExportOrdinalChunk(Names.size());
+ auto *Dir = new ExportDirectoryChunk(MaxOrdinal, Names.size(), DLLName,
+ AddressTab, NameTab, OrdinalTab);
+ Chunks.push_back(std::unique_ptr<Chunk>(Dir));
+ Chunks.push_back(std::unique_ptr<Chunk>(DLLName));
+ Chunks.push_back(std::unique_ptr<Chunk>(AddressTab));
+ Chunks.push_back(std::unique_ptr<Chunk>(NameTab));
+ Chunks.push_back(std::unique_ptr<Chunk>(OrdinalTab));
+ for (Chunk *C : Names)
+ Chunks.push_back(std::unique_ptr<Chunk>(C));
+}
+
+} // namespace coff
+} // namespace lld
diff --git a/COFF/DLL.h b/COFF/DLL.h
new file mode 100644
index 000000000000..83a12df185c2
--- /dev/null
+++ b/COFF/DLL.h
@@ -0,0 +1,84 @@
+//===- DLL.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_DLL_H
+#define LLD_COFF_DLL_H
+
+#include "Chunks.h"
+#include "Symbols.h"
+
+namespace lld {
+namespace coff {
+
+// Windows-specific.
+// IdataContents creates all chunks for the DLL import table.
+// You are supposed to call add() to add symbols and then
+// call getChunks() to get a list of chunks.
+class IdataContents {
+public:
+ void add(DefinedImportData *Sym) { Imports.push_back(Sym); }
+ bool empty() { return Imports.empty(); }
+ std::vector<Chunk *> getChunks();
+
+ uint64_t getDirRVA() { return Dirs[0]->getRVA(); }
+ uint64_t getDirSize();
+ uint64_t getIATRVA() { return Addresses[0]->getRVA(); }
+ uint64_t getIATSize();
+
+private:
+ void create();
+
+ std::vector<DefinedImportData *> Imports;
+ std::vector<std::unique_ptr<Chunk>> Dirs;
+ std::vector<std::unique_ptr<Chunk>> Lookups;
+ std::vector<std::unique_ptr<Chunk>> Addresses;
+ std::vector<std::unique_ptr<Chunk>> Hints;
+ std::map<StringRef, std::unique_ptr<Chunk>> DLLNames;
+};
+
+// Windows-specific.
+// DelayLoadContents creates all chunks for the delay-load DLL import table.
+class DelayLoadContents {
+public:
+ void add(DefinedImportData *Sym) { Imports.push_back(Sym); }
+ bool empty() { return Imports.empty(); }
+ void create(Defined *Helper);
+ std::vector<Chunk *> getChunks();
+ std::vector<Chunk *> getDataChunks();
+ std::vector<std::unique_ptr<Chunk>> &getCodeChunks() { return Thunks; }
+
+ uint64_t getDirRVA() { return Dirs[0]->getRVA(); }
+ uint64_t getDirSize();
+
+private:
+ Chunk *newThunkChunk(DefinedImportData *S, Chunk *Dir);
+
+ Defined *Helper;
+ std::vector<DefinedImportData *> Imports;
+ std::vector<std::unique_ptr<Chunk>> Dirs;
+ std::vector<std::unique_ptr<Chunk>> ModuleHandles;
+ std::vector<std::unique_ptr<Chunk>> Addresses;
+ std::vector<std::unique_ptr<Chunk>> Names;
+ std::vector<std::unique_ptr<Chunk>> HintNames;
+ std::vector<std::unique_ptr<Chunk>> Thunks;
+ std::map<StringRef, std::unique_ptr<Chunk>> DLLNames;
+};
+
+// Windows-specific.
+// EdataContents creates all chunks for the DLL export table.
+class EdataContents {
+public:
+ EdataContents();
+ std::vector<std::unique_ptr<Chunk>> Chunks;
+};
+
+} // namespace coff
+} // namespace lld
+
+#endif
diff --git a/COFF/Driver.cpp b/COFF/Driver.cpp
new file mode 100644
index 000000000000..f528dafd9857
--- /dev/null
+++ b/COFF/Driver.cpp
@@ -0,0 +1,677 @@
+//===- Driver.cpp ---------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Config.h"
+#include "Driver.h"
+#include "Error.h"
+#include "InputFiles.h"
+#include "SymbolTable.h"
+#include "Symbols.h"
+#include "Writer.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/LibDriver/LibDriver.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Option/Option.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+#include "llvm/Support/TargetSelect.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <memory>
+
+using namespace llvm;
+using namespace llvm::COFF;
+using llvm::sys::Process;
+using llvm::sys::fs::OpenFlags;
+using llvm::sys::fs::file_magic;
+using llvm::sys::fs::identify_magic;
+
+namespace lld {
+namespace coff {
+
+Configuration *Config;
+LinkerDriver *Driver;
+
+void link(llvm::ArrayRef<const char *> Args) {
+ Configuration C;
+ LinkerDriver D;
+ Config = &C;
+ Driver = &D;
+ return Driver->link(Args);
+}
+
+// Drop directory components and replace extension with ".exe".
+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();
+}
+
+// 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;
+ MemoryBufferRef MBRef = MB->getMemBufferRef();
+ OwningMBs.push_back(std::move(MB)); // take ownership
+ return MBRef;
+}
+
+static std::unique_ptr<InputFile> createFile(MemoryBufferRef MB) {
+ // File type is detected by contents, not by file extension.
+ file_magic Magic = identify_magic(MB.getBuffer());
+ if (Magic == file_magic::archive)
+ return std::unique_ptr<InputFile>(new ArchiveFile(MB));
+ if (Magic == file_magic::bitcode)
+ return std::unique_ptr<InputFile>(new BitcodeFile(MB));
+ if (Config->OutputFile == "")
+ Config->OutputFile = getOutputPath(MB.getBufferIdentifier());
+ return std::unique_ptr<InputFile>(new ObjectFile(MB));
+}
+
+static bool isDecorated(StringRef Sym) {
+ return Sym.startswith("_") || Sym.startswith("@") || Sym.startswith("?");
+}
+
+// Parses .drectve section contents and returns a list of files
+// specified by /defaultlib.
+void LinkerDriver::parseDirectives(StringRef S) {
+ llvm::opt::InputArgList Args = Parser.parse(S);
+
+ for (auto *Arg : Args) {
+ switch (Arg->getOption().getID()) {
+ case OPT_alternatename:
+ parseAlternateName(Arg->getValue());
+ break;
+ case OPT_defaultlib:
+ if (Optional<StringRef> Path = findLib(Arg->getValue())) {
+ MemoryBufferRef MB = openFile(*Path);
+ Symtab.addFile(createFile(MB));
+ }
+ break;
+ case OPT_export: {
+ Export E = parseExport(Arg->getValue());
+ E.Directives = true;
+ Config->Exports.push_back(E);
+ break;
+ }
+ case OPT_failifmismatch:
+ checkFailIfMismatch(Arg->getValue());
+ break;
+ case OPT_incl:
+ addUndefined(Arg->getValue());
+ break;
+ case OPT_merge:
+ parseMerge(Arg->getValue());
+ break;
+ case OPT_nodefaultlib:
+ Config->NoDefaultLibs.insert(doFindLib(Arg->getValue()));
+ break;
+ case OPT_editandcontinue:
+ case OPT_guardsym:
+ case OPT_throwingnew:
+ break;
+ default:
+ error(Twine(Arg->getSpelling()) + " is not allowed in .drectve");
+ }
+ }
+}
+
+// Find file from search paths. You can omit ".obj", this function takes
+// care of that. Note that the returned path is not guaranteed to exist.
+StringRef LinkerDriver::doFindFile(StringRef Filename) {
+ bool hasPathSep = (Filename.find_first_of("/\\") != StringRef::npos);
+ if (hasPathSep)
+ return Filename;
+ bool hasExt = (Filename.find('.') != StringRef::npos);
+ for (StringRef Dir : SearchPaths) {
+ SmallString<128> Path = Dir;
+ llvm::sys::path::append(Path, Filename);
+ if (llvm::sys::fs::exists(Path.str()))
+ return Alloc.save(Path.str());
+ if (!hasExt) {
+ Path.append(".obj");
+ if (llvm::sys::fs::exists(Path.str()))
+ return Alloc.save(Path.str());
+ }
+ }
+ return Filename;
+}
+
+// Resolves a file path. This never returns the same path
+// (in that case, it returns None).
+Optional<StringRef> LinkerDriver::findFile(StringRef Filename) {
+ StringRef Path = doFindFile(Filename);
+ bool Seen = !VisitedFiles.insert(Path.lower()).second;
+ if (Seen)
+ return None;
+ return Path;
+}
+
+// Find library file from search path.
+StringRef LinkerDriver::doFindLib(StringRef Filename) {
+ // Add ".lib" to Filename if that has no file extension.
+ bool hasExt = (Filename.find('.') != StringRef::npos);
+ if (!hasExt)
+ Filename = Alloc.save(Filename + ".lib");
+ return doFindFile(Filename);
+}
+
+// Resolves a library path. /nodefaultlib options are taken into
+// consideration. This never returns the same path (in that case,
+// it returns None).
+Optional<StringRef> LinkerDriver::findLib(StringRef Filename) {
+ if (Config->NoDefaultLibAll)
+ return None;
+ StringRef Path = doFindLib(Filename);
+ if (Config->NoDefaultLibs.count(Path))
+ return None;
+ bool Seen = !VisitedFiles.insert(Path.lower()).second;
+ if (Seen)
+ return None;
+ return Path;
+}
+
+// Parses LIB environment which contains a list of search paths.
+void LinkerDriver::addLibSearchPaths() {
+ Optional<std::string> EnvOpt = Process::GetEnv("LIB");
+ if (!EnvOpt.hasValue())
+ return;
+ StringRef Env = Alloc.save(*EnvOpt);
+ while (!Env.empty()) {
+ StringRef Path;
+ std::tie(Path, Env) = Env.split(';');
+ SearchPaths.push_back(Path);
+ }
+}
+
+Undefined *LinkerDriver::addUndefined(StringRef Name) {
+ Undefined *U = Symtab.addUndefined(Name);
+ Config->GCRoot.insert(U);
+ return U;
+}
+
+// Symbol names are mangled by appending "_" prefix on x86.
+StringRef LinkerDriver::mangle(StringRef Sym) {
+ assert(Config->Machine != IMAGE_FILE_MACHINE_UNKNOWN);
+ if (Config->Machine == I386)
+ return Alloc.save("_" + Sym);
+ return Sym;
+}
+
+// Windows specific -- find default entry point name.
+StringRef LinkerDriver::findDefaultEntry() {
+ // User-defined main functions and their corresponding entry points.
+ static const char *Entries[][2] = {
+ {"main", "mainCRTStartup"},
+ {"wmain", "wmainCRTStartup"},
+ {"WinMain", "WinMainCRTStartup"},
+ {"wWinMain", "wWinMainCRTStartup"},
+ };
+ for (auto E : Entries) {
+ StringRef Entry = Symtab.findMangle(mangle(E[0]));
+ if (!Entry.empty() && !isa<Undefined>(Symtab.find(Entry)->Body))
+ return mangle(E[1]);
+ }
+ return "";
+}
+
+WindowsSubsystem LinkerDriver::inferSubsystem() {
+ if (Config->DLL)
+ return IMAGE_SUBSYSTEM_WINDOWS_GUI;
+ if (Symtab.findUnderscore("main") || Symtab.findUnderscore("wmain"))
+ return IMAGE_SUBSYSTEM_WINDOWS_CUI;
+ if (Symtab.findUnderscore("WinMain") || Symtab.findUnderscore("wWinMain"))
+ return IMAGE_SUBSYSTEM_WINDOWS_GUI;
+ return IMAGE_SUBSYSTEM_UNKNOWN;
+}
+
+static uint64_t getDefaultImageBase() {
+ if (Config->is64())
+ return Config->DLL ? 0x180000000 : 0x140000000;
+ return Config->DLL ? 0x10000000 : 0x400000;
+}
+
+void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
+ // If the first command line argument is "/lib", link.exe acts like lib.exe.
+ // 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");
+ return;
+ }
+
+ // Needed for LTO.
+ llvm::InitializeAllTargetInfos();
+ llvm::InitializeAllTargets();
+ llvm::InitializeAllTargetMCs();
+ llvm::InitializeAllAsmParsers();
+ llvm::InitializeAllAsmPrinters();
+ llvm::InitializeAllDisassemblers();
+
+ // Parse command line options.
+ llvm::opt::InputArgList Args = Parser.parseLINK(ArgsArr.slice(1));
+
+ // Handle /help
+ if (Args.hasArg(OPT_help)) {
+ printHelp(ArgsArr[0]);
+ return;
+ }
+
+ if (Args.filtered_begin(OPT_INPUT) == Args.filtered_end())
+ error("no input files.");
+
+ // Construct search path list.
+ SearchPaths.push_back("");
+ for (auto *Arg : Args.filtered(OPT_libpath))
+ SearchPaths.push_back(Arg->getValue());
+ addLibSearchPaths();
+
+ // Handle /out
+ if (auto *Arg = Args.getLastArg(OPT_out))
+ Config->OutputFile = Arg->getValue();
+
+ // Handle /verbose
+ if (Args.hasArg(OPT_verbose))
+ Config->Verbose = true;
+
+ // Handle /force or /force:unresolved
+ if (Args.hasArg(OPT_force) || Args.hasArg(OPT_force_unresolved))
+ Config->Force = true;
+
+ // Handle /debug
+ if (Args.hasArg(OPT_debug))
+ Config->Debug = true;
+
+ // Handle /noentry
+ if (Args.hasArg(OPT_noentry)) {
+ if (!Args.hasArg(OPT_dll))
+ error("/noentry must be specified with /dll");
+ Config->NoEntry = true;
+ }
+
+ // Handle /dll
+ if (Args.hasArg(OPT_dll)) {
+ Config->DLL = true;
+ Config->ManifestID = 2;
+ }
+
+ // Handle /fixed
+ if (Args.hasArg(OPT_fixed)) {
+ if (Args.hasArg(OPT_dynamicbase))
+ error("/fixed must not be specified with /dynamicbase");
+ Config->Relocatable = false;
+ Config->DynamicBase = false;
+ }
+
+ // Handle /machine
+ if (auto *Arg = Args.getLastArg(OPT_machine))
+ Config->Machine = getMachineType(Arg->getValue());
+
+ // Handle /nodefaultlib:<filename>
+ for (auto *Arg : Args.filtered(OPT_nodefaultlib))
+ Config->NoDefaultLibs.insert(doFindLib(Arg->getValue()));
+
+ // Handle /nodefaultlib
+ if (Args.hasArg(OPT_nodefaultlib_all))
+ Config->NoDefaultLibAll = true;
+
+ // Handle /base
+ if (auto *Arg = Args.getLastArg(OPT_base))
+ parseNumbers(Arg->getValue(), &Config->ImageBase);
+
+ // Handle /stack
+ if (auto *Arg = Args.getLastArg(OPT_stack))
+ parseNumbers(Arg->getValue(), &Config->StackReserve, &Config->StackCommit);
+
+ // Handle /heap
+ if (auto *Arg = Args.getLastArg(OPT_heap))
+ parseNumbers(Arg->getValue(), &Config->HeapReserve, &Config->HeapCommit);
+
+ // Handle /version
+ if (auto *Arg = Args.getLastArg(OPT_version))
+ parseVersion(Arg->getValue(), &Config->MajorImageVersion,
+ &Config->MinorImageVersion);
+
+ // Handle /subsystem
+ if (auto *Arg = Args.getLastArg(OPT_subsystem))
+ parseSubsystem(Arg->getValue(), &Config->Subsystem, &Config->MajorOSVersion,
+ &Config->MinorOSVersion);
+
+ // Handle /alternatename
+ for (auto *Arg : Args.filtered(OPT_alternatename))
+ parseAlternateName(Arg->getValue());
+
+ // Handle /include
+ for (auto *Arg : Args.filtered(OPT_incl))
+ addUndefined(Arg->getValue());
+
+ // Handle /implib
+ if (auto *Arg = Args.getLastArg(OPT_implib))
+ Config->Implib = Arg->getValue();
+
+ // Handle /opt
+ for (auto *Arg : Args.filtered(OPT_opt)) {
+ std::string Str = StringRef(Arg->getValue()).lower();
+ SmallVector<StringRef, 1> Vec;
+ StringRef(Str).split(Vec, ',');
+ for (StringRef S : Vec) {
+ if (S == "noref") {
+ Config->DoGC = false;
+ Config->DoICF = false;
+ continue;
+ }
+ if (S == "icf" || StringRef(S).startswith("icf=")) {
+ Config->DoICF = true;
+ continue;
+ }
+ if (S == "noicf") {
+ Config->DoICF = false;
+ continue;
+ }
+ if (StringRef(S).startswith("lldlto=")) {
+ StringRef OptLevel = StringRef(S).substr(7);
+ if (OptLevel.getAsInteger(10, Config->LTOOptLevel) ||
+ Config->LTOOptLevel > 3)
+ error("/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);
+ continue;
+ }
+ if (S != "ref" && S != "lbr" && S != "nolbr")
+ error(Twine("/opt: unknown option: ") + S);
+ }
+ }
+
+ // Handle /failifmismatch
+ for (auto *Arg : Args.filtered(OPT_failifmismatch))
+ checkFailIfMismatch(Arg->getValue());
+
+ // Handle /merge
+ for (auto *Arg : Args.filtered(OPT_merge))
+ parseMerge(Arg->getValue());
+
+ // Handle /manifest
+ if (auto *Arg = Args.getLastArg(OPT_manifest_colon))
+ parseManifest(Arg->getValue());
+
+ // Handle /manifestuac
+ if (auto *Arg = Args.getLastArg(OPT_manifestuac))
+ parseManifestUAC(Arg->getValue());
+
+ // Handle /manifestdependency
+ if (auto *Arg = Args.getLastArg(OPT_manifestdependency))
+ Config->ManifestDependency = Arg->getValue();
+
+ // Handle /manifestfile
+ if (auto *Arg = Args.getLastArg(OPT_manifestfile))
+ Config->ManifestFile = Arg->getValue();
+
+ // Handle miscellaneous boolean flags.
+ if (Args.hasArg(OPT_allowbind_no))
+ Config->AllowBind = false;
+ if (Args.hasArg(OPT_allowisolation_no))
+ Config->AllowIsolation = false;
+ if (Args.hasArg(OPT_dynamicbase_no))
+ Config->DynamicBase = false;
+ if (Args.hasArg(OPT_nxcompat_no))
+ Config->NxCompat = false;
+ if (Args.hasArg(OPT_tsaware_no))
+ Config->TerminalServerAware = false;
+ if (Args.hasArg(OPT_nosymtab))
+ Config->WriteSymtab = false;
+
+ // Create a list of input files. Files can be given as arguments
+ // for /defaultlib option.
+ std::vector<StringRef> Paths;
+ std::vector<MemoryBufferRef> MBs;
+ for (auto *Arg : Args.filtered(OPT_INPUT))
+ if (Optional<StringRef> Path = findFile(Arg->getValue()))
+ Paths.push_back(*Path);
+ for (auto *Arg : Args.filtered(OPT_defaultlib))
+ if (Optional<StringRef> Path = findLib(Arg->getValue()))
+ Paths.push_back(*Path);
+ for (StringRef Path : Paths)
+ MBs.push_back(openFile(Path));
+
+ // Windows specific -- Create a resource file containing a manifest file.
+ if (Config->Manifest == Configuration::Embed) {
+ std::unique_ptr<MemoryBuffer> MB = createManifestRes();
+ MBs.push_back(MB->getMemBufferRef());
+ OwningMBs.push_back(std::move(MB)); // take ownership
+ }
+
+ // Windows specific -- Input files can be Windows resource files (.res files).
+ // We invoke cvtres.exe to convert resource files to a regular COFF file
+ // then link the result file normally.
+ std::vector<MemoryBufferRef> Resources;
+ auto NotResource = [](MemoryBufferRef MB) {
+ return identify_magic(MB.getBuffer()) != file_magic::windows_resource;
+ };
+ auto It = std::stable_partition(MBs.begin(), MBs.end(), NotResource);
+ if (It != MBs.end()) {
+ Resources.insert(Resources.end(), It, MBs.end());
+ MBs.erase(It, MBs.end());
+ }
+
+ // Read all input files given via the command line. Note that step()
+ // doesn't read files that are specified by directive sections.
+ for (MemoryBufferRef MB : MBs)
+ Symtab.addFile(createFile(MB));
+ Symtab.step();
+
+ // Determine machine type and check if all object files are
+ // for the same CPU type. Note that this needs to be done before
+ // any call to mangle().
+ for (std::unique_ptr<InputFile> &File : Symtab.getFiles()) {
+ MachineTypes MT = File->getMachineType();
+ if (MT == IMAGE_FILE_MACHINE_UNKNOWN)
+ continue;
+ if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) {
+ Config->Machine = MT;
+ continue;
+ }
+ if (Config->Machine != MT)
+ error(Twine(File->getShortName()) + ": machine type " + machineToStr(MT) +
+ " conflicts with " + machineToStr(Config->Machine));
+ }
+ if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) {
+ llvm::errs() << "warning: /machine is not specified. x64 is assumed.\n";
+ Config->Machine = AMD64;
+ }
+
+ // Windows specific -- Convert Windows resource files to a COFF file.
+ if (!Resources.empty()) {
+ std::unique_ptr<MemoryBuffer> MB = convertResToCOFF(Resources);
+ Symtab.addFile(createFile(MB->getMemBufferRef()));
+ OwningMBs.push_back(std::move(MB)); // take ownership
+ }
+
+ // Handle /largeaddressaware
+ if (Config->is64() || Args.hasArg(OPT_largeaddressaware))
+ Config->LargeAddressAware = true;
+
+ // Handle /highentropyva
+ if (Config->is64() && !Args.hasArg(OPT_highentropyva_no))
+ Config->HighEntropyVA = true;
+
+ // Handle /entry and /dll
+ if (auto *Arg = Args.getLastArg(OPT_entry)) {
+ Config->Entry = addUndefined(mangle(Arg->getValue()));
+ } else if (Args.hasArg(OPT_dll) && !Config->NoEntry) {
+ StringRef S = (Config->Machine == I386) ? "__DllMainCRTStartup@12"
+ : "_DllMainCRTStartup";
+ Config->Entry = addUndefined(S);
+ } else if (!Config->NoEntry) {
+ // Windows specific -- If entry point name is not given, we need to
+ // infer that from user-defined entry name.
+ StringRef S = findDefaultEntry();
+ if (S.empty())
+ error("entry point must be defined");
+ Config->Entry = addUndefined(S);
+ if (Config->Verbose)
+ llvm::outs() << "Entry name inferred: " << S << "\n";
+ }
+
+ // Handle /export
+ for (auto *Arg : Args.filtered(OPT_export)) {
+ Export E = parseExport(Arg->getValue());
+ if (Config->Machine == I386) {
+ if (!isDecorated(E.Name))
+ E.Name = Alloc.save("_" + E.Name);
+ if (!E.ExtName.empty() && !isDecorated(E.ExtName))
+ E.ExtName = Alloc.save("_" + E.ExtName);
+ }
+ Config->Exports.push_back(E);
+ }
+
+ // Handle /def
+ if (auto *Arg = Args.getLastArg(OPT_deffile)) {
+ MemoryBufferRef MB = openFile(Arg->getValue());
+ // parseModuleDefs mutates Config object.
+ parseModuleDefs(MB, &Alloc);
+ }
+
+ // Handle /delayload
+ for (auto *Arg : Args.filtered(OPT_delayload)) {
+ Config->DelayLoads.insert(StringRef(Arg->getValue()).lower());
+ if (Config->Machine == I386) {
+ Config->DelayLoadHelper = addUndefined("___delayLoadHelper2@8");
+ } else {
+ Config->DelayLoadHelper = addUndefined("__delayLoadHelper2");
+ }
+ }
+
+ // Set default image base if /base is not given.
+ if (Config->ImageBase == uint64_t(-1))
+ Config->ImageBase = getDefaultImageBase();
+
+ Symtab.addRelative(mangle("__ImageBase"), 0);
+ if (Config->Machine == I386) {
+ Config->SEHTable = Symtab.addRelative("___safe_se_handler_table", 0);
+ Config->SEHCount = Symtab.addAbsolute("___safe_se_handler_count", 0);
+ }
+
+ // We do not support /guard:cf (control flow protection) yet.
+ // Define CFG symbols anyway so that we can link MSVC 2015 CRT.
+ Symtab.addAbsolute(mangle("__guard_fids_table"), 0);
+ Symtab.addAbsolute(mangle("__guard_fids_count"), 0);
+ Symtab.addAbsolute(mangle("__guard_flags"), 0x100);
+
+ // Read as much files as we can from directives sections.
+ Symtab.run();
+
+ // Resolve auxiliary symbols until we get a convergence.
+ // (Trying to resolve a symbol may trigger a Lazy symbol to load a new file.
+ // A new file may contain a directive section to add new command line options.
+ // That's why we have to repeat until converge.)
+ for (;;) {
+ // Windows specific -- if entry point is not found,
+ // search for its mangled names.
+ if (Config->Entry)
+ Symtab.mangleMaybe(Config->Entry);
+
+ // Windows specific -- Make sure we resolve all dllexported symbols.
+ for (Export &E : Config->Exports) {
+ E.Sym = addUndefined(E.Name);
+ if (!E.Directives)
+ Symtab.mangleMaybe(E.Sym);
+ }
+
+ // Add weak aliases. Weak aliases is a mechanism to give remaining
+ // undefined symbols final chance to be resolved successfully.
+ for (auto Pair : Config->AlternateNames) {
+ StringRef From = Pair.first;
+ StringRef To = Pair.second;
+ Symbol *Sym = Symtab.find(From);
+ if (!Sym)
+ continue;
+ if (auto *U = dyn_cast<Undefined>(Sym->Body))
+ if (!U->WeakAlias)
+ U->WeakAlias = Symtab.addUndefined(To);
+ }
+
+ // Windows specific -- if __load_config_used can be resolved, resolve it.
+ if (Symtab.findUnderscore("_load_config_used"))
+ addUndefined(mangle("_load_config_used"));
+
+ if (Symtab.queueEmpty())
+ break;
+ Symtab.run();
+ }
+
+ // Do LTO by compiling bitcode input files to a set of native COFF files then
+ // link those files.
+ Symtab.addCombinedLTOObjects();
+
+ // Make sure we have resolved all symbols.
+ Symtab.reportRemainingUndefines(/*Resolve=*/true);
+
+ // Windows specific -- if no /subsystem is given, we need to infer
+ // that from entry point name.
+ if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) {
+ Config->Subsystem = inferSubsystem();
+ if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN)
+ error("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");
+
+ // Windows specific -- when we are creating a .dll file, we also
+ // need to create a .lib file.
+ if (!Config->Exports.empty() || Config->DLL) {
+ fixupExports();
+ writeImportLibrary();
+ assignExportOrdinals();
+ }
+
+ // Windows specific -- Create a side-by-side manifest file.
+ if (Config->Manifest == Configuration::SideBySide)
+ createSideBySideManifest();
+
+ // Create a dummy PDB file to satisfy build sytem rules.
+ if (auto *Arg = Args.getLastArg(OPT_pdb))
+ createPDB(Arg->getValue());
+
+ // Identify unreferenced COMDAT sections.
+ if (Config->DoGC)
+ markLive(Symtab.getChunks());
+
+ // Identify identical COMDAT sections to merge them.
+ if (Config->DoICF)
+ doICF(Symtab.getChunks());
+
+ // Write the result.
+ writeResult(&Symtab);
+
+ // Create a symbol map file containing symbol VAs and their names
+ // to help debugging.
+ 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");
+ Symtab.printMap(Out);
+ }
+ // Call exit to avoid calling destructors.
+ exit(0);
+}
+
+} // namespace coff
+} // namespace lld
diff --git a/COFF/Driver.h b/COFF/Driver.h
new file mode 100644
index 000000000000..e50da20cbb04
--- /dev/null
+++ b/COFF/Driver.h
@@ -0,0 +1,180 @@
+//===- Driver.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_DRIVER_H
+#define LLD_COFF_DRIVER_H
+
+#include "Config.h"
+#include "SymbolTable.h"
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/Optional.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Option/Arg.h"
+#include "llvm/Option/ArgList.h"
+#include "llvm/Support/StringSaver.h"
+#include <memory>
+#include <set>
+#include <vector>
+
+namespace lld {
+namespace coff {
+
+class LinkerDriver;
+extern LinkerDriver *Driver;
+
+using llvm::COFF::MachineTypes;
+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);
+
+// Implemented in ICF.cpp.
+void doICF(const std::vector<Chunk *> &Chunks);
+
+class ArgParser {
+public:
+ ArgParser() : Alloc(AllocAux) {}
+ // Parses command line options.
+ llvm::opt::InputArgList parse(llvm::ArrayRef<const char *> Args);
+
+ // Concatenate LINK environment varirable and given arguments and parse them.
+ llvm::opt::InputArgList parseLINK(llvm::ArrayRef<const char *> Args);
+
+ // Tokenizes a given string and then parses as command line options.
+ llvm::opt::InputArgList parse(StringRef S) { return parse(tokenize(S)); }
+
+private:
+ std::vector<const char *> tokenize(StringRef S);
+
+ std::vector<const char *> replaceResponseFiles(std::vector<const char *>);
+
+ llvm::BumpPtrAllocator AllocAux;
+ llvm::StringSaver Alloc;
+};
+
+class LinkerDriver {
+public:
+ LinkerDriver() : Alloc(AllocAux) {}
+ void link(llvm::ArrayRef<const char *> Args);
+
+ // Used by the resolver to parse .drectve section contents.
+ void parseDirectives(StringRef S);
+
+private:
+ llvm::BumpPtrAllocator AllocAux;
+ llvm::StringSaver Alloc;
+ ArgParser Parser;
+ SymbolTable Symtab;
+
+ // Opens a file. Path has to be resolved already.
+ MemoryBufferRef openFile(StringRef Path);
+
+ // Searches a file from search paths.
+ Optional<StringRef> findFile(StringRef Filename);
+ Optional<StringRef> findLib(StringRef Filename);
+ StringRef doFindFile(StringRef Filename);
+ StringRef doFindLib(StringRef Filename);
+
+ // Parses LIB environment which contains a list of search paths.
+ void addLibSearchPaths();
+
+ // Library search path. The first element is always "" (current directory).
+ std::vector<StringRef> SearchPaths;
+ std::set<std::string> VisitedFiles;
+
+ Undefined *addUndefined(StringRef Sym);
+ StringRef mangle(StringRef Sym);
+
+ // Windows specific -- "main" is not the only main function in Windows.
+ // You can choose one from these four -- {w,}{WinMain,main}.
+ // There are four different entry point functions for them,
+ // {w,}{WinMain,main}CRTStartup, respectively. The linker needs to
+ // choose the right one depending on which "main" function is defined.
+ // This function looks up the symbol table and resolve corresponding
+ // entry point name.
+ StringRef findDefaultEntry();
+ WindowsSubsystem inferSubsystem();
+
+ // Driver is the owner of all opened files.
+ // InputFiles have MemoryBufferRefs to them.
+ std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;
+};
+
+void parseModuleDefs(MemoryBufferRef MB, llvm::StringSaver *Alloc);
+void writeImportLibrary();
+
+// Functions below this line are defined in DriverUtils.cpp.
+
+void printHelp(const char *Argv0);
+
+// For /machine option.
+MachineTypes getMachineType(StringRef Arg);
+StringRef machineToStr(MachineTypes MT);
+
+// Parses a string in the form of "<integer>[,<integer>]".
+void parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size = nullptr);
+
+// Parses a string in the form of "<integer>[.<integer>]".
+// Minor's default value is 0.
+void parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor);
+
+// Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".
+void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major,
+ uint32_t *Minor);
+
+void parseAlternateName(StringRef);
+void parseMerge(StringRef);
+
+// Parses a string in the form of "EMBED[,=<integer>]|NO".
+void parseManifest(StringRef Arg);
+
+// Parses a string in the form of "level=<string>|uiAccess=<string>"
+void parseManifestUAC(StringRef Arg);
+
+// Create a resource file containing a manifest XML.
+std::unique_ptr<MemoryBuffer> createManifestRes();
+void createSideBySideManifest();
+
+// Used for dllexported symbols.
+Export parseExport(StringRef Arg);
+void fixupExports();
+void assignExportOrdinals();
+
+// Parses a string in the form of "key=value" and check
+// if value matches previous values for the key.
+// This feature used in the directive section to reject
+// incompatible objects.
+void checkFailIfMismatch(StringRef Arg);
+
+// Convert Windows resource files (.res files) to a .obj file
+// using cvtres.exe.
+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
+enum {
+ OPT_INVALID = 0,
+#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID,
+#include "Options.inc"
+#undef OPTION
+};
+
+} // namespace coff
+} // namespace lld
+
+#endif
diff --git a/COFF/DriverUtils.cpp b/COFF/DriverUtils.cpp
new file mode 100644
index 000000000000..391a8ab66420
--- /dev/null
+++ b/COFF/DriverUtils.cpp
@@ -0,0 +1,718 @@
+//===- DriverUtils.cpp ----------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains utility functions for the driver. Because there
+// are so many small functions, we created this separate file to make
+// Driver.cpp less cluttered.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Config.h"
+#include "Driver.h"
+#include "Error.h"
+#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"
+#include <memory>
+
+using namespace llvm::COFF;
+using namespace llvm;
+using llvm::cl::ExpandResponseFiles;
+using llvm::cl::TokenizeWindowsCommandLine;
+using llvm::sys::Process;
+
+namespace lld {
+namespace coff {
+namespace {
+
+class Executor {
+public:
+ explicit Executor(StringRef S) : Saver(Alloc), Prog(Saver.save(S)) {}
+ void add(StringRef S) { Args.push_back(Saver.save(S)); }
+ void add(std::string &S) { Args.push_back(Saver.save(S)); }
+ void add(Twine S) { Args.push_back(Saver.save(S)); }
+ void add(const char *S) { Args.push_back(Saver.save(S)); }
+
+ void run() {
+ ErrorOr<std::string> ExeOrErr = llvm::sys::findProgramByName(Prog);
+ error(ExeOrErr, Twine("unable to find ") + Prog + " in PATH: ");
+ const char *Exe = Saver.save(*ExeOrErr);
+ Args.insert(Args.begin(), Exe);
+ Args.push_back(nullptr);
+ if (llvm::sys::ExecuteAndWait(Args[0], Args.data()) != 0) {
+ for (const char *S : Args)
+ if (S)
+ llvm::errs() << S << " ";
+ error("failed");
+ }
+ }
+
+private:
+ llvm::BumpPtrAllocator Alloc;
+ llvm::StringSaver Saver;
+ StringRef Prog;
+ std::vector<const char *> Args;
+};
+
+} // anonymous namespace
+
+// Returns /machine's value.
+MachineTypes getMachineType(StringRef S) {
+ MachineTypes MT = StringSwitch<MachineTypes>(S.lower())
+ .Case("x64", AMD64)
+ .Case("amd64", AMD64)
+ .Case("x86", I386)
+ .Case("i386", I386)
+ .Case("arm", ARMNT)
+ .Default(IMAGE_FILE_MACHINE_UNKNOWN);
+ if (MT != IMAGE_FILE_MACHINE_UNKNOWN)
+ return MT;
+ error(Twine("unknown /machine argument: ") + S);
+}
+
+StringRef machineToStr(MachineTypes MT) {
+ switch (MT) {
+ case ARMNT:
+ return "arm";
+ case AMD64:
+ return "x64";
+ case I386:
+ return "x86";
+ default:
+ llvm_unreachable("unknown machine type");
+ }
+}
+
+// Parses a string in the form of "<integer>[,<integer>]".
+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);
+ if (Size && !S2.empty() && S2.getAsInteger(0, *Size))
+ error(Twine("invalid number: ") + S2);
+}
+
+// Parses a string in the form of "<integer>[.<integer>]".
+// If second number is not present, Minor is set to 0.
+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);
+ *Minor = 0;
+ if (!S2.empty() && S2.getAsInteger(0, *Minor))
+ error(Twine("invalid number: ") + S2);
+}
+
+// Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".
+void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major,
+ uint32_t *Minor) {
+ StringRef SysStr, Ver;
+ std::tie(SysStr, Ver) = Arg.split(',');
+ *Sys = StringSwitch<WindowsSubsystem>(SysStr.lower())
+ .Case("boot_application", IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION)
+ .Case("console", IMAGE_SUBSYSTEM_WINDOWS_CUI)
+ .Case("efi_application", IMAGE_SUBSYSTEM_EFI_APPLICATION)
+ .Case("efi_boot_service_driver", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
+ .Case("efi_rom", IMAGE_SUBSYSTEM_EFI_ROM)
+ .Case("efi_runtime_driver", IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
+ .Case("native", IMAGE_SUBSYSTEM_NATIVE)
+ .Case("posix", IMAGE_SUBSYSTEM_POSIX_CUI)
+ .Case("windows", IMAGE_SUBSYSTEM_WINDOWS_GUI)
+ .Default(IMAGE_SUBSYSTEM_UNKNOWN);
+ if (*Sys == IMAGE_SUBSYSTEM_UNKNOWN)
+ error(Twine("unknown subsystem: ") + SysStr);
+ if (!Ver.empty())
+ parseVersion(Ver, Major, Minor);
+}
+
+// Parse a string of the form of "<from>=<to>".
+// Results are directly written to Config.
+void parseAlternateName(StringRef S) {
+ StringRef From, To;
+ std::tie(From, To) = S.split('=');
+ if (From.empty() || To.empty())
+ error(Twine("/alternatename: invalid argument: ") + S);
+ auto It = Config->AlternateNames.find(From);
+ if (It != Config->AlternateNames.end() && It->second != To)
+ error(Twine("/alternatename: conflicts: ") + S);
+ Config->AlternateNames.insert(It, std::make_pair(From, To));
+}
+
+// Parse a string of the form of "<from>=<to>".
+// Results are directly written to Config.
+void parseMerge(StringRef S) {
+ StringRef From, To;
+ std::tie(From, To) = S.split('=');
+ if (From.empty() || To.empty())
+ error(Twine("/merge: invalid argument: ") + S);
+ auto Pair = Config->Merge.insert(std::make_pair(From, To));
+ bool Inserted = Pair.second;
+ if (!Inserted) {
+ StringRef Existing = Pair.first->second;
+ if (Existing != To)
+ llvm::errs() << "warning: " << S << ": already merged into "
+ << Existing << "\n";
+ }
+}
+
+// Parses a string in the form of "EMBED[,=<integer>]|NO".
+// Results are directly written to Config.
+void parseManifest(StringRef Arg) {
+ if (Arg.equals_lower("no")) {
+ Config->Manifest = Configuration::No;
+ return;
+ }
+ if (!Arg.startswith_lower("embed"))
+ error(Twine("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);
+ Arg = Arg.substr(strlen(",id="));
+ if (Arg.getAsInteger(0, Config->ManifestID))
+ error(Twine("Invalid option ") + Arg);
+}
+
+// Parses a string in the form of "level=<string>|uiAccess=<string>|NO".
+// Results are directly written to Config.
+void parseManifestUAC(StringRef Arg) {
+ if (Arg.equals_lower("no")) {
+ Config->ManifestUAC = false;
+ return;
+ }
+ for (;;) {
+ Arg = Arg.ltrim();
+ if (Arg.empty())
+ return;
+ if (Arg.startswith_lower("level=")) {
+ Arg = Arg.substr(strlen("level="));
+ std::tie(Config->ManifestLevel, Arg) = Arg.split(" ");
+ continue;
+ }
+ if (Arg.startswith_lower("uiaccess=")) {
+ Arg = Arg.substr(strlen("uiaccess="));
+ std::tie(Config->ManifestUIAccess, Arg) = Arg.split(" ");
+ continue;
+ }
+ error(Twine("Invalid option ") + Arg);
+ }
+}
+
+// Quote each line with "". Existing double-quote is converted
+// to two double-quotes.
+static void quoteAndPrint(raw_ostream &Out, StringRef S) {
+ while (!S.empty()) {
+ StringRef Line;
+ std::tie(Line, S) = S.split("\n");
+ if (Line.empty())
+ continue;
+ Out << '\"';
+ for (int I = 0, E = Line.size(); I != E; ++I) {
+ if (Line[I] == '\"') {
+ Out << "\"\"";
+ } else {
+ Out << Line[I];
+ }
+ }
+ Out << "\"\n";
+ }
+}
+
+// Create a manifest file contents.
+static std::string createManifestXml() {
+ std::string S;
+ llvm::raw_string_ostream OS(S);
+ // 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"
+ << "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\"\n"
+ << " manifestVersion=\"1.0\">\n";
+ if (Config->ManifestUAC) {
+ OS << " <trustInfo>\n"
+ << " <security>\n"
+ << " <requestedPrivileges>\n"
+ << " <requestedExecutionLevel level=" << Config->ManifestLevel
+ << " uiAccess=" << Config->ManifestUIAccess << "/>\n"
+ << " </requestedPrivileges>\n"
+ << " </security>\n"
+ << " </trustInfo>\n";
+ if (!Config->ManifestDependency.empty()) {
+ OS << " <dependency>\n"
+ << " <dependentAssembly>\n"
+ << " <assemblyIdentity " << Config->ManifestDependency << " />\n"
+ << " </dependentAssembly>\n"
+ << " </dependency>\n";
+ }
+ }
+ OS << "</assembly>\n";
+ OS.flush();
+ return S;
+}
+
+// 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");
+ FileRemover RCRemover(RCPath);
+
+ // Open the temporary file for writing.
+ llvm::raw_fd_ostream Out(RCPath, EC, sys::fs::F_Text);
+ error(EC, Twine("failed to open ") + RCPath);
+
+ // Write resource script to the RC file.
+ Out << "#define LANG_ENGLISH 9\n"
+ << "#define SUBLANG_DEFAULT 1\n"
+ << "#define APP_MANIFEST " << Config->ManifestID << "\n"
+ << "#define RT_MANIFEST 24\n"
+ << "LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT\n"
+ << "APP_MANIFEST RT_MANIFEST {\n";
+ quoteAndPrint(Out, createManifestXml());
+ Out << "}\n";
+ Out.close();
+
+ // Create output resource file.
+ SmallString<128> ResPath;
+ EC = sys::fs::createTemporaryFile("tmp", "res", ResPath);
+ error(EC, "cannot create a temporary file");
+
+ Executor E("rc.exe");
+ E.add("/fo");
+ E.add(ResPath.str());
+ 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);
+}
+
+void createSideBySideManifest() {
+ std::string Path = Config->ManifestFile;
+ if (Path == "")
+ Path = (Twine(Config->OutputFile) + ".manifest").str();
+ std::error_code EC;
+ llvm::raw_fd_ostream Out(Path, EC, llvm::sys::fs::F_Text);
+ error(EC, "failed to create manifest");
+ Out << createManifestXml();
+}
+
+// Parse a string in the form of
+// "<name>[=<internalname>][,@ordinal[,NONAME]][,DATA][,PRIVATE]".
+// Used for parsing /export arguments.
+Export parseExport(StringRef Arg) {
+ Export E;
+ StringRef Rest;
+ std::tie(E.Name, Rest) = Arg.split(",");
+ if (E.Name.empty())
+ goto err;
+ if (E.Name.find('=') != StringRef::npos) {
+ std::tie(E.ExtName, E.Name) = E.Name.split("=");
+ if (E.Name.empty())
+ goto err;
+ }
+
+ while (!Rest.empty()) {
+ StringRef Tok;
+ std::tie(Tok, Rest) = Rest.split(",");
+ if (Tok.equals_lower("noname")) {
+ if (E.Ordinal == 0)
+ goto err;
+ E.Noname = true;
+ continue;
+ }
+ if (Tok.equals_lower("data")) {
+ E.Data = true;
+ continue;
+ }
+ if (Tok.equals_lower("private")) {
+ E.Private = true;
+ continue;
+ }
+ if (Tok.startswith("@")) {
+ int32_t Ord;
+ if (Tok.substr(1).getAsInteger(0, Ord))
+ goto err;
+ if (Ord <= 0 || 65535 < Ord)
+ goto err;
+ E.Ordinal = Ord;
+ continue;
+ }
+ goto err;
+ }
+ return E;
+
+err:
+ error(Twine("invalid /export: ") + Arg);
+}
+
+static StringRef undecorate(StringRef Sym) {
+ if (Config->Machine != I386)
+ return Sym;
+ return Sym.startswith("_") ? Sym.substr(1) : Sym;
+}
+
+// Performs error checking on all /export arguments.
+// It also sets ordinals.
+void fixupExports() {
+ // Symbol ordinals must be unique.
+ std::set<uint16_t> Ords;
+ for (Export &E : Config->Exports) {
+ if (E.Ordinal == 0)
+ continue;
+ if (!Ords.insert(E.Ordinal).second)
+ error("duplicate export ordinal: " + E.Name);
+ }
+
+ for (Export &E : Config->Exports) {
+ if (Undefined *U = cast_or_null<Undefined>(E.Sym->WeakAlias)) {
+ E.SymbolName = U->getName();
+ } else {
+ E.SymbolName = E.Sym->getName();
+ }
+ }
+
+ for (Export &E : Config->Exports)
+ E.ExportName = undecorate(E.ExtName.empty() ? E.Name : E.ExtName);
+
+ // Uniquefy by name.
+ std::map<StringRef, Export *> Map;
+ std::vector<Export> V;
+ for (Export &E : Config->Exports) {
+ auto Pair = Map.insert(std::make_pair(E.ExportName, &E));
+ bool Inserted = Pair.second;
+ if (Inserted) {
+ V.push_back(E);
+ continue;
+ }
+ Export *Existing = Pair.first->second;
+ if (E == *Existing || E.Name != Existing->Name)
+ continue;
+ llvm::errs() << "warning: duplicate /export option: " << E.Name << "\n";
+ }
+ Config->Exports = std::move(V);
+
+ // Sort by name.
+ std::sort(Config->Exports.begin(), Config->Exports.end(),
+ [](const Export &A, const Export &B) {
+ return A.ExportName < B.ExportName;
+ });
+}
+
+void assignExportOrdinals() {
+ // Assign unique ordinals if default (= 0).
+ uint16_t Max = 0;
+ for (Export &E : Config->Exports)
+ Max = std::max(Max, E.Ordinal);
+ for (Export &E : Config->Exports)
+ if (E.Ordinal == 0)
+ E.Ordinal = ++Max;
+}
+
+// Parses a string in the form of "key=value" and check
+// if value matches previous values for the same key.
+void checkFailIfMismatch(StringRef Arg) {
+ StringRef K, V;
+ std::tie(K, V) = Arg.split('=');
+ if (K.empty() || V.empty())
+ error(Twine("/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);
+ Config->MustMatch[K] = V;
+}
+
+// Convert Windows resource files (.res files) to a .obj file
+// using cvtres.exe.
+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");
+
+ // Execute cvtres.exe.
+ Executor E("cvtres.exe");
+ E.add("/machine:" + machineToStr(Config->Machine));
+ E.add("/readonly");
+ E.add("/nologo");
+ E.add("/out:" + Path);
+ 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);
+}
+
+// Create OptTable
+
+// Create prefix string literals used in Options.td
+#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#include "Options.inc"
+#undef PREFIX
+
+// Create table mapping all options defined in Options.td
+static const llvm::opt::OptTable::Info infoTable[] = {
+#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \
+ { \
+ X1, X2, X9, X10, OPT_##ID, llvm::opt::Option::KIND##Class, X8, X7, \
+ OPT_##GROUP, OPT_##ALIAS, X6 \
+ },
+#include "Options.inc"
+#undef OPTION
+};
+
+class COFFOptTable : public llvm::opt::OptTable {
+public:
+ COFFOptTable() : OptTable(infoTable, true) {}
+};
+
+// Parses a given list of options.
+llvm::opt::InputArgList ArgParser::parse(ArrayRef<const char *> ArgsArr) {
+ // First, replace respnose files (@<file>-style options).
+ std::vector<const char *> Argv = replaceResponseFiles(ArgsArr);
+
+ // Make InputArgList from string vectors.
+ COFFOptTable Table;
+ unsigned MissingIndex;
+ unsigned MissingCount;
+ llvm::opt::InputArgList Args =
+ Table.ParseArgs(Argv, MissingIndex, MissingCount);
+
+ // Print the real command line if response files are expanded.
+ if (Args.hasArg(OPT_verbose) && ArgsArr.size() != Argv.size()) {
+ llvm::outs() << "Command line:";
+ for (const char *S : Argv)
+ llvm::outs() << " " << S;
+ llvm::outs() << "\n";
+ }
+
+ if (MissingCount)
+ error(Twine("missing arg value for \"") + Args.getArgString(MissingIndex) +
+ "\", expected " + Twine(MissingCount) +
+ (MissingCount == 1 ? " argument." : " arguments."));
+ for (auto *Arg : Args.filtered(OPT_UNKNOWN))
+ llvm::errs() << "ignoring unknown argument: " << Arg->getSpelling() << "\n";
+ return Args;
+}
+
+llvm::opt::InputArgList ArgParser::parseLINK(ArrayRef<const char *> Args) {
+ // Concatenate LINK env and given arguments and parse them.
+ Optional<std::string> Env = Process::GetEnv("LINK");
+ if (!Env)
+ return parse(Args);
+ std::vector<const char *> V = tokenize(*Env);
+ V.insert(V.end(), Args.begin(), Args.end());
+ return parse(V);
+}
+
+std::vector<const char *> ArgParser::tokenize(StringRef S) {
+ SmallVector<const char *, 16> Tokens;
+ StringSaver Saver(AllocAux);
+ llvm::cl::TokenizeWindowsCommandLine(S, Saver, Tokens);
+ return std::vector<const char *>(Tokens.begin(), Tokens.end());
+}
+
+// Creates a new command line by replacing options starting with '@'
+// character. '@<filename>' is replaced by the file's contents.
+std::vector<const char *>
+ArgParser::replaceResponseFiles(std::vector<const char *> Argv) {
+ SmallVector<const char *, 256> Tokens(Argv.data(), Argv.data() + Argv.size());
+ StringSaver Saver(AllocAux);
+ ExpandResponseFiles(Saver, TokenizeWindowsCommandLine, Tokens);
+ return std::vector<const char *>(Tokens.begin(), Tokens.end());
+}
+
+void printHelp(const char *Argv0) {
+ COFFOptTable Table;
+ Table.PrintHelp(llvm::outs(), Argv0, "LLVM Linker", false);
+}
+
+} // namespace coff
+} // namespace lld
diff --git a/COFF/Error.cpp b/COFF/Error.cpp
new file mode 100644
index 000000000000..255d9bbad9d8
--- /dev/null
+++ b/COFF/Error.cpp
@@ -0,0 +1,30 @@
+//===- Error.cpp ----------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Error.h"
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace lld {
+namespace coff {
+
+void error(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());
+}
+
+} // namespace coff
+} // namespace lld
diff --git a/COFF/Error.h b/COFF/Error.h
new file mode 100644
index 000000000000..cb0a185f0917
--- /dev/null
+++ b/COFF/Error.h
@@ -0,0 +1,28 @@
+//===- Error.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_ERROR_H
+#define LLD_COFF_ERROR_H
+
+#include "lld/Core/LLVM.h"
+
+namespace lld {
+namespace coff {
+
+LLVM_ATTRIBUTE_NORETURN void error(const Twine &Msg);
+void error(std::error_code EC, const Twine &Prefix);
+
+template <typename T> void error(const ErrorOr<T> &V, const Twine &Prefix) {
+ error(V.getError(), Prefix);
+}
+
+} // namespace coff
+} // namespace lld
+
+#endif
diff --git a/COFF/ICF.cpp b/COFF/ICF.cpp
new file mode 100644
index 000000000000..f99b41624a84
--- /dev/null
+++ b/COFF/ICF.cpp
@@ -0,0 +1,244 @@
+//===- ICF.cpp ------------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Identical COMDAT Folding is a feature to merge COMDAT sections not by
+// name (which is regular COMDAT handling) but by contents. If two COMDAT
+// 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. This may be a bit more complicated problem than you
+// might think. The order of processing sections matters since merging two
+// sections can make other sections, whose relocations now point to the same
+// section, mergeable. Graphs may contain cycles, which is common in COFF.
+// 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.
+//
+// First, all sections are grouped by their "constant" values. Constant
+// values are values that are never changed by ICF, such as section contents,
+// section name, number of relocations, type and offset of each relocation,
+// etc. Because we do not care about some relocation targets in this step,
+// two sections in the same group may not be identical, but at least two
+// sections in different groups can never be identical.
+//
+// Then, we try to split each group by relocation targets. Relocations are
+// considered identical if and only if the relocation targets are in the
+// same group. Splitting a group may make more groups to be splittable,
+// because two relocations that were previously considered identical might
+// now point to different groups. We repeat this step until the convergence
+// is obtained.
+//
+// This algorithm is so-called "optimistic" algorithm described in
+// http://research.google.com/pubs/pub36912.html.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Chunks.h"
+#include "Symbols.h"
+#include "lld/Core/Parallel.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <atomic>
+#include <vector>
+
+using namespace llvm;
+
+namespace lld {
+namespace coff {
+
+typedef std::vector<SectionChunk *>::iterator ChunkIterator;
+typedef bool (*Comparator)(const SectionChunk *, const SectionChunk *);
+
+class ICF {
+public:
+ void run(const std::vector<Chunk *> &V);
+
+private:
+ static uint64_t getHash(SectionChunk *C);
+ 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);
+
+ std::atomic<uint64_t> NextID = { 1 };
+};
+
+// Entry point to ICF.
+void doICF(const std::vector<Chunk *> &Chunks) {
+ ICF().run(Chunks);
+}
+
+uint64_t ICF::getHash(SectionChunk *C) {
+ return hash_combine(C->getPermissions(),
+ hash_value(C->SectionName),
+ C->NumRelocs,
+ C->getAlign(),
+ uint32_t(C->Header->SizeOfRawData),
+ C->Checksum);
+}
+
+bool ICF::equalsConstant(const SectionChunk *A, const SectionChunk *B) {
+ if (A->AssocChildren.size() != B->AssocChildren.size() ||
+ A->NumRelocs != B->NumRelocs) {
+ return false;
+ }
+
+ // Compare associative sections.
+ for (size_t I = 0, E = A->AssocChildren.size(); I != E; ++I)
+ if (A->AssocChildren[I]->GroupID != B->AssocChildren[I]->GroupID)
+ return false;
+
+ // Compare relocations.
+ auto Eq = [&](const coff_relocation &R1, const coff_relocation &R2) {
+ if (R1.Type != R2.Type ||
+ R1.VirtualAddress != R2.VirtualAddress) {
+ return false;
+ }
+ SymbolBody *B1 = A->File->getSymbolBody(R1.SymbolTableIndex)->repl();
+ SymbolBody *B2 = B->File->getSymbolBody(R2.SymbolTableIndex)->repl();
+ if (B1 == B2)
+ return true;
+ if (auto *D1 = dyn_cast<DefinedRegular>(B1))
+ if (auto *D2 = dyn_cast<DefinedRegular>(B2))
+ return D1->getValue() == D2->getValue() &&
+ D1->getChunk()->GroupID == D2->getChunk()->GroupID;
+ return false;
+ };
+ if (!std::equal(A->Relocs.begin(), A->Relocs.end(), B->Relocs.begin(), Eq))
+ return false;
+
+ // Compare section attributes and contents.
+ return A->getPermissions() == B->getPermissions() &&
+ A->SectionName == B->SectionName &&
+ A->getAlign() == B->getAlign() &&
+ A->Header->SizeOfRawData == B->Header->SizeOfRawData &&
+ A->Checksum == B->Checksum &&
+ A->getContents() == B->getContents();
+}
+
+bool ICF::equalsVariable(const SectionChunk *A, const SectionChunk *B) {
+ // Compare associative sections.
+ for (size_t I = 0, E = A->AssocChildren.size(); I != E; ++I)
+ if (A->AssocChildren[I]->GroupID != B->AssocChildren[I]->GroupID)
+ return false;
+
+ // Compare relocations.
+ auto Eq = [&](const coff_relocation &R1, const coff_relocation &R2) {
+ SymbolBody *B1 = A->File->getSymbolBody(R1.SymbolTableIndex)->repl();
+ SymbolBody *B2 = B->File->getSymbolBody(R2.SymbolTableIndex)->repl();
+ if (B1 == B2)
+ return true;
+ if (auto *D1 = dyn_cast<DefinedRegular>(B1))
+ if (auto *D2 = dyn_cast<DefinedRegular>(B2))
+ return D1->getChunk()->GroupID == D2->getChunk()->GroupID;
+ return false;
+ };
+ return std::equal(A->Relocs.begin(), A->Relocs.end(), B->Relocs.begin(), Eq);
+}
+
+bool ICF::partition(ChunkIterator Begin, ChunkIterator End, Comparator Eq) {
+ bool R = false;
+ for (auto It = Begin;;) {
+ SectionChunk *Head = *It;
+ auto Bound = std::partition(It + 1, End, [&](SectionChunk *SC) {
+ return Eq(Head, SC);
+ });
+ if (Bound == End)
+ return R;
+ uint64_t ID = NextID++;
+ std::for_each(It, Bound, [&](SectionChunk *SC) { SC->GroupID = ID; });
+ It = Bound;
+ R = true;
+ }
+}
+
+bool ICF::forEachGroup(std::vector<SectionChunk *> &Chunks, Comparator Eq) {
+ bool R = false;
+ for (auto It = Chunks.begin(), End = Chunks.end(); It != End;) {
+ SectionChunk *Head = *It;
+ auto Bound = std::find_if(It + 1, End, [&](SectionChunk *SC) {
+ return SC->GroupID != Head->GroupID;
+ });
+ if (partition(It, Bound, Eq))
+ R = true;
+ It = Bound;
+ }
+ return R;
+}
+
+// Merge identical COMDAT sections.
+// Two sections are considered the same if their section headers,
+// contents and relocations are all the same.
+void ICF::run(const std::vector<Chunk *> &Vec) {
+ // Collect only mergeable sections and group by hash value.
+ parallel_for_each(Vec.begin(), Vec.end(), [&](Chunk *C) {
+ if (auto *SC = dyn_cast<SectionChunk>(C)) {
+ bool Global = SC->Sym && SC->Sym->isExternal();
+ bool Writable = SC->getPermissions() & llvm::COFF::IMAGE_SCN_MEM_WRITE;
+ if (SC->isCOMDAT() && SC->isLive() && Global && !Writable)
+ SC->GroupID = getHash(SC) | (uint64_t(1) << 63);
+ }
+ });
+ std::vector<SectionChunk *> Chunks;
+ for (Chunk *C : Vec) {
+ if (auto *SC = dyn_cast<SectionChunk>(C)) {
+ if (SC->GroupID) {
+ Chunks.push_back(SC);
+ } else {
+ SC->GroupID = NextID++;
+ }
+ }
+ }
+
+ // From now on, sections in Chunks are ordered so that sections in
+ // the same group are consecutive in the vector.
+ std::sort(Chunks.begin(), Chunks.end(),
+ [](SectionChunk *A, SectionChunk *B) {
+ return A->GroupID < B->GroupID;
+ });
+
+ // Split groups until we get a convergence.
+ int Cnt = 1;
+ forEachGroup(Chunks, equalsConstant);
+
+ for (;;) {
+ if (!forEachGroup(Chunks, equalsVariable))
+ break;
+ ++Cnt;
+ }
+ if (Config->Verbose)
+ llvm::outs() << "\nICF needed " << Cnt << " iterations.\n";
+
+ // Merge sections in the same group.
+ for (auto It = Chunks.begin(), End = Chunks.end(); It != End;) {
+ SectionChunk *Head = *It++;
+ auto Bound = std::find_if(It, End, [&](SectionChunk *SC) {
+ return Head->GroupID != SC->GroupID;
+ });
+ if (It == Bound)
+ continue;
+ if (Config->Verbose)
+ llvm::outs() << "Selected " << Head->getDebugName() << "\n";
+ while (It != Bound) {
+ SectionChunk *SC = *It++;
+ if (Config->Verbose)
+ llvm::outs() << " Removed " << SC->getDebugName() << "\n";
+ Head->replace(SC);
+ }
+ }
+}
+
+} // namespace coff
+} // namespace lld
diff --git a/COFF/InputFiles.cpp b/COFF/InputFiles.cpp
new file mode 100644
index 000000000000..23fc2a085122
--- /dev/null
+++ b/COFF/InputFiles.cpp
@@ -0,0 +1,367 @@
+//===- InputFiles.cpp -----------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Chunks.h"
+#include "Error.h"
+#include "InputFiles.h"
+#include "Symbols.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/LTO/LTOModule.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/COFF.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm::COFF;
+using namespace llvm::object;
+using namespace llvm::support::endian;
+using llvm::RoundUpToAlignment;
+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;
+
+// Returns the last element of a path, which is supposed to be a filename.
+static StringRef getBasename(StringRef Path) {
+ size_t Pos = Path.find_last_of("\\/");
+ if (Pos == StringRef::npos)
+ return Path;
+ return Path.substr(Pos + 1);
+}
+
+// Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)".
+std::string InputFile::getShortName() {
+ if (ParentName == "")
+ return getName().lower();
+ std::string Res = (getBasename(ParentName) + "(" +
+ getBasename(getName()) + ")").str();
+ return StringRef(Res).lower();
+}
+
+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);
+
+ // Allocate a buffer for Lazy objects.
+ size_t NumSyms = File->getNumberOfSymbols();
+ LazySymbols.reserve(NumSyms);
+
+ // Read the symbol table to construct Lazy objects.
+ for (const Archive::Symbol &Sym : File->symbols())
+ LazySymbols.emplace_back(this, Sym);
+
+ // 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;
+ Seen[Child.getChildOffset()].clear();
+ }
+}
+
+// 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;
+
+ // 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;
+}
+
+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);
+
+ if (auto *Obj = dyn_cast<COFFObjectFile>(Bin.get())) {
+ Bin.release();
+ COFFObj.reset(Obj);
+ } else {
+ error(Twine(getName()) + " is not a COFF file.");
+ }
+
+ // Read section and symbol tables.
+ initializeChunks();
+ initializeSymbols();
+ initializeSEH();
+}
+
+void ObjectFile::initializeChunks() {
+ uint32_t NumSections = COFFObj->getNumberOfSections();
+ Chunks.reserve(NumSections);
+ SparseChunks.resize(NumSections + 1);
+ 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 (Name == ".sxdata") {
+ SXData = Sec;
+ continue;
+ }
+ if (Name == ".drectve") {
+ ArrayRef<uint8_t> Data;
+ COFFObj->getSectionContents(Sec, Data);
+ Directives = std::string((const char *)Data.data(), Data.size());
+ continue;
+ }
+ // Skip non-DWARF debug info. MSVC linker converts the sections into
+ // a PDB file, but we don't support that.
+ if (Name == ".debug" || Name.startswith(".debug$"))
+ continue;
+ // We want to preserve DWARF debug sections only when /debug is on.
+ if (!Config->Debug && Name.startswith(".debug"))
+ continue;
+ if (Sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE)
+ continue;
+ auto *C = new (Alloc) SectionChunk(this, Sec);
+ Chunks.push_back(C);
+ SparseChunks[I] = C;
+ }
+}
+
+void ObjectFile::initializeSymbols() {
+ uint32_t NumSymbols = COFFObj->getNumberOfSymbols();
+ SymbolBodies.reserve(NumSymbols);
+ SparseSymbolBodies.resize(NumSymbols);
+ llvm::SmallVector<Undefined *, 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;
+
+ const void *AuxP = nullptr;
+ if (Sym.getNumberOfAuxSymbols())
+ AuxP = COFFObj->getSymbol(I + 1)->getRawPtr();
+ bool IsFirst = (LastSectionNumber != Sym.getSectionNumber());
+
+ SymbolBody *Body = nullptr;
+ if (Sym.isUndefined()) {
+ Body = createUndefined(Sym);
+ } else if (Sym.isWeakExternal()) {
+ Body = createWeakExternal(Sym, AuxP);
+ WeakAliases.push_back((Undefined *)Body);
+ } else {
+ Body = createDefined(Sym, AuxP, IsFirst);
+ }
+ if (Body) {
+ SymbolBodies.push_back(Body);
+ SparseSymbolBodies[I] = Body;
+ }
+ I += Sym.getNumberOfAuxSymbols();
+ LastSectionNumber = Sym.getSectionNumber();
+ }
+ for (Undefined *U : WeakAliases)
+ U->WeakAlias = SparseSymbolBodies[(uintptr_t)U->WeakAlias];
+}
+
+Undefined *ObjectFile::createUndefined(COFFSymbolRef Sym) {
+ StringRef Name;
+ COFFObj->getSymbolName(Sym, Name);
+ 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;
+ if (Sym.isCommon()) {
+ auto *C = new (Alloc) CommonChunk(Sym);
+ Chunks.push_back(C);
+ return new (Alloc) DefinedCommon(this, Sym, C);
+ }
+ if (Sym.isAbsolute()) {
+ COFFObj->getSymbolName(Sym, Name);
+ // Skip special symbols.
+ if (Name == "@comp.id")
+ return nullptr;
+ // COFF spec 5.10.1. The .sxdata section.
+ if (Name == "@feat.00") {
+ if (Sym.getValue() & 1)
+ SEHCompat = true;
+ return nullptr;
+ }
+ return new (Alloc) DefinedAbsolute(Name, Sym);
+ }
+ if (Sym.getSectionNumber() == llvm::COFF::IMAGE_SYM_DEBUG)
+ return nullptr;
+
+ // Nothing else to do without a section chunk.
+ auto *SC = cast_or_null<SectionChunk>(SparseChunks[Sym.getSectionNumber()]);
+ if (!SC)
+ return nullptr;
+
+ // Handle section definitions
+ if (IsFirst && AuxP) {
+ auto *Aux = reinterpret_cast<const coff_aux_section_definition *>(AuxP);
+ if (Aux->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE)
+ if (auto *ParentSC = cast_or_null<SectionChunk>(
+ SparseChunks[Aux->getNumber(Sym.isBigObj())]))
+ ParentSC->addAssociative(SC);
+ SC->Checksum = Aux->CheckSum;
+ }
+
+ auto *B = new (Alloc) DefinedRegular(this, Sym, SC);
+ if (SC->isCOMDAT() && Sym.getValue() == 0 && !AuxP)
+ SC->setSymbol(B);
+
+ return B;
+}
+
+void ObjectFile::initializeSEH() {
+ if (!SEHCompat || !SXData)
+ return;
+ ArrayRef<uint8_t> A;
+ COFFObj->getSectionContents(SXData, A);
+ if (A.size() % 4 != 0)
+ error(".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)
+ SEHandlers.insert(SparseSymbolBodies[*I]);
+}
+
+MachineTypes ObjectFile::getMachineType() {
+ if (COFFObj)
+ return static_cast<MachineTypes>(COFFObj->getMachine());
+ return IMAGE_FILE_MACHINE_UNKNOWN;
+}
+
+StringRef ltrim1(StringRef S, const char *Chars) {
+ if (!S.empty() && strchr(Chars, S[0]))
+ return S.substr(1);
+ return S;
+}
+
+void ImportFile::parse() {
+ const char *Buf = MB.getBufferStart();
+ const char *End = MB.getBufferEnd();
+ const auto *Hdr = reinterpret_cast<const coff_import_header *>(Buf);
+
+ // Check if the total size is valid.
+ if ((size_t)(End - Buf) != (sizeof(*Hdr) + Hdr->SizeOfData))
+ error("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);
+ const char *NameStart = Buf + sizeof(coff_import_header) + Name.size() + 1;
+ DLLName = StringRef(NameStart);
+ StringRef ExtName;
+ switch (Hdr->getNameType()) {
+ case IMPORT_ORDINAL:
+ ExtName = "";
+ break;
+ case IMPORT_NAME:
+ ExtName = Name;
+ break;
+ case IMPORT_NAME_NOPREFIX:
+ ExtName = ltrim1(Name, "?@_");
+ break;
+ case IMPORT_NAME_UNDECORATE:
+ ExtName = ltrim1(Name, "?@_");
+ ExtName = ExtName.substr(0, ExtName.find('@'));
+ break;
+ }
+ ImpSym = new (Alloc) DefinedImportData(DLLName, ImpName, ExtName, Hdr);
+ SymbolBodies.push_back(ImpSym);
+
+ // If type is function, we need to create a thunk which jump to an
+ // address pointed by the __imp_ symbol. (This allows you to call
+ // DLL functions just like regular non-DLL functions.)
+ if (Hdr->getType() != llvm::COFF::IMPORT_CODE)
+ return;
+ ThunkSym = new (Alloc) DefinedImportThunk(Name, ImpSym, Hdr->Machine);
+ SymbolBodies.push_back(ThunkSym);
+}
+
+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);
+
+ llvm::StringSaver Saver(Alloc);
+ for (unsigned I = 0, E = M->getSymbolCount(); I != E; ++I) {
+ lto_symbol_attributes Attrs = M->getSymbolAttributes(I);
+ if ((Attrs & LTO_SYMBOL_SCOPE_MASK) == LTO_SYMBOL_SCOPE_INTERNAL)
+ continue;
+
+ StringRef SymName = Saver.save(M->getSymbolName(I));
+ int SymbolDef = Attrs & LTO_SYMBOL_DEFINITION_MASK;
+ if (SymbolDef == LTO_SYMBOL_DEFINITION_UNDEFINED) {
+ SymbolBodies.push_back(new (Alloc) Undefined(SymName));
+ } else {
+ bool Replaceable =
+ (SymbolDef == LTO_SYMBOL_DEFINITION_TENTATIVE || // common
+ (Attrs & LTO_SYMBOL_COMDAT) || // comdat
+ (SymbolDef == LTO_SYMBOL_DEFINITION_WEAK && // weak external
+ (Attrs & LTO_SYMBOL_ALIAS)));
+ SymbolBodies.push_back(new (Alloc) DefinedBitcode(this, SymName,
+ Replaceable));
+ }
+ }
+
+ Directives = M->getLinkerOpts();
+}
+
+MachineTypes BitcodeFile::getMachineType() {
+ if (!M)
+ return IMAGE_FILE_MACHINE_UNKNOWN;
+ switch (Triple(M->getTargetTriple()).getArch()) {
+ case Triple::x86_64:
+ return AMD64;
+ case Triple::x86:
+ return I386;
+ case Triple::arm:
+ return ARMNT;
+ default:
+ return IMAGE_FILE_MACHINE_UNKNOWN;
+ }
+}
+
+std::mutex BitcodeFile::Mu;
+
+} // namespace coff
+} // namespace lld
diff --git a/COFF/InputFiles.h b/COFF/InputFiles.h
new file mode 100644
index 000000000000..6a263fbaddf6
--- /dev/null
+++ b/COFF/InputFiles.h
@@ -0,0 +1,222 @@
+//===- InputFiles.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_INPUT_FILES_H
+#define LLD_COFF_INPUT_FILES_H
+
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/LTO/LTOModule.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/StringSaver.h"
+#include <memory>
+#include <mutex>
+#include <set>
+#include <vector>
+
+namespace lld {
+namespace coff {
+
+using llvm::LTOModule;
+using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN;
+using llvm::COFF::MachineTypes;
+using llvm::object::Archive;
+using llvm::object::COFFObjectFile;
+using llvm::object::COFFSymbolRef;
+using llvm::object::coff_section;
+
+class Chunk;
+class Defined;
+class DefinedImportData;
+class DefinedImportThunk;
+class Lazy;
+class SymbolBody;
+class Undefined;
+
+// The root class of input files.
+class InputFile {
+public:
+ enum Kind { ArchiveKind, ObjectKind, ImportKind, BitcodeKind };
+ Kind kind() const { return FileKind; }
+ virtual ~InputFile() {}
+
+ // Returns the filename.
+ StringRef getName() { return MB.getBufferIdentifier(); }
+
+ // Returns symbols defined by this file.
+ virtual std::vector<SymbolBody *> &getSymbols() = 0;
+
+ // Reads a file (the constructor doesn't do that).
+ virtual void parse() = 0;
+
+ // Returns the CPU type this file was compiled to.
+ virtual MachineTypes getMachineType() { return IMAGE_FILE_MACHINE_UNKNOWN; }
+
+ // Returns a short, human-friendly filename. If this is a member of
+ // an archive file, a returned value includes parent's filename.
+ // Used for logging or debugging.
+ std::string getShortName();
+
+ // Sets a parent filename if this file is created from an archive.
+ void setParentName(StringRef N) { ParentName = N; }
+
+ // Returns .drectve section contents if exist.
+ StringRef getDirectives() { return StringRef(Directives).trim(); }
+
+ // Each file has a unique index. The index number is used to
+ // resolve ties in symbol resolution.
+ int Index;
+ static int NextIndex;
+
+protected:
+ InputFile(Kind K, MemoryBufferRef M)
+ : Index(NextIndex++), MB(M), FileKind(K) {}
+
+ MemoryBufferRef MB;
+ std::string Directives;
+
+private:
+ const Kind FileKind;
+ StringRef ParentName;
+};
+
+// .lib or .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() override;
+
+ // 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; }
+
+ // All symbols returned by ArchiveFiles are of Lazy type.
+ std::vector<SymbolBody *> &getSymbols() override {
+ llvm_unreachable("internal error");
+ }
+
+private:
+ std::unique_ptr<Archive> File;
+ std::string Filename;
+ std::vector<Lazy> LazySymbols;
+ std::map<uint64_t, std::atomic_flag> Seen;
+};
+
+// .obj or .o file. This may be a member of an archive file.
+class ObjectFile : public InputFile {
+public:
+ explicit ObjectFile(MemoryBufferRef M) : InputFile(ObjectKind, M) {}
+ static bool classof(const InputFile *F) { return F->kind() == ObjectKind; }
+ void parse() override;
+ MachineTypes getMachineType() override;
+ std::vector<Chunk *> &getChunks() { return Chunks; }
+ std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies; }
+
+ // Returns a SymbolBody object for the SymbolIndex'th symbol in the
+ // underlying object file.
+ SymbolBody *getSymbolBody(uint32_t SymbolIndex) {
+ return SparseSymbolBodies[SymbolIndex];
+ }
+
+ // Returns the underying COFF file.
+ COFFObjectFile *getCOFFObj() { return COFFObj.get(); }
+
+ // True if this object file is compatible with SEH.
+ // COFF-specific and x86-only.
+ bool SEHCompat = false;
+
+ // The list of safe exception handlers listed in .sxdata section.
+ // COFF-specific and x86-only.
+ std::set<SymbolBody *> SEHandlers;
+
+private:
+ void initializeChunks();
+ void initializeSymbols();
+ void initializeSEH();
+
+ 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;
+ const coff_section *SXData = nullptr;
+
+ // List of all chunks defined by this file. This includes both section
+ // chunks and non-section chunks for common symbols.
+ std::vector<Chunk *> Chunks;
+
+ // This vector contains the same chunks as Chunks, but they are
+ // indexed such that you can get a SectionChunk by section index.
+ // Nonexistent section indices are filled with null pointers.
+ // (Because section number is 1-based, the first slot is always a
+ // null pointer.)
+ std::vector<Chunk *> SparseChunks;
+
+ // List of all symbols referenced or defined by this file.
+ std::vector<SymbolBody *> SymbolBodies;
+
+ // This vector contains the same symbols as SymbolBodies, but they
+ // are indexed such that you can get a SymbolBody by symbol
+ // index. Nonexistent indices (which are occupied by auxiliary
+ // symbols in the real symbol table) are filled with null pointers.
+ std::vector<SymbolBody *> SparseSymbolBodies;
+};
+
+// This type represents import library members that contain DLL names
+// and symbols exported from the DLLs. See Microsoft PE/COFF spec. 7
+// for details about the format.
+class ImportFile : public InputFile {
+public:
+ explicit ImportFile(MemoryBufferRef M)
+ : InputFile(ImportKind, M), StringAlloc(StringAllocAux) {}
+ static bool classof(const InputFile *F) { return F->kind() == ImportKind; }
+ std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies; }
+
+ DefinedImportData *ImpSym = nullptr;
+ DefinedImportThunk *ThunkSym = nullptr;
+ std::string DLLName;
+
+private:
+ void parse() override;
+
+ std::vector<SymbolBody *> SymbolBodies;
+ llvm::BumpPtrAllocator Alloc;
+ llvm::BumpPtrAllocator StringAllocAux;
+ llvm::StringSaver StringAlloc;
+};
+
+// Used for LTO.
+class BitcodeFile : public InputFile {
+public:
+ explicit BitcodeFile(MemoryBufferRef M) : InputFile(BitcodeKind, M) {}
+ 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); }
+
+private:
+ void parse() override;
+
+ std::vector<SymbolBody *> SymbolBodies;
+ llvm::BumpPtrAllocator Alloc;
+ std::unique_ptr<LTOModule> M;
+ static std::mutex Mu;
+};
+
+} // namespace coff
+} // namespace lld
+
+#endif
diff --git a/COFF/MarkLive.cpp b/COFF/MarkLive.cpp
new file mode 100644
index 000000000000..0870986ad81a
--- /dev/null
+++ b/COFF/MarkLive.cpp
@@ -0,0 +1,61 @@
+//===- MarkLive.cpp -------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Chunks.h"
+#include "Symbols.h"
+#include "llvm/ADT/STLExtras.h"
+#include <vector>
+
+namespace lld {
+namespace coff {
+
+// Set live bit on for each reachable chunk. Unmarked (unreachable)
+// COMDAT chunks will be ignored by Writer, so they will be excluded
+// from the final output.
+void markLive(const std::vector<Chunk *> &Chunks) {
+ // We build up a worklist of sections which have been marked as live. We only
+ // push into the worklist when we discover an unmarked section, and we mark
+ // as we push, so sections never appear twice in the list.
+ SmallVector<SectionChunk *, 256> Worklist;
+
+ // COMDAT section chunks are dead by default. Add non-COMDAT chunks.
+ for (Chunk *C : Chunks)
+ if (auto *SC = dyn_cast<SectionChunk>(C))
+ if (SC->isLive())
+ Worklist.push_back(SC);
+
+ auto Enqueue = [&](SectionChunk *C) {
+ if (C->isLive())
+ return;
+ C->markLive();
+ Worklist.push_back(C);
+ };
+
+ // Add GC root chunks.
+ for (Undefined *U : Config->GCRoot)
+ if (auto *D = dyn_cast<DefinedRegular>(U->repl()))
+ Enqueue(D->getChunk());
+
+ while (!Worklist.empty()) {
+ SectionChunk *SC = Worklist.pop_back_val();
+ assert(SC->isLive() && "We mark as live when pushing onto the worklist!");
+
+ // Mark all symbols listed in the relocation table for this section.
+ for (SymbolBody *S : SC->symbols())
+ if (auto *D = dyn_cast<DefinedRegular>(S->repl()))
+ Enqueue(D->getChunk());
+
+ // Mark associative sections if any.
+ for (SectionChunk *C : SC->children())
+ Enqueue(C);
+ }
+}
+
+}
+}
diff --git a/COFF/ModuleDef.cpp b/COFF/ModuleDef.cpp
new file mode 100644
index 000000000000..d117e961f89a
--- /dev/null
+++ b/COFF/ModuleDef.cpp
@@ -0,0 +1,291 @@
+//===- COFF/ModuleDef.cpp -------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Windows-specific.
+// A parser for the module-definition file (.def file).
+// Parsed results are directly written to Config global variable.
+//
+// The format of module-definition files are described in this document:
+// https://msdn.microsoft.com/en-us/library/28d6s79h.aspx
+//
+//===----------------------------------------------------------------------===//
+
+#include "Config.h"
+#include "Error.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/StringSaver.h"
+#include "llvm/Support/raw_ostream.h"
+#include <system_error>
+
+using namespace llvm;
+
+namespace lld {
+namespace coff {
+namespace {
+
+enum Kind {
+ Unknown,
+ Eof,
+ Identifier,
+ Comma,
+ Equal,
+ KwBase,
+ KwData,
+ KwExports,
+ KwHeapsize,
+ KwLibrary,
+ KwName,
+ KwNoname,
+ KwPrivate,
+ KwStacksize,
+ KwVersion,
+};
+
+struct Token {
+ explicit Token(Kind T = Unknown, StringRef S = "") : K(T), Value(S) {}
+ Kind K;
+ StringRef Value;
+};
+
+static bool isDecorated(StringRef Sym) {
+ return Sym.startswith("_") || Sym.startswith("@") || Sym.startswith("?");
+}
+
+class Lexer {
+public:
+ explicit Lexer(StringRef S) : Buf(S) {}
+
+ Token lex() {
+ Buf = Buf.trim();
+ if (Buf.empty())
+ return Token(Eof);
+
+ switch (Buf[0]) {
+ case '\0':
+ return Token(Eof);
+ case ';': {
+ size_t End = Buf.find('\n');
+ Buf = (End == Buf.npos) ? "" : Buf.drop_front(End);
+ return lex();
+ }
+ case '=':
+ Buf = Buf.drop_front();
+ return Token(Equal, "=");
+ case ',':
+ Buf = Buf.drop_front();
+ return Token(Comma, ",");
+ case '"': {
+ StringRef S;
+ std::tie(S, Buf) = Buf.substr(1).split('"');
+ return Token(Identifier, S);
+ }
+ default: {
+ size_t End = Buf.find_first_of("=,\r\n \t\v");
+ StringRef Word = Buf.substr(0, End);
+ Kind K = llvm::StringSwitch<Kind>(Word)
+ .Case("BASE", KwBase)
+ .Case("DATA", KwData)
+ .Case("EXPORTS", KwExports)
+ .Case("HEAPSIZE", KwHeapsize)
+ .Case("LIBRARY", KwLibrary)
+ .Case("NAME", KwName)
+ .Case("NONAME", KwNoname)
+ .Case("PRIVATE", KwPrivate)
+ .Case("STACKSIZE", KwStacksize)
+ .Case("VERSION", KwVersion)
+ .Default(Identifier);
+ Buf = (End == Buf.npos) ? "" : Buf.drop_front(End);
+ return Token(K, Word);
+ }
+ }
+ }
+
+private:
+ StringRef Buf;
+};
+
+class Parser {
+public:
+ explicit Parser(StringRef S, StringSaver *A) : Lex(S), Alloc(A) {}
+
+ void parse() {
+ do {
+ parseOne();
+ } while (Tok.K != Eof);
+ }
+
+private:
+ void read() {
+ if (Stack.empty()) {
+ Tok = Lex.lex();
+ return;
+ }
+ Tok = Stack.back();
+ Stack.pop_back();
+ }
+
+ void readAsInt(uint64_t *I) {
+ read();
+ if (Tok.K != Identifier || Tok.Value.getAsInteger(10, *I))
+ error("integer expected");
+ }
+
+ void expect(Kind Expected, StringRef Msg) {
+ read();
+ if (Tok.K != Expected)
+ error(Msg);
+ }
+
+ void unget() { Stack.push_back(Tok); }
+
+ void parseOne() {
+ read();
+ switch (Tok.K) {
+ case Eof:
+ return;
+ case KwExports:
+ for (;;) {
+ read();
+ if (Tok.K != Identifier) {
+ unget();
+ return;
+ }
+ parseExport();
+ }
+ case KwHeapsize:
+ parseNumbers(&Config->HeapReserve, &Config->HeapCommit);
+ return;
+ case KwLibrary:
+ parseName(&Config->OutputFile, &Config->ImageBase);
+ if (!StringRef(Config->OutputFile).endswith_lower(".dll"))
+ Config->OutputFile += ".dll";
+ return;
+ case KwStacksize:
+ parseNumbers(&Config->StackReserve, &Config->StackCommit);
+ return;
+ case KwName:
+ parseName(&Config->OutputFile, &Config->ImageBase);
+ return;
+ case KwVersion:
+ parseVersion(&Config->MajorImageVersion, &Config->MinorImageVersion);
+ return;
+ default:
+ error(Twine("unknown directive: ") + Tok.Value);
+ }
+ }
+
+ void parseExport() {
+ Export E;
+ E.Name = Tok.Value;
+ read();
+ if (Tok.K == Equal) {
+ read();
+ if (Tok.K != Identifier)
+ error(Twine("identifier expected, but got ") + Tok.Value);
+ E.ExtName = E.Name;
+ E.Name = Tok.Value;
+ } else {
+ unget();
+ }
+
+ if (Config->Machine == I386) {
+ if (!isDecorated(E.Name))
+ E.Name = Alloc->save("_" + E.Name);
+ if (!E.ExtName.empty() && !isDecorated(E.ExtName))
+ E.ExtName = Alloc->save("_" + E.ExtName);
+ }
+
+ for (;;) {
+ read();
+ if (Tok.K == Identifier && Tok.Value[0] == '@') {
+ Tok.Value.drop_front().getAsInteger(10, E.Ordinal);
+ read();
+ if (Tok.K == KwNoname) {
+ E.Noname = true;
+ } else {
+ unget();
+ }
+ continue;
+ }
+ if (Tok.K == KwData) {
+ E.Data = true;
+ continue;
+ }
+ if (Tok.K == KwPrivate) {
+ E.Private = true;
+ continue;
+ }
+ unget();
+ Config->Exports.push_back(E);
+ return;
+ }
+ }
+
+ // HEAPSIZE/STACKSIZE reserve[,commit]
+ void parseNumbers(uint64_t *Reserve, uint64_t *Commit) {
+ readAsInt(Reserve);
+ read();
+ if (Tok.K != Comma) {
+ unget();
+ Commit = nullptr;
+ return;
+ }
+ readAsInt(Commit);
+ }
+
+ // NAME outputPath [BASE=address]
+ void parseName(std::string *Out, uint64_t *Baseaddr) {
+ read();
+ if (Tok.K == Identifier) {
+ *Out = Tok.Value;
+ } else {
+ *Out = "";
+ unget();
+ return;
+ }
+ read();
+ if (Tok.K == KwBase) {
+ expect(Equal, "'=' expected");
+ readAsInt(Baseaddr);
+ } else {
+ unget();
+ *Baseaddr = 0;
+ }
+ }
+
+ // VERSION major[.minor]
+ void parseVersion(uint32_t *Major, uint32_t *Minor) {
+ read();
+ if (Tok.K != Identifier)
+ error(Twine("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);
+ if (V2.empty())
+ *Minor = 0;
+ else if (V2.getAsInteger(10, *Minor))
+ error(Twine("integer expected, but got ") + Tok.Value);
+ }
+
+ Lexer Lex;
+ Token Tok;
+ std::vector<Token> Stack;
+ StringSaver *Alloc;
+};
+
+} // anonymous namespace
+
+void parseModuleDefs(MemoryBufferRef MB, StringSaver *Alloc) {
+ Parser(MB.getBuffer(), Alloc).parse();
+}
+
+} // namespace coff
+} // namespace lld
diff --git a/COFF/Options.td b/COFF/Options.td
new file mode 100644
index 000000000000..a21b8de76afb
--- /dev/null
+++ b/COFF/Options.td
@@ -0,0 +1,125 @@
+include "llvm/Option/OptParser.td"
+
+// link.exe accepts options starting with either a dash or a slash.
+
+// Flag that takes no arguments.
+class F<string name> : Flag<["/", "-", "-?"], name>;
+
+// Flag that takes one argument after ":".
+class P<string name, string help> :
+ Joined<["/", "-", "-?"], name#":">, HelpText<help>;
+
+// Boolean flag suffixed by ":no".
+multiclass B<string name, string help> {
+ def "" : F<name>;
+ def _no : F<name#":no">, HelpText<help>;
+}
+
+def align : P<"align", "Section alignment">;
+def alternatename : P<"alternatename", "Define weak alias">;
+def base : P<"base", "Base address of the program">;
+def defaultlib : P<"defaultlib", "Add the library to the list of input files">;
+def delayload : P<"delayload", "Delay loaded DLL name">;
+def entry : P<"entry", "Name of entry point symbol">;
+def export : P<"export", "Export a function">;
+// No help text because /failifmismatch is not intended to be used by the user.
+def failifmismatch : P<"failifmismatch", "">;
+def heap : P<"heap", "Size of the heap">;
+def implib : P<"implib", "Import library name">;
+def libpath : P<"libpath", "Additional library search path">;
+def machine : P<"machine", "Specify target platform">;
+def merge : P<"merge", "Combine sections">;
+def mllvm : P<"mllvm", "Options to pass to LLVM">;
+def nodefaultlib : P<"nodefaultlib", "Remove a default library">;
+def opt : P<"opt", "Control optimizations">;
+def out : P<"out", "Path to file to write output">;
+def pdb : P<"pdb", "PDB file path">;
+def section : P<"section", "Specify section attributes">;
+def stack : P<"stack", "Size of the stack">;
+def stub : P<"stub", "Specify DOS stub file">;
+def subsystem : P<"subsystem", "Specify subsystem">;
+def version : P<"version", "Specify a version number in the PE header">;
+
+def disallowlib : Joined<["/", "-", "-?"], "disallowlib:">, Alias<nodefaultlib>;
+
+def manifest : F<"manifest">;
+def manifest_colon : P<"manifest", "Create manifest file">;
+def manifestuac : P<"manifestuac", "User access control">;
+def manifestfile : P<"manifestfile", "Manifest file path">;
+def manifestdependency : P<"manifestdependency",
+ "Attributes for <dependency> in 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
+// a reserved keyword in tablegen.
+def incl : Joined<["/", "-"], "include:">,
+ HelpText<"Force symbol to be added to symbol table as undefined one">;
+
+// "def" is also a keyword.
+def deffile : Joined<["/", "-"], "def:">,
+ HelpText<"Use module-definition file">;
+
+def debug : F<"debug">, HelpText<"Embed a symbol table in the image">;
+def dll : F<"dll">, HelpText<"Create a DLL">;
+def nodefaultlib_all : F<"nodefaultlib">;
+def noentry : F<"noentry">;
+def profile : F<"profile">;
+def swaprun_cd : F<"swaprun:cd">;
+def swaprun_net : F<"swaprun:net">;
+def verbose : F<"verbose">;
+
+def force : F<"force">,
+ HelpText<"Allow undefined symbols when creating executables">;
+def force_unresolved : F<"force:unresolved">;
+
+defm allowbind: B<"allowbind", "Disable DLL binding">;
+defm allowisolation : B<"allowisolation", "Set NO_ISOLATION bit">;
+defm dynamicbase : B<"dynamicbase",
+ "Disable address space layout randomization">;
+defm fixed : B<"fixed", "Enable base relocations">;
+defm highentropyva : B<"highentropyva", "Set HIGH_ENTROPY_VA bit">;
+defm largeaddressaware : B<"largeaddressaware", "Disable large addresses">;
+defm nxcompat : B<"nxcompat", "Disable data execution provention">;
+defm safeseh : B<"safeseh", "Produce an image with Safe Exception Handler">;
+defm tsaware : B<"tsaware", "Create non-Terminal Server aware executable">;
+
+def help : F<"help">;
+def help_q : Flag<["/?", "-?"], "">, Alias<help>;
+
+// LLD extensions
+def nosymtab : F<"nosymtab">;
+
+// Flags for debugging
+def lldmap : Joined<["/", "-"], "lldmap:">;
+
+//==============================================================================
+// The flags below do nothing. They are defined only for link.exe compatibility.
+//==============================================================================
+
+class QF<string name> : Joined<["/", "-", "-?"], name#":">;
+
+multiclass QB<string name> {
+ def "" : F<name>;
+ def _no : F<name#":no">;
+}
+
+def functionpadmin : F<"functionpadmin">;
+def ignoreidl : F<"ignoreidl">;
+def incremental : F<"incremental">;
+def no_incremental : F<"incremental:no">;
+def nologo : F<"nologo">;
+def throwingnew : F<"throwingnew">;
+def editandcontinue : F<"editandcontinue">;
+
+def delay : QF<"delay">;
+def errorreport : QF<"errorreport">;
+def idlout : QF<"idlout">;
+def ignore : QF<"ignore">;
+def maxilksize : QF<"maxilksize">;
+def pdbaltpath : QF<"pdbaltpath">;
+def tlbid : QF<"tlbid">;
+def tlbout : QF<"tlbout">;
+def verbose_all : QF<"verbose">;
+def guardsym : QF<"guardsym">;
+
+defm wx : QB<"wx">;
diff --git a/COFF/PDB.cpp b/COFF/PDB.cpp
new file mode 100644
index 000000000000..786d28798bab
--- /dev/null
+++ b/COFF/PDB.cpp
@@ -0,0 +1,60 @@
+//===- PDB.cpp ------------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Driver.h"
+#include "Error.h"
+#include "Symbols.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/FileOutputBuffer.h"
+#include <memory>
+
+using namespace llvm;
+using namespace llvm::support;
+using namespace llvm::support::endian;
+
+const int PageSize = 4096;
+const uint8_t Magic[32] = "Microsoft C/C++ MSF 7.00\r\n\032DS\0\0";
+
+namespace {
+struct PDBHeader {
+ uint8_t Magic[32];
+ ulittle32_t PageSize;
+ ulittle32_t FpmPage;
+ ulittle32_t PageCount;
+ ulittle32_t RootSize;
+ ulittle32_t Reserved;
+ ulittle32_t RootPointer;
+};
+}
+
+void lld::coff::createPDB(StringRef Path) {
+ // Create a file.
+ size_t FileSize = PageSize * 3;
+ ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
+ FileOutputBuffer::create(Path, FileSize);
+ error(BufferOrErr, Twine("failed to open ") + Path);
+ std::unique_ptr<FileOutputBuffer> Buffer = std::move(*BufferOrErr);
+
+ // Write the file header.
+ uint8_t *Buf = Buffer->getBufferStart();
+ auto *Hdr = reinterpret_cast<PDBHeader *>(Buf);
+ memcpy(Hdr->Magic, Magic, sizeof(Magic));
+ Hdr->PageSize = PageSize;
+ // I don't know what FpmPage field means, but it must not be 0.
+ Hdr->FpmPage = 1;
+ Hdr->PageCount = FileSize / PageSize;
+ // Root directory is empty, containing only the length field.
+ Hdr->RootSize = 4;
+ // Root directory is on page 1.
+ Hdr->RootPointer = 1;
+
+ // Write the root directory. Root stream is on page 2.
+ write32le(Buf + PageSize, 2);
+ Buffer->commit();
+}
diff --git a/COFF/README.md b/COFF/README.md
new file mode 100644
index 000000000000..c1be560f4405
--- /dev/null
+++ b/COFF/README.md
@@ -0,0 +1,265 @@
+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.
diff --git a/COFF/SymbolTable.cpp b/COFF/SymbolTable.cpp
new file mode 100644
index 000000000000..5b7b89cd360a
--- /dev/null
+++ b/COFF/SymbolTable.cpp
@@ -0,0 +1,445 @@
+//===- SymbolTable.cpp ----------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Config.h"
+#include "Driver.h"
+#include "Error.h"
+#include "SymbolTable.h"
+#include "Symbols.h"
+#include "lld/Core/Parallel.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/LTO/LTOCodeGenerator.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+#include <utility>
+
+using namespace llvm;
+
+namespace lld {
+namespace coff {
+
+void SymbolTable::addFile(std::unique_ptr<InputFile> FileP) {
+#if LLVM_ENABLE_THREADS
+ std::launch Policy = std::launch::async;
+#else
+ std::launch Policy = std::launch::deferred;
+#endif
+
+ InputFile *File = FileP.get();
+ Files.push_back(std::move(FileP));
+ if (auto *F = dyn_cast<ArchiveFile>(File)) {
+ ArchiveQueue.push_back(
+ std::async(Policy, [=]() { F->parse(); return F; }));
+ return;
+ }
+ ObjectQueue.push_back(
+ std::async(Policy, [=]() { File->parse(); return File; }));
+ if (auto *F = dyn_cast<ObjectFile>(File)) {
+ ObjectFiles.push_back(F);
+ } else if (auto *F = dyn_cast<BitcodeFile>(File)) {
+ BitcodeFiles.push_back(F);
+ } else {
+ ImportFiles.push_back(cast<ImportFile>(File));
+ }
+}
+
+void SymbolTable::step() {
+ if (queueEmpty())
+ return;
+ readObjects();
+ readArchives();
+}
+
+void SymbolTable::run() {
+ while (!queueEmpty())
+ step();
+}
+
+void SymbolTable::readArchives() {
+ if (ArchiveQueue.empty())
+ return;
+
+ // Add lazy symbols to the symbol table. Lazy symbols that conflict
+ // with existing undefined symbols are accumulated in LazySyms.
+ std::vector<Symbol *> LazySyms;
+ for (std::future<ArchiveFile *> &Future : ArchiveQueue) {
+ ArchiveFile *File = Future.get();
+ if (Config->Verbose)
+ llvm::outs() << "Reading " << File->getShortName() << "\n";
+ for (Lazy &Sym : File->getLazySymbols())
+ addLazy(&Sym, &LazySyms);
+ }
+ ArchiveQueue.clear();
+
+ // Add archive member files to ObjectQueue that should resolve
+ // existing undefined symbols.
+ for (Symbol *Sym : LazySyms)
+ addMemberFile(cast<Lazy>(Sym->Body));
+}
+
+void SymbolTable::readObjects() {
+ if (ObjectQueue.empty())
+ return;
+
+ // Add defined and undefined symbols to the symbol table.
+ std::vector<StringRef> Directives;
+ for (size_t I = 0; I < ObjectQueue.size(); ++I) {
+ InputFile *File = ObjectQueue[I].get();
+ if (Config->Verbose)
+ llvm::outs() << "Reading " << File->getShortName() << "\n";
+ // Adding symbols may add more files to ObjectQueue
+ // (but not to ArchiveQueue).
+ for (SymbolBody *Sym : File->getSymbols())
+ if (Sym->isExternal())
+ addSymbol(Sym);
+ StringRef S = File->getDirectives();
+ if (!S.empty()) {
+ Directives.push_back(S);
+ if (Config->Verbose)
+ llvm::outs() << "Directives: " << File->getShortName()
+ << ": " << S << "\n";
+ }
+ }
+ ObjectQueue.clear();
+
+ // Parse directive sections. This may add files to
+ // ArchiveQueue and ObjectQueue.
+ for (StringRef S : Directives)
+ Driver->parseDirectives(S);
+}
+
+bool SymbolTable::queueEmpty() {
+ return ArchiveQueue.empty() && ObjectQueue.empty();
+}
+
+void SymbolTable::reportRemainingUndefines(bool Resolve) {
+ llvm::SmallPtrSet<SymbolBody *, 8> Undefs;
+ for (auto &I : Symtab) {
+ Symbol *Sym = I.second;
+ auto *Undef = dyn_cast<Undefined>(Sym->Body);
+ if (!Undef)
+ continue;
+ StringRef Name = Undef->getName();
+ // A weak alias may have been resolved, so check for that.
+ if (Defined *D = Undef->getWeakAlias()) {
+ if (Resolve)
+ Sym->Body = D;
+ continue;
+ }
+ // If we can resolve a symbol by removing __imp_ prefix, do that.
+ // This odd rule is for compatibility with MSVC linker.
+ if (Name.startswith("__imp_")) {
+ Symbol *Imp = find(Name.substr(strlen("__imp_")));
+ if (Imp && isa<Defined>(Imp->Body)) {
+ if (!Resolve)
+ continue;
+ auto *D = cast<Defined>(Imp->Body);
+ auto *S = new (Alloc) DefinedLocalImport(Name, D);
+ LocalImportChunks.push_back(S->getChunk());
+ Sym->Body = S;
+ continue;
+ }
+ }
+ // Remaining undefined symbols are not fatal if /force is specified.
+ // They are replaced with dummy defined symbols.
+ if (Config->Force && Resolve)
+ Sym->Body = new (Alloc) DefinedAbsolute(Name, 0);
+ Undefs.insert(Sym->Body);
+ }
+ if (Undefs.empty())
+ return;
+ for (Undefined *U : Config->GCRoot)
+ if (Undefs.count(U->repl()))
+ llvm::errs() << "<root>: undefined symbol: " << U->getName() << "\n";
+ for (std::unique_ptr<InputFile> &File : Files)
+ if (!isa<ArchiveFile>(File.get()))
+ for (SymbolBody *Sym : File->getSymbols())
+ if (Undefs.count(Sym->repl()))
+ llvm::errs() << File->getShortName() << ": undefined symbol: "
+ << Sym->getName() << "\n";
+ if (!Config->Force)
+ error("Link failed");
+}
+
+void SymbolTable::addLazy(Lazy *New, std::vector<Symbol *> *Accum) {
+ Symbol *Sym = insert(New);
+ if (Sym->Body == New)
+ return;
+ SymbolBody *Existing = Sym->Body;
+ if (isa<Defined>(Existing))
+ return;
+ if (Lazy *L = dyn_cast<Lazy>(Existing))
+ if (L->getFileIndex() < New->getFileIndex())
+ return;
+ Sym->Body = New;
+ New->setBackref(Sym);
+ if (isa<Undefined>(Existing))
+ Accum->push_back(Sym);
+}
+
+void SymbolTable::addSymbol(SymbolBody *New) {
+ // Find an existing symbol or create and insert a new one.
+ assert(isa<Defined>(New) || isa<Undefined>(New));
+ Symbol *Sym = insert(New);
+ if (Sym->Body == New)
+ return;
+ SymbolBody *Existing = Sym->Body;
+
+ // If we have an undefined symbol and a lazy symbol,
+ // let the lazy symbol to read a member file.
+ if (auto *L = dyn_cast<Lazy>(Existing)) {
+ // Undefined symbols with weak aliases need not to be resolved,
+ // since they would be replaced with weak aliases if they remain
+ // undefined.
+ if (auto *U = dyn_cast<Undefined>(New)) {
+ if (!U->WeakAlias) {
+ addMemberFile(L);
+ return;
+ }
+ }
+ Sym->Body = New;
+ return;
+ }
+
+ // compare() returns -1, 0, or 1 if the lhs symbol is less preferable,
+ // equivalent (conflicting), or more preferable, respectively.
+ int Comp = Existing->compare(New);
+ if (Comp == 0)
+ error(Twine("duplicate symbol: ") + Existing->getDebugName() + " and " +
+ New->getDebugName());
+ if (Comp < 0)
+ Sym->Body = New;
+}
+
+Symbol *SymbolTable::insert(SymbolBody *New) {
+ Symbol *&Sym = Symtab[New->getName()];
+ if (Sym) {
+ New->setBackref(Sym);
+ return Sym;
+ }
+ Sym = new (Alloc) Symbol(New);
+ New->setBackref(Sym);
+ return Sym;
+}
+
+// Reads an archive member file pointed by a given symbol.
+void SymbolTable::addMemberFile(Lazy *Body) {
+ std::unique_ptr<InputFile> File = Body->getMember();
+
+ // getMember returns an empty buffer if the member was already
+ // read from the library.
+ if (!File)
+ return;
+ if (Config->Verbose)
+ llvm::outs() << "Loaded " << File->getShortName() << " for "
+ << Body->getName() << "\n";
+ addFile(std::move(File));
+}
+
+std::vector<Chunk *> SymbolTable::getChunks() {
+ std::vector<Chunk *> Res;
+ for (ObjectFile *File : ObjectFiles) {
+ std::vector<Chunk *> &V = File->getChunks();
+ Res.insert(Res.end(), V.begin(), V.end());
+ }
+ return Res;
+}
+
+Symbol *SymbolTable::find(StringRef Name) {
+ auto It = Symtab.find(Name);
+ if (It == Symtab.end())
+ return nullptr;
+ return It->second;
+}
+
+Symbol *SymbolTable::findUnderscore(StringRef Name) {
+ if (Config->Machine == I386)
+ return find(("_" + Name).str());
+ return find(Name);
+}
+
+StringRef SymbolTable::findByPrefix(StringRef Prefix) {
+ for (auto Pair : Symtab) {
+ StringRef Name = Pair.first;
+ if (Name.startswith(Prefix))
+ return Name;
+ }
+ return "";
+}
+
+StringRef SymbolTable::findMangle(StringRef Name) {
+ if (Symbol *Sym = find(Name))
+ if (!isa<Undefined>(Sym->Body))
+ return Name;
+ if (Config->Machine != I386)
+ return findByPrefix(("?" + Name + "@@Y").str());
+ if (!Name.startswith("_"))
+ return "";
+ // Search for x86 C function.
+ StringRef S = findByPrefix((Name + "@").str());
+ if (!S.empty())
+ return S;
+ // Search for x86 C++ non-member function.
+ return findByPrefix(("?" + Name.substr(1) + "@@Y").str());
+}
+
+void SymbolTable::mangleMaybe(Undefined *U) {
+ if (U->WeakAlias)
+ return;
+ if (!isa<Undefined>(U->repl()))
+ return;
+ StringRef Alias = findMangle(U->getName());
+ if (!Alias.empty())
+ U->WeakAlias = addUndefined(Alias);
+}
+
+Undefined *SymbolTable::addUndefined(StringRef Name) {
+ auto *New = new (Alloc) Undefined(Name);
+ addSymbol(New);
+ if (auto *U = dyn_cast<Undefined>(New->repl()))
+ return U;
+ return New;
+}
+
+DefinedRelative *SymbolTable::addRelative(StringRef Name, uint64_t VA) {
+ auto *New = new (Alloc) DefinedRelative(Name, VA);
+ addSymbol(New);
+ return New;
+}
+
+DefinedAbsolute *SymbolTable::addAbsolute(StringRef Name, uint64_t VA) {
+ auto *New = new (Alloc) DefinedAbsolute(Name, VA);
+ addSymbol(New);
+ return New;
+}
+
+void SymbolTable::printMap(llvm::raw_ostream &OS) {
+ for (ObjectFile *File : ObjectFiles) {
+ OS << File->getShortName() << ":\n";
+ for (SymbolBody *Body : File->getSymbols())
+ if (auto *R = dyn_cast<DefinedRegular>(Body))
+ if (R->getChunk()->isLive())
+ OS << Twine::utohexstr(Config->ImageBase + R->getRVA())
+ << " " << R->getName() << "\n";
+ }
+}
+
+void SymbolTable::addCombinedLTOObject(ObjectFile *Obj) {
+ for (SymbolBody *Body : Obj->getSymbols()) {
+ if (!Body->isExternal())
+ continue;
+ // We should not see any new undefined symbols at this point, but we'll
+ // diagnose them later in reportRemainingUndefines().
+ StringRef Name = Body->getName();
+ Symbol *Sym = insert(Body);
+
+ if (isa<DefinedBitcode>(Sym->Body)) {
+ Sym->Body = Body;
+ continue;
+ }
+ if (auto *L = dyn_cast<Lazy>(Sym->Body)) {
+ // 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);
+ if (Comp < 0)
+ Sym->Body = Body;
+ }
+}
+
+void SymbolTable::addCombinedLTOObjects() {
+ if (BitcodeFiles.empty())
+ return;
+
+ // Diagnose any undefined symbols early, but do not resolve weak externals,
+ // as resolution breaks the invariant that each Symbol points to a unique
+ // SymbolBody, which we rely on to replace DefinedBitcode symbols correctly.
+ reportRemainingUndefines(/*Resolve=*/false);
+
+ // 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());
+ CG.setOptLevel(Config->LTOOptLevel);
+ std::vector<ObjectFile *> Objs = createLTOObjects(&CG);
+
+ for (ObjectFile *Obj : Objs)
+ addCombinedLTOObject(Obj);
+
+ size_t NumBitcodeFiles = BitcodeFiles.size();
+ run();
+ if (BitcodeFiles.size() != NumBitcodeFiles)
+ error("LTO: late loaded symbol created new bitcode reference");
+}
+
+// Combine and compile bitcode files and then return the result
+// as a vector of regular COFF object files.
+std::vector<ObjectFile *> SymbolTable::createLTOObjects(LTOCodeGenerator *CG) {
+ // All symbols referenced by non-bitcode objects must be preserved.
+ for (ObjectFile *File : ObjectFiles)
+ for (SymbolBody *Body : File->getSymbols())
+ if (auto *S = dyn_cast<DefinedBitcode>(Body->repl()))
+ CG->addMustPreserveSymbol(S->getName());
+
+ // Likewise for bitcode symbols which we initially resolved to non-bitcode.
+ for (BitcodeFile *File : BitcodeFiles)
+ for (SymbolBody *Body : File->getSymbols())
+ if (isa<DefinedBitcode>(Body) && !isa<DefinedBitcode>(Body->repl()))
+ CG->addMustPreserveSymbol(Body->getName());
+
+ // Likewise for other symbols that must be preserved.
+ for (Undefined *U : Config->GCRoot) {
+ if (auto *S = dyn_cast<DefinedBitcode>(U->repl()))
+ CG->addMustPreserveSymbol(S->getName());
+ else if (auto *S = dyn_cast_or_null<DefinedBitcode>(U->getWeakAlias()))
+ CG->addMustPreserveSymbol(S->getName());
+ }
+
+ CG->setModule(BitcodeFiles[0]->takeModule());
+ for (unsigned I = 1, E = BitcodeFiles.size(); I != E; ++I)
+ CG->addModule(BitcodeFiles[I]->takeModule().get());
+
+ bool DisableVerify = true;
+#ifdef NDEBUG
+ DisableVerify = false;
+#endif
+ if (!CG->optimize(DisableVerify, false, false, false))
+ error(""); // 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) {
+ OSs.emplace_back(Obj);
+ OSPtrs.push_back(&OSs.back());
+ }
+
+ if (!CG->compileOptimized(OSPtrs))
+ error(""); // 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>"));
+ Files.emplace_back(ObjFile);
+ ObjectFiles.push_back(ObjFile);
+ ObjFile->parse();
+ ObjFiles.push_back(ObjFile);
+ }
+
+ return ObjFiles;
+}
+
+} // namespace coff
+} // namespace lld
diff --git a/COFF/SymbolTable.h b/COFF/SymbolTable.h
new file mode 100644
index 000000000000..ce305bfa8743
--- /dev/null
+++ b/COFF/SymbolTable.h
@@ -0,0 +1,125 @@
+//===- SymbolTable.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_SYMBOL_TABLE_H
+#define LLD_COFF_SYMBOL_TABLE_H
+
+#include "InputFiles.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/Support/Allocator.h"
+#include "llvm/Support/raw_ostream.h"
+
+#ifdef _MSC_VER
+// <future> depends on <eh.h> for __uncaught_exception.
+#include <eh.h>
+#endif
+
+#include <future>
+
+namespace llvm {
+struct LTOCodeGenerator;
+}
+
+namespace lld {
+namespace coff {
+
+class Chunk;
+class Defined;
+class Lazy;
+class SymbolBody;
+struct Symbol;
+
+// SymbolTable is a bucket of all known symbols, including defined,
+// undefined, or lazy symbols (the last one is symbols in archive
+// files whose archive members are not yet loaded).
+//
+// We put all symbols of all files to a SymbolTable, and the
+// SymbolTable selects the "best" symbols if there are name
+// 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().
+class SymbolTable {
+public:
+ void addFile(std::unique_ptr<InputFile> File);
+ std::vector<std::unique_ptr<InputFile>> &getFiles() { return Files; }
+ void step();
+ void run();
+ bool queueEmpty();
+
+ // Print an error message on undefined symbols. If Resolve is true, try to
+ // resolve any undefined symbols and update the symbol table accordingly.
+ void reportRemainingUndefines(bool Resolve);
+
+ // Returns a list of chunks of selected symbols.
+ std::vector<Chunk *> getChunks();
+
+ // Returns a symbol for a given name. Returns a nullptr if not found.
+ Symbol *find(StringRef Name);
+ Symbol *findUnderscore(StringRef Name);
+
+ // Occasionally we have to resolve an undefined symbol to its
+ // mangled symbol. This function tries to find a mangled name
+ // for U from the symbol table, and if found, set the symbol as
+ // a weak alias for U.
+ void mangleMaybe(Undefined *U);
+ StringRef findMangle(StringRef Name);
+
+ // Print a layout map to OS.
+ void printMap(llvm::raw_ostream &OS);
+
+ // Build a set of COFF objects representing the combined contents of
+ // BitcodeFiles and add them to the symbol table. Called after all files are
+ // added and before the writer writes results to a file.
+ void addCombinedLTOObjects();
+
+ // The writer needs to handle DLL import libraries specially in
+ // order to create the import descriptor table.
+ std::vector<ImportFile *> ImportFiles;
+
+ // The writer needs to infer the machine type from the object files.
+ std::vector<ObjectFile *> ObjectFiles;
+
+ // Creates an Undefined symbol for a given name.
+ Undefined *addUndefined(StringRef Name);
+ DefinedRelative *addRelative(StringRef Name, uint64_t VA);
+ DefinedAbsolute *addAbsolute(StringRef Name, uint64_t VA);
+
+ // A list of chunks which to be added to .rdata.
+ std::vector<Chunk *> LocalImportChunks;
+
+private:
+ void readArchives();
+ void readObjects();
+
+ void addSymbol(SymbolBody *New);
+ void addLazy(Lazy *New, std::vector<Symbol *> *Accum);
+ Symbol *insert(SymbolBody *New);
+ StringRef findByPrefix(StringRef Prefix);
+
+ void addMemberFile(Lazy *Body);
+ void addCombinedLTOObject(ObjectFile *Obj);
+ std::vector<ObjectFile *> createLTOObjects(llvm::LTOCodeGenerator *CG);
+
+ llvm::DenseMap<StringRef, Symbol *> Symtab;
+
+ std::vector<std::unique_ptr<InputFile>> Files;
+ std::vector<std::future<ArchiveFile *>> ArchiveQueue;
+ std::vector<std::future<InputFile *>> ObjectQueue;
+
+ std::vector<BitcodeFile *> BitcodeFiles;
+ std::vector<SmallVector<char, 0>> Objs;
+ llvm::BumpPtrAllocator Alloc;
+};
+
+} // namespace coff
+} // namespace lld
+
+#endif
diff --git a/COFF/Symbols.cpp b/COFF/Symbols.cpp
new file mode 100644
index 000000000000..d732d76cfb06
--- /dev/null
+++ b/COFF/Symbols.cpp
@@ -0,0 +1,243 @@
+//===- Symbols.cpp --------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Error.h"
+#include "InputFiles.h"
+#include "Symbols.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace llvm::object;
+using llvm::sys::fs::identify_magic;
+using llvm::sys::fs::file_magic;
+
+namespace lld {
+namespace coff {
+
+StringRef SymbolBody::getName() {
+ // DefinedCOFF names are read lazily for a performance reason.
+ // Non-external symbol names are never used by the linker except for logging
+ // or debugging. Their internal references are resolved not by name but by
+ // symbol index. And because they are not external, no one can refer them by
+ // name. Object files contain lots of non-external symbols, and creating
+ // StringRefs for them (which involves lots of strlen() on the string table)
+ // is a waste of time.
+ if (Name.empty()) {
+ auto *D = cast<DefinedCOFF>(this);
+ D->File->getCOFFObj()->getSymbolName(D->Sym, Name);
+ }
+ return Name;
+}
+
+// Returns 1, 0 or -1 if this symbol should take precedence
+// over the Other, tie or lose, respectively.
+int SymbolBody::compare(SymbolBody *Other) {
+ Kind LK = kind(), RK = Other->kind();
+
+ // Normalize so that the smaller kind is on the left.
+ if (LK > RK)
+ return -Other->compare(this);
+
+ // First handle comparisons between two different kinds.
+ if (LK != RK) {
+ if (RK > LastDefinedKind) {
+ if (LK == LazyKind && cast<Undefined>(Other)->WeakAlias)
+ return -1;
+
+ // The LHS is either defined or lazy and so it wins.
+ assert((LK <= LastDefinedKind || LK == LazyKind) && "Bad kind!");
+ return 1;
+ }
+
+ // Bitcode has special complexities.
+ if (RK == DefinedBitcodeKind) {
+ auto *RHS = cast<DefinedBitcode>(Other);
+
+ switch (LK) {
+ case DefinedCommonKind:
+ return 1;
+
+ case DefinedRegularKind:
+ // As an approximation, regular symbols win over bitcode symbols,
+ // but we definitely have a conflict if the regular symbol is not
+ // replaceable and neither is the bitcode symbol. We do not
+ // replicate the rest of the symbol resolution logic here; symbol
+ // resolution will be done accurately after lowering bitcode symbols
+ // to regular symbols in addCombinedLTOObject().
+ if (cast<DefinedRegular>(this)->isCOMDAT() || RHS->IsReplaceable)
+ return 1;
+
+ // Fallthrough to the default of a tie otherwise.
+ default:
+ return 0;
+ }
+ }
+
+ // Either of the object file kind will trump a higher kind.
+ if (LK <= LastDefinedCOFFKind)
+ return 1;
+
+ // The remaining kind pairs are ties amongst defined symbols.
+ return 0;
+ }
+
+ // Now handle the case where the kinds are the same.
+ switch (LK) {
+ case DefinedRegularKind: {
+ auto *LHS = cast<DefinedRegular>(this);
+ auto *RHS = cast<DefinedRegular>(Other);
+ if (LHS->isCOMDAT() && RHS->isCOMDAT())
+ return LHS->getFileIndex() < RHS->getFileIndex() ? 1 : -1;
+ return 0;
+ }
+
+ case DefinedCommonKind: {
+ auto *LHS = cast<DefinedCommon>(this);
+ auto *RHS = cast<DefinedCommon>(Other);
+ if (LHS->getSize() == RHS->getSize())
+ return LHS->getFileIndex() < RHS->getFileIndex() ? 1 : -1;
+ return LHS->getSize() > RHS->getSize() ? 1 : -1;
+ }
+
+ case DefinedBitcodeKind: {
+ auto *LHS = cast<DefinedBitcode>(this);
+ auto *RHS = cast<DefinedBitcode>(Other);
+ // If both are non-replaceable, we have a tie.
+ if (!LHS->IsReplaceable && !RHS->IsReplaceable)
+ return 0;
+
+ // Non-replaceable symbols win, but even two replaceable symboles don't
+ // tie. If both symbols are replaceable, choice is arbitrary.
+ if (RHS->IsReplaceable && LHS->IsReplaceable)
+ return uintptr_t(LHS) < uintptr_t(RHS) ? 1 : -1;
+ return LHS->IsReplaceable ? -1 : 1;
+ }
+
+ case LazyKind: {
+ // Don't tie, pick the earliest.
+ auto *LHS = cast<Lazy>(this);
+ auto *RHS = cast<Lazy>(Other);
+ return LHS->getFileIndex() < RHS->getFileIndex() ? 1 : -1;
+ }
+
+ case UndefinedKind: {
+ auto *LHS = cast<Undefined>(this);
+ auto *RHS = cast<Undefined>(Other);
+ // Tie if both undefined symbols have different weak aliases.
+ if (LHS->WeakAlias && RHS->WeakAlias) {
+ if (LHS->WeakAlias->getName() != RHS->WeakAlias->getName())
+ return 0;
+ return uintptr_t(LHS) < uintptr_t(RHS) ? 1 : -1;
+ }
+ return LHS->WeakAlias ? 1 : -1;
+ }
+
+ case DefinedLocalImportKind:
+ case DefinedImportThunkKind:
+ case DefinedImportDataKind:
+ case DefinedAbsoluteKind:
+ case DefinedRelativeKind:
+ // These all simply tie.
+ return 0;
+ }
+ llvm_unreachable("unknown symbol kind");
+}
+
+std::string SymbolBody::getDebugName() {
+ std::string N = getName().str();
+ if (auto *D = dyn_cast<DefinedCOFF>(this)) {
+ N += " ";
+ N += D->File->getShortName();
+ } else if (auto *D = dyn_cast<DefinedBitcode>(this)) {
+ N += " ";
+ N += D->File->getShortName();
+ }
+ 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))
+ return COFFSymbolRef(reinterpret_cast<const coff_symbol16 *>(Sym));
+ assert(SymSize == sizeof(coff_symbol32));
+ return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(Sym));
+}
+
+DefinedImportThunk::DefinedImportThunk(StringRef Name, DefinedImportData *S,
+ uint16_t Machine)
+ : Defined(DefinedImportThunkKind, Name) {
+ switch (Machine) {
+ case AMD64: Data.reset(new ImportThunkChunkX64(S)); return;
+ case I386: Data.reset(new ImportThunkChunkX86(S)); return;
+ case ARMNT: Data.reset(new ImportThunkChunkARM(S)); return;
+ default: llvm_unreachable("unknown machine type");
+ }
+}
+
+std::unique_ptr<InputFile> Lazy::getMember() {
+ 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);
+
+ file_magic Magic = identify_magic(MBRef.getBuffer());
+ if (Magic == file_magic::coff_import_library)
+ return std::unique_ptr<InputFile>(new ImportFile(MBRef));
+
+ std::unique_ptr<InputFile> Obj;
+ if (Magic == file_magic::coff_object)
+ Obj.reset(new ObjectFile(MBRef));
+ else if (Magic == file_magic::bitcode)
+ Obj.reset(new BitcodeFile(MBRef));
+ else
+ error(Twine(File->getName()) + ": unknown file type");
+
+ Obj->setParentName(File->getName());
+ return Obj;
+}
+
+Defined *Undefined::getWeakAlias() {
+ // A weak alias may be a weak alias to another symbol, so check recursively.
+ for (SymbolBody *A = WeakAlias; A; A = cast<Undefined>(A)->WeakAlias)
+ if (auto *D = dyn_cast<Defined>(A->repl()))
+ return D;
+ return nullptr;
+}
+
+} // namespace coff
+} // namespace lld
diff --git a/COFF/Symbols.h b/COFF/Symbols.h
new file mode 100644
index 000000000000..7059fbc8bb15
--- /dev/null
+++ b/COFF/Symbols.h
@@ -0,0 +1,407 @@
+//===- Symbols.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_SYMBOLS_H
+#define LLD_COFF_SYMBOLS_H
+
+#include "Chunks.h"
+#include "Config.h"
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/COFF.h"
+#include <atomic>
+#include <memory>
+#include <vector>
+
+namespace lld {
+namespace coff {
+
+using llvm::object::Archive;
+using llvm::object::COFFSymbolRef;
+using llvm::object::coff_import_header;
+using llvm::object::coff_symbol_generic;
+
+class ArchiveFile;
+class BitcodeFile;
+class InputFile;
+class ObjectFile;
+class SymbolBody;
+
+// 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 {
+ explicit Symbol(SymbolBody *P) : Body(P) {}
+ SymbolBody *Body;
+};
+
+// The base class for real symbol classes.
+class SymbolBody {
+public:
+ enum Kind {
+ // The order of these is significant. We start with the regular defined
+ // symbols as those are the most prevelant and the zero tag is the cheapest
+ // to set. Among the defined kinds, the lower the kind is preferred over
+ // the higher kind when testing wether one symbol should take precedence
+ // over another.
+ DefinedRegularKind = 0,
+ DefinedCommonKind,
+ DefinedLocalImportKind,
+ DefinedImportThunkKind,
+ DefinedImportDataKind,
+ DefinedAbsoluteKind,
+ DefinedRelativeKind,
+ DefinedBitcodeKind,
+
+ UndefinedKind,
+ LazyKind,
+
+ LastDefinedCOFFKind = DefinedCommonKind,
+ LastDefinedKind = DefinedBitcodeKind,
+ };
+
+ Kind kind() const { return static_cast<Kind>(SymbolKind); }
+
+ // Returns true if this is an external symbol.
+ bool isExternal() { return IsExternal; }
+
+ // Returns the symbol name.
+ StringRef getName();
+
+ // 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; }
+
+ // 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.
+ int compare(SymbolBody *Other);
+
+ // Returns a name of this symbol including source file name.
+ // Used only for debugging and logging.
+ std::string getDebugName();
+
+protected:
+ explicit SymbolBody(Kind K, StringRef N = "")
+ : SymbolKind(K), IsExternal(true), IsCOMDAT(false),
+ IsReplaceable(false), Name(N) {}
+
+ const unsigned SymbolKind : 8;
+ unsigned IsExternal : 1;
+
+ // This bit is used by the \c DefinedRegular subclass.
+ unsigned IsCOMDAT : 1;
+
+ // This bit is used by the \c DefinedBitcode subclass.
+ unsigned IsReplaceable : 1;
+
+ StringRef Name;
+ Symbol *Backref = nullptr;
+};
+
+// The base class for any defined symbols, including absolute symbols,
+// etc.
+class Defined : public SymbolBody {
+public:
+ Defined(Kind K, StringRef N = "") : SymbolBody(K, N) {}
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() <= LastDefinedKind;
+ }
+
+ // Returns the RVA (relative virtual address) of this symbol. The
+ // 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();
+
+ // Returns the output section index.
+ // Used to implement SECTION relocation type.
+ uint64_t getSectionIndex();
+
+ // Returns true if this symbol points to an executable (e.g. .text) section.
+ // Used to implement ARM relocations.
+ bool isExecutable();
+};
+
+// Symbols defined via a COFF object file.
+class DefinedCOFF : public Defined {
+ friend SymbolBody;
+public:
+ DefinedCOFF(Kind K, ObjectFile *F, COFFSymbolRef S)
+ : Defined(K), File(F), Sym(S.getGeneric()) {}
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() <= LastDefinedCOFFKind;
+ }
+
+ int getFileIndex() { return File->Index; }
+
+ COFFSymbolRef getCOFFSymbol();
+
+protected:
+ ObjectFile *File;
+ const coff_symbol_generic *Sym;
+};
+
+// Regular defined symbols read from object file symbol tables.
+class DefinedRegular : public DefinedCOFF {
+public:
+ DefinedRegular(ObjectFile *F, COFFSymbolRef S, SectionChunk *C)
+ : DefinedCOFF(DefinedRegularKind, F, S), Data(&C->Repl) {
+ IsExternal = S.isExternal();
+ IsCOMDAT = C->isCOMDAT();
+ }
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() == DefinedRegularKind;
+ }
+
+ uint64_t getRVA() { return (*Data)->getRVA() + Sym->Value; }
+ bool isCOMDAT() { return IsCOMDAT; }
+ SectionChunk *getChunk() { return *Data; }
+ uint32_t getValue() { return Sym->Value; }
+
+private:
+ SectionChunk **Data;
+};
+
+class DefinedCommon : public DefinedCOFF {
+public:
+ DefinedCommon(ObjectFile *F, COFFSymbolRef S, CommonChunk *C)
+ : DefinedCOFF(DefinedCommonKind, F, S), Data(C) {
+ IsExternal = S.isExternal();
+ }
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() == DefinedCommonKind;
+ }
+
+ uint64_t getRVA() { return Data->getRVA(); }
+
+private:
+ friend SymbolBody;
+ uint64_t getSize() { return Sym->Value; }
+ CommonChunk *Data;
+};
+
+// Absolute symbols.
+class DefinedAbsolute : public Defined {
+public:
+ DefinedAbsolute(StringRef N, COFFSymbolRef S)
+ : Defined(DefinedAbsoluteKind, N), VA(S.getValue()) {
+ IsExternal = S.isExternal();
+ }
+
+ DefinedAbsolute(StringRef N, uint64_t V)
+ : Defined(DefinedAbsoluteKind, N), VA(V) {}
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() == DefinedAbsoluteKind;
+ }
+
+ uint64_t getRVA() { return VA - Config->ImageBase; }
+ void setVA(uint64_t V) { VA = V; }
+
+private:
+ uint64_t VA;
+};
+
+// This is a kind of absolute symbol but relative to the image base.
+// Unlike absolute symbols, relocations referring this kind of symbols
+// are subject of the base relocation. This type is used rarely --
+// mainly for __ImageBase.
+class DefinedRelative : public Defined {
+public:
+ explicit DefinedRelative(StringRef Name, uint64_t V = 0)
+ : Defined(DefinedRelativeKind, Name), RVA(V) {}
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() == DefinedRelativeKind;
+ }
+
+ uint64_t getRVA() { return RVA; }
+ void setRVA(uint64_t V) { RVA = V; }
+
+private:
+ uint64_t RVA;
+};
+
+// This class represents a symbol defined in an archive file. It is
+// created from an archive file header, and it knows how to load an
+// object file from an archive to replace itself with a defined
+// symbol. If the resolver finds both Undefined and Lazy for
+// the same name, it will ask the Lazy to load a file.
+class Lazy : public SymbolBody {
+public:
+ Lazy(ArchiveFile *F, const Archive::Symbol S)
+ : SymbolBody(LazyKind, S.getName()), File(F), Sym(S) {}
+
+ static bool classof(const SymbolBody *S) { return S->kind() == LazyKind; }
+
+ // Returns an object file for this symbol, or a nullptr if the file
+ // was already returned.
+ std::unique_ptr<InputFile> getMember();
+
+ int getFileIndex() { return File->Index; }
+
+private:
+ ArchiveFile *File;
+ const Archive::Symbol Sym;
+};
+
+// Undefined symbols.
+class Undefined : public SymbolBody {
+public:
+ explicit Undefined(StringRef N) : SymbolBody(UndefinedKind, N) {}
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() == UndefinedKind;
+ }
+
+ // An undefined symbol can have a fallback symbol which gives an
+ // undefined symbol a second chance if it would remain undefined.
+ // If it remains undefined, it'll be replaced with whatever the
+ // Alias pointer points to.
+ SymbolBody *WeakAlias = nullptr;
+
+ // If this symbol is external weak, try to resolve it to a defined
+ // symbol by searching the chain of fallback symbols. Returns the symbol if
+ // successful, otherwise returns null.
+ Defined *getWeakAlias();
+};
+
+// Windows-specific classes.
+
+// This class represents a symbol imported from a DLL. This has two
+// names for internal use and external use. The former is used for
+// name resolution, and the latter is used for the import descriptor
+// table in an output. The former has "__imp_" prefix.
+class DefinedImportData : public Defined {
+public:
+ DefinedImportData(StringRef D, StringRef N, StringRef E,
+ const coff_import_header *H)
+ : Defined(DefinedImportDataKind, N), DLLName(D), ExternalName(E), Hdr(H) {
+ }
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() == DefinedImportDataKind;
+ }
+
+ uint64_t getRVA() { return Location->getRVA(); }
+ StringRef getDLLName() { return DLLName; }
+ StringRef getExternalName() { return ExternalName; }
+ void setLocation(Chunk *AddressTable) { Location = AddressTable; }
+ uint16_t getOrdinal() { return Hdr->OrdinalHint; }
+
+private:
+ StringRef DLLName;
+ StringRef ExternalName;
+ const coff_import_header *Hdr;
+ Chunk *Location = nullptr;
+};
+
+// This class represents a symbol for a jump table entry which jumps
+// to a function in a DLL. Linker are supposed to create such symbols
+// without "__imp_" prefix for all function symbols exported from
+// DLLs, so that you can call DLL functions as regular functions with
+// a regular name. A function pointer is given as a DefinedImportData.
+class DefinedImportThunk : public Defined {
+public:
+ DefinedImportThunk(StringRef Name, DefinedImportData *S, uint16_t Machine);
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() == DefinedImportThunkKind;
+ }
+
+ uint64_t getRVA() { return Data->getRVA(); }
+ Chunk *getChunk() { return Data.get(); }
+
+private:
+ std::unique_ptr<Chunk> Data;
+};
+
+// If you have a symbol "__imp_foo" in your object file, a symbol name
+// "foo" becomes automatically available as a pointer to "__imp_foo".
+// This class is for such automatically-created symbols.
+// Yes, this is an odd feature. We didn't intend to implement that.
+// This is here just for compatibility with MSVC.
+class DefinedLocalImport : public Defined {
+public:
+ DefinedLocalImport(StringRef N, Defined *S)
+ : Defined(DefinedLocalImportKind, N), Data(S) {}
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() == DefinedLocalImportKind;
+ }
+
+ uint64_t getRVA() { return Data.getRVA(); }
+ Chunk *getChunk() { return &Data; }
+
+private:
+ LocalImportChunk Data;
+};
+
+class DefinedBitcode : public Defined {
+ friend SymbolBody;
+public:
+ DefinedBitcode(BitcodeFile *F, StringRef N, bool IsReplaceable)
+ : Defined(DefinedBitcodeKind, N), File(F) {
+ this->IsReplaceable = IsReplaceable;
+ }
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() == DefinedBitcodeKind;
+ }
+
+private:
+ BitcodeFile *File;
+};
+
+inline uint64_t Defined::getRVA() {
+ switch (kind()) {
+ case DefinedAbsoluteKind:
+ return cast<DefinedAbsolute>(this)->getRVA();
+ case DefinedRelativeKind:
+ return cast<DefinedRelative>(this)->getRVA();
+ case DefinedImportDataKind:
+ return cast<DefinedImportData>(this)->getRVA();
+ case DefinedImportThunkKind:
+ return cast<DefinedImportThunk>(this)->getRVA();
+ case DefinedLocalImportKind:
+ return cast<DefinedLocalImport>(this)->getRVA();
+ case DefinedCommonKind:
+ return cast<DefinedCommon>(this)->getRVA();
+ case DefinedRegularKind:
+ return cast<DefinedRegular>(this)->getRVA();
+ case DefinedBitcodeKind:
+ llvm_unreachable("There is no address for a bitcode symbol.");
+ case LazyKind:
+ case UndefinedKind:
+ llvm_unreachable("Cannot get the address for an undefined symbol.");
+ }
+ llvm_unreachable("unknown symbol kind");
+}
+
+} // namespace coff
+} // namespace lld
+
+#endif
diff --git a/COFF/Writer.cpp b/COFF/Writer.cpp
new file mode 100644
index 000000000000..a74b316b87a4
--- /dev/null
+++ b/COFF/Writer.cpp
@@ -0,0 +1,765 @@
+//===- Writer.cpp ---------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Config.h"
+#include "DLL.h"
+#include "Error.h"
+#include "InputFiles.h"
+#include "SymbolTable.h"
+#include "Symbols.h"
+#include "Writer.h"
+#include "lld/Core/Parallel.h"
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/Debug.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/FileOutputBuffer.h"
+#include "llvm/Support/raw_ostream.h"
+#include <algorithm>
+#include <cstdio>
+#include <map>
+#include <memory>
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::COFF;
+using namespace llvm::object;
+using namespace llvm::support;
+using namespace llvm::support::endian;
+using namespace lld;
+using namespace lld::coff;
+
+static const int PageSize = 4096;
+static const int SectorSize = 512;
+static const int DOSStubSize = 64;
+static const int NumberfOfDataDirectory = 16;
+
+namespace {
+// The writer writes a SymbolTable result to a file.
+class Writer {
+public:
+ Writer(SymbolTable *T) : Symtab(T) {}
+ void run();
+
+private:
+ void createSections();
+ void createMiscChunks();
+ void createImportTables();
+ void createExportTable();
+ void assignAddresses();
+ void removeEmptySections();
+ void createSymbolAndStringTable();
+ void openFile(StringRef OutputPath);
+ template <typename PEHeaderTy> void writeHeader();
+ void fixSafeSEHSymbols();
+ void writeSections();
+ void sortExceptionTable();
+ void applyRelocations();
+
+ llvm::Optional<coff_symbol16> createSymbol(Defined *D);
+ size_t addEntryToStringTable(StringRef Str);
+
+ OutputSection *findSection(StringRef Name);
+ OutputSection *createSection(StringRef Name);
+ void addBaserels(OutputSection *Dest);
+ void addBaserelBlocks(OutputSection *Dest, std::vector<Baserel> &V);
+
+ uint32_t getSizeOfInitializedData();
+ std::map<StringRef, std::vector<DefinedImportData *>> binImports();
+
+ SymbolTable *Symtab;
+ std::unique_ptr<llvm::FileOutputBuffer> Buffer;
+ llvm::SpecificBumpPtrAllocator<OutputSection> CAlloc;
+ llvm::SpecificBumpPtrAllocator<BaserelChunk> BAlloc;
+ std::vector<OutputSection *> OutputSections;
+ std::vector<char> Strtab;
+ std::vector<llvm::object::coff_symbol16> OutputSymtab;
+ IdataContents Idata;
+ DelayLoadContents DelayIdata;
+ EdataContents Edata;
+ std::unique_ptr<SEHTableChunk> SEHTable;
+
+ uint64_t FileSize;
+ uint32_t PointerToSymbolTable = 0;
+ uint64_t SizeOfImage;
+ uint64_t SizeOfHeaders;
+
+ std::vector<std::unique_ptr<Chunk>> Chunks;
+};
+} // anonymous namespace
+
+namespace lld {
+namespace coff {
+
+void writeResult(SymbolTable *T) { Writer(T).run(); }
+
+// OutputSection represents a section in an output file. It's a
+// container of chunks. OutputSection and Chunk are 1:N relationship.
+// Chunks cannot belong to more than one OutputSections. The writer
+// creates multiple OutputSections and assign them unique,
+// non-overlapping file offsets and RVAs.
+class OutputSection {
+public:
+ OutputSection(StringRef N) : Name(N), Header({}) {}
+ void setRVA(uint64_t);
+ void setFileOffset(uint64_t);
+ void addChunk(Chunk *C);
+ StringRef getName() { return Name; }
+ std::vector<Chunk *> &getChunks() { return Chunks; }
+ void addPermissions(uint32_t C);
+ uint32_t getPermissions() { return Header.Characteristics & PermMask; }
+ uint32_t getCharacteristics() { return Header.Characteristics; }
+ uint64_t getRVA() { return Header.VirtualAddress; }
+ uint64_t getFileOff() { return Header.PointerToRawData; }
+ void writeHeaderTo(uint8_t *Buf);
+
+ // Returns the size of this section in an executable memory image.
+ // This may be smaller than the raw size (the raw size is multiple
+ // of disk sector size, so there may be padding at end), or may be
+ // larger (if that's the case, the loader reserves spaces after end
+ // of raw data).
+ uint64_t getVirtualSize() { return Header.VirtualSize; }
+
+ // Returns the size of the section in the output file.
+ uint64_t getRawSize() { return Header.SizeOfRawData; }
+
+ // Set offset into the string table storing this section name.
+ // Used only when the name is longer than 8 bytes.
+ void setStringTableOff(uint32_t V) { StringTableOff = V; }
+
+ // N.B. The section index is one based.
+ uint32_t SectionIndex = 0;
+
+private:
+ StringRef Name;
+ coff_section Header;
+ uint32_t StringTableOff = 0;
+ std::vector<Chunk *> Chunks;
+};
+
+void OutputSection::setRVA(uint64_t RVA) {
+ Header.VirtualAddress = RVA;
+ for (Chunk *C : Chunks)
+ C->setRVA(C->getRVA() + RVA);
+}
+
+void OutputSection::setFileOffset(uint64_t Off) {
+ // If a section has no actual data (i.e. BSS section), we want to
+ // set 0 to its PointerToRawData. Otherwise the output is rejected
+ // by the loader.
+ if (Header.SizeOfRawData == 0)
+ return;
+ Header.PointerToRawData = Off;
+}
+
+void OutputSection::addChunk(Chunk *C) {
+ Chunks.push_back(C);
+ C->setOutputSection(this);
+ uint64_t Off = Header.VirtualSize;
+ Off = RoundUpToAlignment(Off, C->getAlign());
+ C->setRVA(Off);
+ C->setOutputSectionOff(Off);
+ Off += C->getSize();
+ Header.VirtualSize = Off;
+ if (C->hasData())
+ Header.SizeOfRawData = RoundUpToAlignment(Off, SectorSize);
+}
+
+void OutputSection::addPermissions(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);
+ *Hdr = Header;
+ if (StringTableOff) {
+ // If name is too long, write offset into the string table as a name.
+ sprintf(Hdr->Name, "/%d", StringTableOff);
+ } else {
+ assert(!Config->Debug || Name.size() <= COFF::NameSize);
+ strncpy(Hdr->Name, Name.data(),
+ std::min(Name.size(), (size_t)COFF::NameSize));
+ }
+}
+
+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");
+}
+
+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");
+}
+
+bool Defined::isExecutable() {
+ const auto X = IMAGE_SCN_MEM_EXECUTE;
+ if (auto *D = dyn_cast<DefinedRegular>(this))
+ return D->getChunk()->getOutputSection()->getPermissions() & X;
+ return isa<DefinedImportThunk>(this);
+}
+
+} // namespace coff
+} // namespace lld
+
+// The main function of the writer.
+void Writer::run() {
+ createSections();
+ createMiscChunks();
+ createImportTables();
+ createExportTable();
+ if (Config->Relocatable)
+ createSection(".reloc");
+ assignAddresses();
+ removeEmptySections();
+ createSymbolAndStringTable();
+ openFile(Config->OutputFile);
+ if (Config->is64()) {
+ writeHeader<pe32plus_header>();
+ } else {
+ writeHeader<pe32_header>();
+ }
+ fixSafeSEHSymbols();
+ writeSections();
+ sortExceptionTable();
+ error(Buffer->commit(), "Failed to write the output file");
+}
+
+static StringRef getOutputSection(StringRef Name) {
+ StringRef S = Name.split('$').first;
+ auto It = Config->Merge.find(S);
+ if (It == Config->Merge.end())
+ return S;
+ return It->second;
+}
+
+// Create output section objects and add them to OutputSections.
+void Writer::createSections() {
+ // First, bin chunks by name.
+ std::map<StringRef, std::vector<Chunk *>> Map;
+ for (Chunk *C : Symtab->getChunks()) {
+ auto *SC = dyn_cast<SectionChunk>(C);
+ if (SC && !SC->isLive()) {
+ if (Config->Verbose)
+ SC->printDiscardedMessage();
+ continue;
+ }
+ Map[C->getSectionName()].push_back(C);
+ }
+
+ // Then create an OutputSection for each section.
+ // '$' and all following characters in input section names are
+ // discarded when determining output section. So, .text$foo
+ // contributes to .text, for example. See PE/COFF spec 3.2.
+ SmallDenseMap<StringRef, OutputSection *> Sections;
+ for (auto Pair : Map) {
+ StringRef Name = getOutputSection(Pair.first);
+ OutputSection *&Sec = Sections[Name];
+ if (!Sec) {
+ Sec = new (CAlloc.Allocate()) OutputSection(Name);
+ OutputSections.push_back(Sec);
+ }
+ std::vector<Chunk *> &Chunks = Pair.second;
+ for (Chunk *C : Chunks) {
+ Sec->addChunk(C);
+ Sec->addPermissions(C->getPermissions());
+ }
+ }
+}
+
+void Writer::createMiscChunks() {
+ // Create thunks for locally-dllimported symbols.
+ if (!Symtab->LocalImportChunks.empty()) {
+ OutputSection *Sec = createSection(".rdata");
+ for (Chunk *C : Symtab->LocalImportChunks)
+ Sec->addChunk(C);
+ }
+
+ // Create SEH table. x86-only.
+ if (Config->Machine != I386)
+ return;
+ std::set<Defined *> Handlers;
+ for (lld::coff::ObjectFile *File : Symtab->ObjectFiles) {
+ if (!File->SEHCompat)
+ return;
+ for (SymbolBody *B : File->SEHandlers)
+ Handlers.insert(cast<Defined>(B->repl()));
+ }
+ SEHTable.reset(new SEHTableChunk(Handlers));
+ createSection(".rdata")->addChunk(SEHTable.get());
+}
+
+// Create .idata section for the DLL-imported symbol table.
+// The format of this section is inherently Windows-specific.
+// IdataContents class abstracted away the details for us,
+// so we just let it create chunks and add them to the section.
+void Writer::createImportTables() {
+ if (Symtab->ImportFiles.empty())
+ return;
+
+ // Initialize DLLOrder so that import entries are ordered in
+ // the same order as in the command line. (That affects DLL
+ // initialization order, and this ordering is MSVC-compatible.)
+ for (ImportFile *File : Symtab->ImportFiles) {
+ std::string DLL = StringRef(File->DLLName).lower();
+ if (Config->DLLOrder.count(DLL) == 0)
+ Config->DLLOrder[DLL] = Config->DLLOrder.size();
+ }
+
+ OutputSection *Text = createSection(".text");
+ for (ImportFile *File : Symtab->ImportFiles) {
+ if (DefinedImportThunk *Thunk = File->ThunkSym)
+ Text->addChunk(Thunk->getChunk());
+ if (Config->DelayLoads.count(StringRef(File->DLLName).lower())) {
+ DelayIdata.add(File->ImpSym);
+ } else {
+ Idata.add(File->ImpSym);
+ }
+ }
+ if (!Idata.empty()) {
+ OutputSection *Sec = createSection(".idata");
+ for (Chunk *C : Idata.getChunks())
+ Sec->addChunk(C);
+ }
+ if (!DelayIdata.empty()) {
+ Defined *Helper = cast<Defined>(Config->DelayLoadHelper->repl());
+ DelayIdata.create(Helper);
+ OutputSection *Sec = createSection(".didat");
+ for (Chunk *C : DelayIdata.getChunks())
+ Sec->addChunk(C);
+ Sec = createSection(".data");
+ for (Chunk *C : DelayIdata.getDataChunks())
+ Sec->addChunk(C);
+ Sec = createSection(".text");
+ for (std::unique_ptr<Chunk> &C : DelayIdata.getCodeChunks())
+ Sec->addChunk(C.get());
+ }
+}
+
+void Writer::createExportTable() {
+ if (Config->Exports.empty())
+ return;
+ OutputSection *Sec = createSection(".edata");
+ for (std::unique_ptr<Chunk> &C : Edata.Chunks)
+ Sec->addChunk(C.get());
+}
+
+// The Windows loader doesn't seem to like empty sections,
+// so we remove them if any.
+void Writer::removeEmptySections() {
+ auto IsEmpty = [](OutputSection *S) { return S->getVirtualSize() == 0; };
+ OutputSections.erase(
+ std::remove_if(OutputSections.begin(), OutputSections.end(), IsEmpty),
+ OutputSections.end());
+ uint32_t Idx = 1;
+ for (OutputSection *Sec : OutputSections)
+ Sec->SectionIndex = Idx++;
+}
+
+size_t Writer::addEntryToStringTable(StringRef Str) {
+ assert(Str.size() > COFF::NameSize);
+ size_t OffsetOfEntry = Strtab.size() + 4; // +4 for the size field
+ Strtab.insert(Strtab.end(), Str.begin(), Str.end());
+ Strtab.push_back('\0');
+ return OffsetOfEntry;
+}
+
+Optional<coff_symbol16> Writer::createSymbol(Defined *Def) {
+ if (auto *D = dyn_cast<DefinedRegular>(Def))
+ if (!D->getChunk()->isLive())
+ return None;
+
+ coff_symbol16 Sym;
+ StringRef Name = Def->getName();
+ if (Name.size() > COFF::NameSize) {
+ Sym.Name.Offset.Zeroes = 0;
+ Sym.Name.Offset.Offset = addEntryToStringTable(Name);
+ } else {
+ memset(Sym.Name.ShortName, 0, COFF::NameSize);
+ memcpy(Sym.Name.ShortName, Name.data(), Name.size());
+ }
+
+ if (auto *D = dyn_cast<DefinedCOFF>(Def)) {
+ COFFSymbolRef Ref = D->getCOFFSymbol();
+ Sym.Type = Ref.getType();
+ Sym.StorageClass = Ref.getStorageClass();
+ } else {
+ Sym.Type = IMAGE_SYM_TYPE_NULL;
+ Sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
+ }
+ Sym.NumberOfAuxSymbols = 0;
+
+ switch (Def->kind()) {
+ case SymbolBody::DefinedAbsoluteKind:
+ case SymbolBody::DefinedRelativeKind:
+ Sym.Value = Def->getRVA();
+ Sym.SectionNumber = IMAGE_SYM_ABSOLUTE;
+ break;
+ default: {
+ uint64_t RVA = Def->getRVA();
+ OutputSection *Sec = nullptr;
+ for (OutputSection *S : OutputSections) {
+ if (S->getRVA() > RVA)
+ break;
+ Sec = S;
+ }
+ Sym.Value = RVA - Sec->getRVA();
+ Sym.SectionNumber = Sec->SectionIndex;
+ break;
+ }
+ }
+ return Sym;
+}
+
+void Writer::createSymbolAndStringTable() {
+ if (!Config->Debug || !Config->WriteSymtab)
+ return;
+
+ // Name field in the section table is 8 byte long. Longer names need
+ // to be written to the string table. First, construct string table.
+ for (OutputSection *Sec : OutputSections) {
+ StringRef Name = Sec->getName();
+ if (Name.size() <= COFF::NameSize)
+ continue;
+ Sec->setStringTableOff(addEntryToStringTable(Name));
+ }
+
+ for (lld::coff::ObjectFile *File : Symtab->ObjectFiles)
+ for (SymbolBody *B : File->getSymbols())
+ if (auto *D = dyn_cast<Defined>(B))
+ if (Optional<coff_symbol16> Sym = createSymbol(D))
+ OutputSymtab.push_back(*Sym);
+
+ for (ImportFile *File : Symtab->ImportFiles)
+ for (SymbolBody *B : File->getSymbols())
+ if (Optional<coff_symbol16> Sym = createSymbol(cast<Defined>(B)))
+ OutputSymtab.push_back(*Sym);
+
+ OutputSection *LastSection = OutputSections.back();
+ // We position the symbol table to be adjacent to the end of the last section.
+ uint64_t FileOff =
+ LastSection->getFileOff() +
+ RoundUpToAlignment(LastSection->getRawSize(), SectorSize);
+ if (!OutputSymtab.empty()) {
+ PointerToSymbolTable = FileOff;
+ FileOff += OutputSymtab.size() * sizeof(coff_symbol16);
+ }
+ if (!Strtab.empty())
+ FileOff += Strtab.size() + 4;
+ FileSize = RoundUpToAlignment(FileOff, SectorSize);
+}
+
+// Visits all sections to assign incremental, non-overlapping RVAs and
+// file offsets.
+void Writer::assignAddresses() {
+ SizeOfHeaders = DOSStubSize + sizeof(PEMagic) + sizeof(coff_file_header) +
+ sizeof(data_directory) * NumberfOfDataDirectory +
+ sizeof(coff_section) * OutputSections.size();
+ SizeOfHeaders +=
+ Config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header);
+ SizeOfHeaders = RoundUpToAlignment(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
+ // the loader cannot handle holes.
+ std::stable_partition(
+ OutputSections.begin(), OutputSections.end(), [](OutputSection *S) {
+ return (S->getPermissions() & IMAGE_SCN_MEM_DISCARDABLE) == 0;
+ });
+ for (OutputSection *Sec : OutputSections) {
+ if (Sec->getName() == ".reloc")
+ addBaserels(Sec);
+ Sec->setRVA(RVA);
+ Sec->setFileOffset(FileSize);
+ RVA += RoundUpToAlignment(Sec->getVirtualSize(), PageSize);
+ FileSize += RoundUpToAlignment(Sec->getRawSize(), SectorSize);
+ }
+ SizeOfImage = SizeOfHeaders + RoundUpToAlignment(RVA - 0x1000, PageSize);
+}
+
+template <typename PEHeaderTy> void Writer::writeHeader() {
+ // Write DOS stub
+ uint8_t *Buf = Buffer->getBufferStart();
+ auto *DOS = reinterpret_cast<dos_header *>(Buf);
+ Buf += DOSStubSize;
+ DOS->Magic[0] = 'M';
+ DOS->Magic[1] = 'Z';
+ DOS->AddressOfRelocationTable = sizeof(dos_header);
+ DOS->AddressOfNewExeHeader = DOSStubSize;
+
+ // Write PE magic
+ memcpy(Buf, PEMagic, sizeof(PEMagic));
+ Buf += sizeof(PEMagic);
+
+ // Write COFF header
+ auto *COFF = reinterpret_cast<coff_file_header *>(Buf);
+ Buf += sizeof(*COFF);
+ COFF->Machine = Config->Machine;
+ COFF->NumberOfSections = OutputSections.size();
+ COFF->Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
+ if (Config->LargeAddressAware)
+ COFF->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
+ if (!Config->is64())
+ COFF->Characteristics |= IMAGE_FILE_32BIT_MACHINE;
+ if (Config->DLL)
+ COFF->Characteristics |= IMAGE_FILE_DLL;
+ if (!Config->Relocatable)
+ COFF->Characteristics |= IMAGE_FILE_RELOCS_STRIPPED;
+ COFF->SizeOfOptionalHeader =
+ sizeof(PEHeaderTy) + sizeof(data_directory) * NumberfOfDataDirectory;
+
+ // Write PE header
+ auto *PE = reinterpret_cast<PEHeaderTy *>(Buf);
+ Buf += sizeof(*PE);
+ PE->Magic = Config->is64() ? PE32Header::PE32_PLUS : PE32Header::PE32;
+ PE->ImageBase = Config->ImageBase;
+ PE->SectionAlignment = PageSize;
+ PE->FileAlignment = SectorSize;
+ PE->MajorImageVersion = Config->MajorImageVersion;
+ PE->MinorImageVersion = Config->MinorImageVersion;
+ PE->MajorOperatingSystemVersion = Config->MajorOSVersion;
+ PE->MinorOperatingSystemVersion = Config->MinorOSVersion;
+ PE->MajorSubsystemVersion = Config->MajorOSVersion;
+ PE->MinorSubsystemVersion = Config->MinorOSVersion;
+ PE->Subsystem = Config->Subsystem;
+ PE->SizeOfImage = SizeOfImage;
+ PE->SizeOfHeaders = SizeOfHeaders;
+ if (!Config->NoEntry) {
+ Defined *Entry = cast<Defined>(Config->Entry->repl());
+ PE->AddressOfEntryPoint = Entry->getRVA();
+ // Pointer to thumb code must have the LSB set, so adjust it.
+ if (Config->Machine == ARMNT)
+ PE->AddressOfEntryPoint |= 1;
+ }
+ PE->SizeOfStackReserve = Config->StackReserve;
+ PE->SizeOfStackCommit = Config->StackCommit;
+ PE->SizeOfHeapReserve = Config->HeapReserve;
+ PE->SizeOfHeapCommit = Config->HeapCommit;
+ if (Config->DynamicBase)
+ PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE;
+ if (Config->HighEntropyVA)
+ PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA;
+ if (!Config->AllowBind)
+ PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_BIND;
+ if (Config->NxCompat)
+ PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
+ if (!Config->AllowIsolation)
+ PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION;
+ if (Config->TerminalServerAware)
+ PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE;
+ PE->NumberOfRvaAndSize = NumberfOfDataDirectory;
+ if (OutputSection *Text = findSection(".text")) {
+ PE->BaseOfCode = Text->getRVA();
+ PE->SizeOfCode = Text->getRawSize();
+ }
+ PE->SizeOfInitializedData = getSizeOfInitializedData();
+
+ // Write data directory
+ auto *Dir = reinterpret_cast<data_directory *>(Buf);
+ Buf += sizeof(*Dir) * NumberfOfDataDirectory;
+ if (OutputSection *Sec = findSection(".edata")) {
+ Dir[EXPORT_TABLE].RelativeVirtualAddress = Sec->getRVA();
+ Dir[EXPORT_TABLE].Size = Sec->getVirtualSize();
+ }
+ if (!Idata.empty()) {
+ Dir[IMPORT_TABLE].RelativeVirtualAddress = Idata.getDirRVA();
+ Dir[IMPORT_TABLE].Size = Idata.getDirSize();
+ Dir[IAT].RelativeVirtualAddress = Idata.getIATRVA();
+ Dir[IAT].Size = Idata.getIATSize();
+ }
+ if (!DelayIdata.empty()) {
+ Dir[DELAY_IMPORT_DESCRIPTOR].RelativeVirtualAddress =
+ DelayIdata.getDirRVA();
+ Dir[DELAY_IMPORT_DESCRIPTOR].Size = DelayIdata.getDirSize();
+ }
+ if (OutputSection *Sec = findSection(".rsrc")) {
+ Dir[RESOURCE_TABLE].RelativeVirtualAddress = Sec->getRVA();
+ Dir[RESOURCE_TABLE].Size = Sec->getVirtualSize();
+ }
+ if (OutputSection *Sec = findSection(".reloc")) {
+ Dir[BASE_RELOCATION_TABLE].RelativeVirtualAddress = Sec->getRVA();
+ Dir[BASE_RELOCATION_TABLE].Size = Sec->getVirtualSize();
+ }
+ if (OutputSection *Sec = findSection(".pdata")) {
+ Dir[EXCEPTION_TABLE].RelativeVirtualAddress = Sec->getRVA();
+ Dir[EXCEPTION_TABLE].Size = Sec->getVirtualSize();
+ }
+ 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;
+ }
+ }
+ if (Symbol *Sym = Symtab->findUnderscore("_load_config_used")) {
+ if (Defined *B = dyn_cast<Defined>(Sym->Body)) {
+ Dir[LOAD_CONFIG_TABLE].RelativeVirtualAddress = B->getRVA();
+ Dir[LOAD_CONFIG_TABLE].Size = Config->is64() ? 112 : 64;
+ }
+ }
+
+ // Write section table
+ for (OutputSection *Sec : OutputSections) {
+ Sec->writeHeaderTo(Buf);
+ Buf += sizeof(coff_section);
+ }
+
+ if (OutputSymtab.empty())
+ return;
+
+ COFF->PointerToSymbolTable = PointerToSymbolTable;
+ uint32_t NumberOfSymbols = OutputSymtab.size();
+ COFF->NumberOfSymbols = NumberOfSymbols;
+ auto *SymbolTable = reinterpret_cast<coff_symbol16 *>(
+ Buffer->getBufferStart() + COFF->PointerToSymbolTable);
+ for (size_t I = 0; I != NumberOfSymbols; ++I)
+ SymbolTable[I] = OutputSymtab[I];
+ // Create the string table, it follows immediately after the symbol table.
+ // 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());
+}
+
+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);
+}
+
+void Writer::fixSafeSEHSymbols() {
+ if (!SEHTable)
+ return;
+ Config->SEHTable->setRVA(SEHTable->getRVA());
+ Config->SEHCount->setVA(SEHTable->getSize() / 4);
+}
+
+// Write section contents to a mmap'ed file.
+void Writer::writeSections() {
+ uint8_t *Buf = Buffer->getBufferStart();
+ for (OutputSection *Sec : OutputSections) {
+ uint8_t *SecBuf = Buf + Sec->getFileOff();
+ // Fill gaps between functions in .text with INT3 instructions
+ // instead of leaving as NUL bytes (which can be interpreted as
+ // ADD instructions).
+ if (Sec->getPermissions() & IMAGE_SCN_CNT_CODE)
+ memset(SecBuf, 0xCC, Sec->getRawSize());
+ parallel_for_each(Sec->getChunks().begin(), Sec->getChunks().end(),
+ [&](Chunk *C) { C->writeTo(SecBuf); });
+ }
+}
+
+// Sort .pdata section contents according to PE/COFF spec 5.5.
+void Writer::sortExceptionTable() {
+ OutputSection *Sec = findSection(".pdata");
+ if (!Sec)
+ return;
+ // We assume .pdata contains function table entries only.
+ uint8_t *Begin = Buffer->getBufferStart() + Sec->getFileOff();
+ uint8_t *End = Begin + Sec->getVirtualSize();
+ if (Config->Machine == AMD64) {
+ struct Entry { ulittle32_t Begin, End, Unwind; };
+ parallel_sort(
+ (Entry *)Begin, (Entry *)End,
+ [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; });
+ return;
+ }
+ if (Config->Machine == ARMNT) {
+ struct Entry { ulittle32_t Begin, Unwind; };
+ parallel_sort(
+ (Entry *)Begin, (Entry *)End,
+ [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; });
+ return;
+ }
+ errs() << "warning: don't know how to handle .pdata.\n";
+}
+
+OutputSection *Writer::findSection(StringRef Name) {
+ for (OutputSection *Sec : OutputSections)
+ if (Sec->getName() == Name)
+ return Sec;
+ return nullptr;
+}
+
+uint32_t Writer::getSizeOfInitializedData() {
+ uint32_t Res = 0;
+ for (OutputSection *S : OutputSections)
+ if (S->getPermissions() & IMAGE_SCN_CNT_INITIALIZED_DATA)
+ Res += S->getRawSize();
+ return Res;
+}
+
+// Returns an existing section or create a new one if not found.
+OutputSection *Writer::createSection(StringRef Name) {
+ if (auto *Sec = findSection(Name))
+ return Sec;
+ const auto DATA = IMAGE_SCN_CNT_INITIALIZED_DATA;
+ const auto BSS = IMAGE_SCN_CNT_UNINITIALIZED_DATA;
+ const auto CODE = IMAGE_SCN_CNT_CODE;
+ const auto DISCARDABLE = IMAGE_SCN_MEM_DISCARDABLE;
+ const auto R = IMAGE_SCN_MEM_READ;
+ const auto W = IMAGE_SCN_MEM_WRITE;
+ const auto X = IMAGE_SCN_MEM_EXECUTE;
+ uint32_t Perms = StringSwitch<uint32_t>(Name)
+ .Case(".bss", BSS | R | W)
+ .Case(".data", DATA | R | W)
+ .Case(".didat", DATA | R)
+ .Case(".edata", DATA | R)
+ .Case(".idata", DATA | R)
+ .Case(".rdata", DATA | R)
+ .Case(".reloc", DATA | DISCARDABLE | R)
+ .Case(".text", CODE | R | X)
+ .Default(0);
+ if (!Perms)
+ llvm_unreachable("unknown section name");
+ auto Sec = new (CAlloc.Allocate()) OutputSection(Name);
+ Sec->addPermissions(Perms);
+ OutputSections.push_back(Sec);
+ return Sec;
+}
+
+// Dest is .reloc section. Add contents to that section.
+void Writer::addBaserels(OutputSection *Dest) {
+ std::vector<Baserel> V;
+ for (OutputSection *Sec : OutputSections) {
+ if (Sec == Dest)
+ continue;
+ // Collect all locations for base relocations.
+ for (Chunk *C : Sec->getChunks())
+ C->getBaserels(&V);
+ // Add the addresses to .reloc section.
+ if (!V.empty())
+ addBaserelBlocks(Dest, V);
+ V.clear();
+ }
+}
+
+// Add addresses to .reloc section. Note that addresses are grouped by page.
+void Writer::addBaserelBlocks(OutputSection *Dest, std::vector<Baserel> &V) {
+ const uint32_t Mask = ~uint32_t(PageSize - 1);
+ uint32_t Page = V[0].RVA & Mask;
+ size_t I = 0, J = 1;
+ for (size_t E = V.size(); J < E; ++J) {
+ uint32_t P = V[J].RVA & Mask;
+ if (P == Page)
+ continue;
+ BaserelChunk *Buf = BAlloc.Allocate();
+ Dest->addChunk(new (Buf) BaserelChunk(Page, &V[I], &V[0] + J));
+ I = J;
+ Page = P;
+ }
+ if (I == J)
+ return;
+ BaserelChunk *Buf = BAlloc.Allocate();
+ Dest->addChunk(new (Buf) BaserelChunk(Page, &V[I], &V[0] + J));
+}
diff --git a/COFF/Writer.h b/COFF/Writer.h
new file mode 100644
index 000000000000..0473315ae50a
--- /dev/null
+++ b/COFF/Writer.h
@@ -0,0 +1,26 @@
+//===- Writer.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_WRITER_H
+#define LLD_COFF_WRITER_H
+
+#include <vector>
+
+namespace lld {
+namespace coff {
+
+class Chunk;
+class OutputSection;
+
+void writeResult(SymbolTable *T);
+
+}
+}
+
+#endif
diff --git a/ELF/CMakeLists.txt b/ELF/CMakeLists.txt
new file mode 100644
index 000000000000..763275e30caa
--- /dev/null
+++ b/ELF/CMakeLists.txt
@@ -0,0 +1,26 @@
+set(LLVM_TARGET_DEFINITIONS Options.td)
+tablegen(LLVM Options.inc -gen-opt-parser-defs)
+add_public_tablegen_target(ELFOptionsTableGen)
+
+add_llvm_library(lldELF2
+ Driver.cpp
+ DriverUtils.cpp
+ Error.cpp
+ InputFiles.cpp
+ InputSection.cpp
+ LinkerScript.cpp
+ MarkLive.cpp
+ OutputSections.cpp
+ SymbolTable.cpp
+ Symbols.cpp
+ Target.cpp
+ Writer.cpp
+
+ LINK_COMPONENTS
+ Object
+ Option
+ MC
+ Support
+ )
+
+add_dependencies(lldELF2 ELFOptionsTableGen)
diff --git a/ELF/Config.h b/ELF/Config.h
new file mode 100644
index 000000000000..7b820f18b8c7
--- /dev/null
+++ b/ELF/Config.h
@@ -0,0 +1,84 @@
+//===- Config.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_CONFIG_H
+#define LLD_ELF_CONFIG_H
+
+#include "llvm/ADT/MapVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/ELF.h"
+
+#include <vector>
+
+namespace lld {
+namespace elf2 {
+
+class InputFile;
+class SymbolBody;
+
+enum ELFKind {
+ ELFNoneKind,
+ ELF32LEKind,
+ ELF32BEKind,
+ ELF64LEKind,
+ ELF64BEKind
+};
+
+struct Configuration {
+ SymbolBody *EntrySym = nullptr;
+ SymbolBody *MipsGpDisp = nullptr;
+ InputFile *FirstElf = nullptr;
+ llvm::StringRef DynamicLinker;
+ llvm::StringRef Entry;
+ llvm::StringRef Emulation;
+ llvm::StringRef Fini;
+ llvm::StringRef Init;
+ llvm::StringRef OutputFile;
+ llvm::StringRef SoName;
+ llvm::StringRef Sysroot;
+ std::string RPath;
+ llvm::MapVector<llvm::StringRef, std::vector<llvm::StringRef>> OutputSections;
+ std::vector<llvm::StringRef> SearchPaths;
+ std::vector<llvm::StringRef> Undefined;
+ bool AllowMultipleDefinition;
+ bool AsNeeded = false;
+ bool Bsymbolic;
+ bool DiscardAll;
+ bool DiscardLocals;
+ bool DiscardNone;
+ bool EnableNewDtags;
+ bool ExportDynamic;
+ bool GcSections;
+ bool GnuHash = false;
+ bool Mips64EL = false;
+ bool NoInhibitExec;
+ bool NoUndefined;
+ bool PrintGcSections;
+ bool Shared;
+ bool Static = false;
+ bool StripAll;
+ bool SysvHash = true;
+ bool Verbose;
+ bool ZExecStack;
+ bool ZNodelete;
+ bool ZNow;
+ bool ZOrigin;
+ bool ZRelro;
+ ELFKind EKind = ELFNoneKind;
+ uint16_t EMachine = llvm::ELF::EM_NONE;
+ uint64_t EntryAddr = -1;
+ unsigned Optimize = 0;
+};
+
+extern Configuration *Config;
+
+} // namespace elf2
+} // namespace lld
+
+#endif
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp
new file mode 100644
index 000000000000..6d881373b303
--- /dev/null
+++ b/ELF/Driver.cpp
@@ -0,0 +1,299 @@
+//===- Driver.cpp ---------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Driver.h"
+#include "Config.h"
+#include "Error.h"
+#include "InputFiles.h"
+#include "SymbolTable.h"
+#include "Target.h"
+#include "Writer.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/Support/raw_ostream.h"
+#include <utility>
+
+using namespace llvm;
+using namespace llvm::ELF;
+using namespace llvm::object;
+
+using namespace lld;
+using namespace lld::elf2;
+
+Configuration *lld::elf2::Config;
+LinkerDriver *lld::elf2::Driver;
+
+void lld::elf2::link(ArrayRef<const char *> Args) {
+ Configuration C;
+ LinkerDriver D;
+ Config = &C;
+ Driver = &D;
+ Driver->main(Args.slice(1));
+}
+
+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")
+ return {ELF32BEKind, EM_PPC};
+ if (S == "elf64ppc")
+ 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);
+}
+
+// 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;
+ 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
+
+ switch (identify_magic(MBRef.getBuffer())) {
+ case file_magic::unknown:
+ readLinkerScript(&Alloc, MBRef);
+ return;
+ case file_magic::archive:
+ if (WholeArchive) {
+ auto File = make_unique<ArchiveFile>(MBRef);
+ for (MemoryBufferRef &MB : File->getMembers())
+ Files.push_back(createELFFile<ObjectFile>(MB));
+ OwningArchives.emplace_back(std::move(File));
+ return;
+ }
+ Files.push_back(make_unique<ArchiveFile>(MBRef));
+ return;
+ case file_magic::elf_shared_object:
+ Files.push_back(createELFFile<SharedFile>(MBRef));
+ return;
+ default:
+ Files.push_back(createELFFile<ObjectFile>(MBRef));
+ }
+}
+
+static StringRef
+getString(opt::InputArgList &Args, unsigned Key, StringRef Default = "") {
+ if (auto *Arg = Args.getLastArg(Key))
+ return Arg->getValue();
+ return Default;
+}
+
+static bool hasZOption(opt::InputArgList &Args, StringRef Key) {
+ for (auto *Arg : Args.filtered(OPT_z))
+ if (Key == Arg->getValue())
+ return true;
+ return false;
+}
+
+void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
+ initSymbols();
+
+ opt::InputArgList Args = parseArgs(&Alloc, ArgsArr);
+ createFiles(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.");
+
+ switch (Config->EKind) {
+ case ELF32LEKind:
+ link<ELF32LE>(Args);
+ return;
+ case ELF32BEKind:
+ link<ELF32BE>(Args);
+ return;
+ case ELF64LEKind:
+ link<ELF64LE>(Args);
+ return;
+ case ELF64BEKind:
+ link<ELF64BE>(Args);
+ return;
+ default:
+ error("-m or at least a .o file required");
+ }
+}
+
+void LinkerDriver::createFiles(opt::InputArgList &Args) {
+ for (auto *Arg : Args.filtered(OPT_L))
+ Config->SearchPaths.push_back(Arg->getValue());
+
+ std::vector<StringRef> RPaths;
+ for (auto *Arg : Args.filtered(OPT_rpath))
+ RPaths.push_back(Arg->getValue());
+ if (!RPaths.empty())
+ Config->RPath = llvm::join(RPaths.begin(), RPaths.end(), ":");
+
+ if (auto *Arg = Args.getLastArg(OPT_m)) {
+ StringRef S = Arg->getValue();
+ std::pair<ELFKind, uint16_t> P = parseEmulation(S);
+ Config->EKind = P.first;
+ Config->EMachine = P.second;
+ Config->Emulation = S;
+ }
+
+ Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition);
+ Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic);
+ Config->DiscardAll = Args.hasArg(OPT_discard_all);
+ Config->DiscardLocals = Args.hasArg(OPT_discard_locals);
+ Config->DiscardNone = Args.hasArg(OPT_discard_none);
+ Config->EnableNewDtags = !Args.hasArg(OPT_disable_new_dtags);
+ Config->ExportDynamic = Args.hasArg(OPT_export_dynamic);
+ Config->GcSections = Args.hasArg(OPT_gc_sections);
+ Config->NoInhibitExec = Args.hasArg(OPT_noinhibit_exec);
+ Config->NoUndefined = Args.hasArg(OPT_no_undefined);
+ Config->PrintGcSections = Args.hasArg(OPT_print_gc_sections);
+ Config->Shared = Args.hasArg(OPT_shared);
+ Config->StripAll = Args.hasArg(OPT_strip_all);
+ Config->Verbose = Args.hasArg(OPT_verbose);
+
+ 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->OutputFile = getString(Args, OPT_o);
+ Config->SoName = getString(Args, OPT_soname);
+ Config->Sysroot = getString(Args, OPT_sysroot);
+
+ 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 (auto *Arg = Args.getLastArg(OPT_hash_style)) {
+ StringRef S = Arg->getValue();
+ if (S == "gnu") {
+ Config->GnuHash = true;
+ Config->SysvHash = false;
+ } else if (S == "both") {
+ Config->GnuHash = true;
+ } else if (S != "sysv")
+ error("Unknown hash style: " + S);
+ }
+
+ for (auto *Arg : Args.filtered(OPT_undefined))
+ Config->Undefined.push_back(Arg->getValue());
+
+ for (auto *Arg : Args) {
+ switch (Arg->getOption().getID()) {
+ case OPT_l:
+ addFile(searchLibrary(Arg->getValue()));
+ break;
+ case OPT_INPUT:
+ case OPT_script:
+ addFile(Arg->getValue());
+ break;
+ case OPT_as_needed:
+ Config->AsNeeded = true;
+ break;
+ case OPT_no_as_needed:
+ Config->AsNeeded = false;
+ break;
+ case OPT_Bstatic:
+ Config->Static = true;
+ break;
+ case OPT_Bdynamic:
+ Config->Static = false;
+ break;
+ case OPT_whole_archive:
+ WholeArchive = true;
+ break;
+ case OPT_no_whole_archive:
+ WholeArchive = false;
+ break;
+ }
+ }
+
+ if (Files.empty())
+ error("no input files.");
+
+ if (Config->GnuHash && Config->EMachine == EM_MIPS)
+ error("The .gnu.hash section is not compatible with the MIPS target.");
+}
+
+template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
+ SymbolTable<ELFT> Symtab;
+ Target.reset(createTarget());
+
+ if (!Config->Shared) {
+ // Add entry symbol.
+ if (Config->Entry.empty())
+ 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_");
+ }
+
+ 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.
+ Config->MipsGpDisp = Symtab.addIgnored("_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);
+ }
+
+ for (std::unique_ptr<InputFile> &F : Files)
+ Symtab.addFile(std::move(F));
+
+ for (StringRef S : Config->Undefined)
+ Symtab.addUndefinedOpt(S);
+
+ if (Config->OutputFile.empty())
+ Config->OutputFile = "a.out";
+
+ // Write the result to the file.
+ Symtab.scanShlibUndefined();
+ if (Config->GcSections)
+ markLive<ELFT>(&Symtab);
+ writeResult<ELFT>(&Symtab);
+}
diff --git a/ELF/Driver.h b/ELF/Driver.h
new file mode 100644
index 000000000000..2641155104dc
--- /dev/null
+++ b/ELF/Driver.h
@@ -0,0 +1,67 @@
+//===- Driver.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_DRIVER_H
+#define LLD_ELF_DRIVER_H
+
+#include "SymbolTable.h"
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Option/ArgList.h"
+
+namespace lld {
+namespace elf2 {
+
+extern class LinkerDriver *Driver;
+
+// Entry point of the ELF linker.
+void link(ArrayRef<const char *> Args);
+
+class LinkerDriver {
+public:
+ void main(ArrayRef<const char *> Args);
+ void createFiles(llvm::opt::InputArgList &Args);
+ template <class ELFT> void link(llvm::opt::InputArgList &Args);
+
+ void addFile(StringRef Path);
+
+private:
+ template <template <class> class T>
+ std::unique_ptr<InputFile> createELFInputFile(MemoryBufferRef MB);
+
+ llvm::BumpPtrAllocator Alloc;
+ bool WholeArchive = false;
+ std::vector<std::unique_ptr<InputFile>> Files;
+ std::vector<std::unique_ptr<ArchiveFile>> OwningArchives;
+ std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;
+};
+
+// Parses command line options.
+llvm::opt::InputArgList parseArgs(llvm::BumpPtrAllocator *A,
+ ArrayRef<const char *> Args);
+
+// Create enum with OPT_xxx values for each option in Options.td
+enum {
+ OPT_INVALID = 0,
+#define OPTION(_1, _2, ID, _4, _5, _6, _7, _8, _9, _10, _11) OPT_##ID,
+#include "Options.inc"
+#undef OPTION
+};
+
+// Parses a linker script. Calling this function updates the Symtab and Config.
+void readLinkerScript(llvm::BumpPtrAllocator *A, MemoryBufferRef MB);
+
+std::string findFromSearchPaths(StringRef Path);
+std::string searchLibrary(StringRef Path);
+std::string buildSysrootedPath(llvm::StringRef Dir, llvm::StringRef File);
+
+} // namespace elf2
+} // namespace lld
+
+#endif
diff --git a/ELF/DriverUtils.cpp b/ELF/DriverUtils.cpp
new file mode 100644
index 000000000000..51b500bebf49
--- /dev/null
+++ b/ELF/DriverUtils.cpp
@@ -0,0 +1,120 @@
+//===- DriverUtils.cpp ----------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains utility functions for the driver. Because there
+// are so many small functions, we created this separate file to make
+// Driver.cpp less cluttered.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Driver.h"
+#include "Error.h"
+#include "llvm/ADT/STLExtras.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 lld;
+using namespace lld::elf2;
+
+// Create OptTable
+
+// Create prefix string literals used in Options.td
+#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
+#include "Options.inc"
+#undef PREFIX
+
+// Create table mapping all options defined in Options.td
+static const opt::OptTable::Info infoTable[] = {
+#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) {}
+};
+
+// Parses a given list of options.
+opt::InputArgList lld::elf2::parseArgs(llvm::BumpPtrAllocator *A,
+ ArrayRef<const char *> Argv) {
+ // Make InputArgList from string vectors.
+ ELFOptTable Table;
+ unsigned MissingIndex;
+ unsigned 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);
+
+ // Parse options and then do error checking.
+ opt::InputArgList Args = Table.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");
+
+ return Args;
+}
+
+std::string lld::elf2::findFromSearchPaths(StringRef Path) {
+ for (StringRef Dir : Config->SearchPaths) {
+ std::string FullPath = buildSysrootedPath(Dir, Path);
+ if (sys::fs::exists(FullPath))
+ return FullPath;
+ }
+ return "";
+}
+
+// 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 lld::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())
+ return S;
+ }
+ error("Unable to find library -l" + Path);
+}
+
+// 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 lld::elf2::buildSysrootedPath(StringRef Dir, StringRef File) {
+ SmallString<128> Path;
+ if (Dir.startswith("="))
+ sys::path::append(Path, Config->Sysroot, Dir.substr(1), File);
+ else
+ sys::path::append(Path, Dir, File);
+ return Path.str();
+}
diff --git a/ELF/Error.cpp b/ELF/Error.cpp
new file mode 100644
index 000000000000..e0701f7f4cc6
--- /dev/null
+++ b/ELF/Error.cpp
@@ -0,0 +1,38 @@
+//===- Error.cpp ----------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Error.h"
+
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/raw_ostream.h"
+
+namespace lld {
+namespace elf2 {
+
+void warning(const Twine &Msg) { llvm::errs() << Msg << "\n"; }
+
+void error(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 error(std::error_code EC) {
+ if (!EC)
+ return;
+ error(EC.message());
+}
+
+} // namespace elf2
+} // namespace lld
diff --git a/ELF/Error.h b/ELF/Error.h
new file mode 100644
index 000000000000..b1d2e7a8fc5b
--- /dev/null
+++ b/ELF/Error.h
@@ -0,0 +1,32 @@
+//===- Error.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_ERROR_H
+#define LLD_COFF_ERROR_H
+
+#include "lld/Core/LLVM.h"
+
+namespace lld {
+namespace elf2 {
+
+void warning(const Twine &Msg);
+
+LLVM_ATTRIBUTE_NORETURN 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
+} // namespace lld
+
+#endif
diff --git a/ELF/InputFiles.cpp b/ELF/InputFiles.cpp
new file mode 100644
index 000000000000..e0827a3ee43d
--- /dev/null
+++ b/ELF/InputFiles.cpp
@@ -0,0 +1,496 @@
+//===- InputFiles.cpp -----------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InputFiles.h"
+#include "InputSection.h"
+#include "Error.h"
+#include "Symbols.h"
+#include "llvm/ADT/STLExtras.h"
+
+using namespace llvm;
+using namespace llvm::ELF;
+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); }
+};
+}
+
+template <class ELFT>
+ELFFileBase<ELFT>::ELFFileBase(Kind K, MemoryBufferRef M)
+ : InputFile(K, M), ELFObj(MB.getBuffer(), ECRAII().getEC()) {}
+
+template <class ELFT>
+ELFKind ELFFileBase<ELFT>::getELFKind() {
+ using llvm::support::little;
+ if (ELFT::Is64Bits)
+ return ELFT::TargetEndianness == little ? ELF64LEKind : ELF64BEKind;
+ return ELFT::TargetEndianness == little ? ELF32LEKind : ELF32BEKind;
+}
+
+template <class ELFT>
+typename ELFFileBase<ELFT>::Elf_Sym_Range
+ELFFileBase<ELFT>::getSymbolsHelper(bool Local) {
+ 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);
+}
+
+template <class ELFT>
+uint32_t ELFFileBase<ELFT>::getSectionIndex(const Elf_Sym &Sym) const {
+ uint32_t I = Sym.st_shndx;
+ if (I == ELF::SHN_XINDEX)
+ return this->ELFObj.getExtendedSymbolTableIndex(&Sym, this->Symtab,
+ SymtabSHNDX);
+ if (I >= ELF::SHN_LORESERVE || I == ELF::SHN_ABS)
+ return 0;
+ return I;
+}
+
+template <class ELFT> void ELFFileBase<ELFT>::initStringTable() {
+ if (!Symtab)
+ return;
+ ErrorOr<StringRef> StringTableOrErr = ELFObj.getStringTableForSymtab(*Symtab);
+ error(StringTableOrErr.getError());
+ StringTable = *StringTableOrErr;
+}
+
+template <class ELFT>
+typename ELFFileBase<ELFT>::Elf_Sym_Range
+ELFFileBase<ELFT>::getNonLocalSymbols() {
+ return getSymbolsHelper(false);
+}
+
+template <class ELFT>
+ObjectFile<ELFT>::ObjectFile(MemoryBufferRef M)
+ : ELFFileBase<ELFT>(Base::ObjectKind, M) {}
+
+template <class ELFT>
+typename ObjectFile<ELFT>::Elf_Sym_Range ObjectFile<ELFT>::getLocalSymbols() {
+ return this->getSymbolsHelper(true);
+}
+
+template <class ELFT> uint32_t ObjectFile<ELFT>::getMipsGp0() const {
+ return MipsReginfo ? MipsReginfo->getGp0() : 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 elf2::ObjectFile<ELFT>::parse(DenseSet<StringRef> &Comdats) {
+ // Read section and symbol tables.
+ initializeSections(Comdats);
+ initializeSymbols();
+}
+
+// Sections with SHT_GROUP and comdat bits define comdat section groups.
+// 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) {
+ 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;
+}
+
+template <class ELFT>
+ArrayRef<typename ObjectFile<ELFT>::GroupEntryType>
+ObjectFile<ELFT>::getShtGroupEntries(const Elf_Shdr &Sec) {
+ const ELFFile<ELFT> &Obj = this->ELFObj;
+ ErrorOr<ArrayRef<GroupEntryType>> EntriesOrErr =
+ Obj.template getSectionContentsAsArray<GroupEntryType>(&Sec);
+ error(EntriesOrErr.getError());
+ ArrayRef<GroupEntryType> Entries = *EntriesOrErr;
+ if (Entries.empty() || Entries[0] != GRP_COMDAT)
+ error("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;
+ uintX_t Flags = Sec.sh_flags;
+ if (!(Flags & SHF_MERGE))
+ return false;
+ if (Flags & SHF_WRITE)
+ error("Writable SHF_MERGE sections are 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");
+
+ // Don't try to merge if the aligment is larger than the sh_entsize.
+ //
+ // 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
+ // 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;
+
+ return true;
+}
+
+template <class ELFT>
+void elf2::ObjectFile<ELFT>::initializeSections(DenseSet<StringRef> &Comdats) {
+ uint64_t Size = this->ELFObj.getNumSections();
+ Sections.resize(Size);
+ unsigned I = -1;
+ const ELFFile<ELFT> &Obj = this->ELFObj;
+ for (const Elf_Shdr &Sec : Obj.sections()) {
+ ++I;
+ if (Sections[I] == &InputSection<ELFT>::Discarded)
+ continue;
+
+ switch (Sec.sh_type) {
+ case SHT_GROUP:
+ Sections[I] = &InputSection<ELFT>::Discarded;
+ if (Comdats.insert(getShtGroupSignature(Sec)).second)
+ continue;
+ for (GroupEntryType E : getShtGroupEntries(Sec)) {
+ uint32_t SecIndex = E;
+ if (SecIndex >= Size)
+ error("Invalid section index in group");
+ 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;
+ 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)) {
+ S->RelocSections.push_back(&Sec);
+ } else if (auto *S = dyn_cast<EHInputSection<ELFT>>(RelocatedSection)) {
+ if (S->RelocSection)
+ error("Multiple relocation sections to .eh_frame are not supported");
+ S->RelocSection = &Sec;
+ } else {
+ error("Relocations pointing to SHF_MERGE are not supported");
+ }
+ break;
+ }
+ default:
+ Sections[I] = createInputSection(Sec);
+ }
+ }
+}
+
+template <class ELFT> InputSectionBase<ELFT> *
+elf2::ObjectFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
+ ErrorOr<StringRef> NameOrErr = this->ELFObj.getSectionName(&Sec);
+ error(NameOrErr);
+ StringRef Name = *NameOrErr;
+
+ // .note.GNU-stack is a marker section to control the presence of
+ // PT_GNU_STACK segment in outputs. Since the presence of the segment
+ // is controlled only by the command line option (-z execstack) in LLD,
+ // .note.GNU-stack is ignored.
+ 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 (this->Alloc) MipsReginfoInputSection<ELFT>(this, &Sec);
+ return MipsReginfo;
+ }
+
+ if (Name == ".eh_frame")
+ return new (this->EHAlloc.Allocate()) EHInputSection<ELFT>(this, &Sec);
+ if (shouldMerge<ELFT>(Sec))
+ return new (this->MAlloc.Allocate()) MergeInputSection<ELFT>(this, &Sec);
+ return new (this->Alloc) InputSection<ELFT>(this, &Sec);
+}
+
+template <class ELFT> void elf2::ObjectFile<ELFT>::initializeSymbols() {
+ this->initStringTable();
+ Elf_Sym_Range Syms = this->getNonLocalSymbols();
+ uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
+ this->SymbolBodies.reserve(NumSymbols);
+ for (const Elf_Sym &Sym : Syms)
+ this->SymbolBodies.push_back(createSymbolBody(this->StringTable, &Sym));
+}
+
+template <class ELFT>
+InputSectionBase<ELFT> *
+elf2::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];
+}
+
+template <class ELFT>
+SymbolBody *elf2::ObjectFile<ELFT>::createSymbolBody(StringRef StringTable,
+ const Elf_Sym *Sym) {
+ ErrorOr<StringRef> NameOrErr = Sym->getName(StringTable);
+ error(NameOrErr.getError());
+ StringRef Name = *NameOrErr;
+
+ switch (Sym->st_shndx) {
+ case SHN_UNDEF:
+ return new (this->Alloc) UndefinedElf<ELFT>(Name, *Sym);
+ case SHN_COMMON:
+ return new (this->Alloc) DefinedCommon(
+ Name, Sym->st_size, Sym->st_value,
+ Sym->getBinding() == llvm::ELF::STB_WEAK, Sym->getVisibility());
+ }
+
+ switch (Sym->getBinding()) {
+ default:
+ error("unexpected binding");
+ case STB_GLOBAL:
+ case STB_WEAK:
+ case STB_GNU_UNIQUE: {
+ InputSectionBase<ELFT> *Sec = getSection(*Sym);
+ if (Sec == &InputSection<ELFT>::Discarded)
+ return new (this->Alloc) UndefinedElf<ELFT>(Name, *Sym);
+ return new (this->Alloc) DefinedRegular<ELFT>(Name, *Sym, Sec);
+ }
+ }
+}
+
+static std::unique_ptr<Archive> openArchive(MemoryBufferRef MB) {
+ ErrorOr<std::unique_ptr<Archive>> ArchiveOrErr = Archive::create(MB);
+ error(ArchiveOrErr, "Failed to parse archive");
+ return std::move(*ArchiveOrErr);
+}
+
+void ArchiveFile::parse() {
+ File = openArchive(MB);
+
+ // Allocate a buffer for Lazy objects.
+ size_t NumSyms = File->getNumberOfSymbols();
+ LazySymbols.reserve(NumSyms);
+
+ // Read the symbol table to construct Lazy objects.
+ for (const Archive::Symbol &Sym : File->symbols())
+ LazySymbols.emplace_back(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;
+
+ 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;
+}
+
+std::vector<MemoryBufferRef> ArchiveFile::getMembers() {
+ File = openArchive(MB);
+
+ std::vector<MemoryBufferRef> Result;
+ for (auto &ChildOrErr : File->children()) {
+ error(ChildOrErr,
+ "Could not get the child of the archive " + File->getFileName());
+ const Archive::Child Child(*ChildOrErr);
+ ErrorOr<MemoryBufferRef> MbOrErr = Child.getMemoryBufferRef();
+ if (!MbOrErr)
+ error(MbOrErr, "Could not get the buffer for a child of the archive " +
+ File->getFileName());
+ Result.push_back(MbOrErr.get());
+ }
+ return Result;
+}
+
+template <class ELFT>
+SharedFile<ELFT>::SharedFile(MemoryBufferRef M)
+ : ELFFileBase<ELFT>(Base::SharedKind, M) {
+ AsNeeded = Config->AsNeeded;
+}
+
+template <class ELFT>
+const typename ELFFile<ELFT>::Elf_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;
+}
+
+template <class ELFT> void SharedFile<ELFT>::parseSoName() {
+ typedef typename ELFFile<ELFT>::Elf_Dyn Elf_Dyn;
+ typedef typename ELFFile<ELFT>::uintX_t uintX_t;
+ const Elf_Shdr *DynamicSec = nullptr;
+
+ const ELFFile<ELFT> Obj = this->ELFObj;
+ for (const Elf_Shdr &Sec : Obj.sections()) {
+ switch (Sec.sh_type) {
+ default:
+ continue;
+ case SHT_DYNSYM:
+ this->Symtab = &Sec;
+ break;
+ case SHT_DYNAMIC:
+ DynamicSec = &Sec;
+ break;
+ case SHT_SYMTAB_SHNDX: {
+ ErrorOr<ArrayRef<Elf_Word>> ErrorOrTable = Obj.getSHNDXTable(Sec);
+ error(ErrorOrTable);
+ this->SymtabSHNDX = *ErrorOrTable;
+ break;
+ }
+ }
+ }
+
+ this->initStringTable();
+ this->SoName = this->getName();
+
+ if (!DynamicSec)
+ return;
+ auto *Begin =
+ reinterpret_cast<const Elf_Dyn *>(Obj.base() + DynamicSec->sh_offset);
+ const Elf_Dyn *End = Begin + DynamicSec->sh_size / sizeof(Elf_Dyn);
+
+ for (const Elf_Dyn &Dyn : make_range(Begin, End)) {
+ if (Dyn.d_tag == DT_SONAME) {
+ uintX_t Val = Dyn.getVal();
+ if (Val >= this->StringTable.size())
+ error("Invalid DT_SONAME entry");
+ this->SoName = StringRef(this->StringTable.data() + Val);
+ return;
+ }
+ }
+}
+
+template <class ELFT> void SharedFile<ELFT>::parse() {
+ Elf_Sym_Range Syms = this->getNonLocalSymbols();
+ uint32_t NumSymbols = std::distance(Syms.begin(), Syms.end());
+ SymbolBodies.reserve(NumSymbols);
+ for (const Elf_Sym &Sym : Syms) {
+ ErrorOr<StringRef> NameOrErr = Sym.getName(this->StringTable);
+ error(NameOrErr.getError());
+ StringRef Name = *NameOrErr;
+
+ if (Sym.isUndefined())
+ Undefs.push_back(Name);
+ else
+ SymbolBodies.emplace_back(this, Name, Sym);
+ }
+}
+
+template <typename T>
+static std::unique_ptr<InputFile> createELFFileAux(MemoryBufferRef MB) {
+ std::unique_ptr<T> Ret = llvm::make_unique<T>(MB);
+
+ if (!Config->FirstElf)
+ Config->FirstElf = Ret.get();
+
+ if (Config->EKind == ELFNoneKind) {
+ Config->EKind = Ret->getELFKind();
+ Config->EMachine = Ret->getEMachine();
+ }
+
+ return std::move(Ret);
+}
+
+template <template <class> class T>
+std::unique_ptr<InputFile> lld::elf2::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());
+}
+
+template class elf2::ELFFileBase<ELF32LE>;
+template class elf2::ELFFileBase<ELF32BE>;
+template class elf2::ELFFileBase<ELF64LE>;
+template class elf2::ELFFileBase<ELF64BE>;
+
+template class elf2::ObjectFile<ELF32LE>;
+template class elf2::ObjectFile<ELF32BE>;
+template class elf2::ObjectFile<ELF64LE>;
+template class elf2::ObjectFile<ELF64BE>;
+
+template class elf2::SharedFile<ELF32LE>;
+template class elf2::SharedFile<ELF32BE>;
+template class elf2::SharedFile<ELF64LE>;
+template class elf2::SharedFile<ELF64BE>;
+
+template std::unique_ptr<InputFile>
+elf2::createELFFile<ObjectFile>(MemoryBufferRef);
+
+template std::unique_ptr<InputFile>
+elf2::createELFFile<SharedFile>(MemoryBufferRef);
diff --git a/ELF/InputFiles.h b/ELF/InputFiles.h
new file mode 100644
index 000000000000..4e529c558cf5
--- /dev/null
+++ b/ELF/InputFiles.h
@@ -0,0 +1,211 @@
+//===- InputFiles.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_INPUT_FILES_H
+#define LLD_ELF_INPUT_FILES_H
+
+#include "Config.h"
+#include "InputSection.h"
+#include "Error.h"
+#include "Symbols.h"
+
+#include "lld/Core/LLVM.h"
+#include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/ELF.h"
+
+namespace lld {
+namespace elf2 {
+
+using llvm::object::Archive;
+
+class InputFile;
+class Lazy;
+class SymbolBody;
+
+// The root class of input files.
+class InputFile {
+public:
+ enum Kind { ObjectKind, SharedKind, ArchiveKind };
+ Kind kind() const { return FileKind; }
+
+ StringRef getName() const { return MB.getBufferIdentifier(); }
+
+protected:
+ InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}
+ MemoryBufferRef MB;
+
+private:
+ const Kind FileKind;
+};
+
+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;
+
+ ELFFileBase(Kind K, MemoryBufferRef M);
+ static bool classof(const InputFile *F) {
+ Kind K = F->kind();
+ 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];
+ }
+
+ StringRef getStringTable() const { return StringTable; }
+
+ uint32_t getSectionIndex(const Elf_Sym &Sym) const;
+
+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;
+
+ typedef llvm::support::detail::packed_endian_specific_integral<
+ uint32_t, ELFT::TargetEndianness, 2> GroupEntryType;
+ StringRef getShtGroupSignature(const Elf_Shdr &Sec);
+ ArrayRef<GroupEntryType> getShtGroupEntries(const Elf_Shdr &Sec);
+
+public:
+ static bool classof(const InputFile *F) {
+ return F->kind() == Base::ObjectKind;
+ }
+
+ ArrayRef<SymbolBody *> getSymbols() { return this->SymbolBodies; }
+
+ explicit ObjectFile(MemoryBufferRef M);
+ void parse(llvm::DenseSet<StringRef> &Comdats);
+
+ 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 this->SymbolBodies[SymbolIndex - FirstNonLocal];
+ }
+
+ Elf_Sym_Range getLocalSymbols();
+ const Elf_Sym *getLocalSymbol(uintX_t SymIndex);
+
+ const Elf_Shdr *getSymbolTable() const { return this->Symtab; };
+
+ // Get MIPS GP0 value defined by this file. This value represents the gp value
+ // used to create the relocatable object and required to support
+ // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.
+ uint32_t getMipsGp0() const;
+
+private:
+ void initializeSections(llvm::DenseSet<StringRef> &Comdats);
+ void initializeSymbols();
+ InputSectionBase<ELFT> *createInputSection(const Elf_Shdr &Sec);
+
+ SymbolBody *createSymbolBody(StringRef StringTable, const Elf_Sym *Sym);
+
+ // List of all sections defined by this file.
+ std::vector<InputSectionBase<ELFT> *> Sections;
+
+ // List of all symbols referenced or defined by this file.
+ std::vector<SymbolBody *> SymbolBodies;
+
+ // MIPS .reginfo section defined by this file.
+ MipsReginfoInputSection<ELFT> *MipsReginfo = nullptr;
+
+ llvm::BumpPtrAllocator Alloc;
+ llvm::SpecificBumpPtrAllocator<MergeInputSection<ELFT>> MAlloc;
+ llvm::SpecificBumpPtrAllocator<EHInputSection<ELFT>> EHAlloc;
+};
+
+class ArchiveFile : public InputFile {
+public:
+ explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}
+ static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }
+ 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; }
+ std::vector<MemoryBufferRef> getMembers();
+
+private:
+ std::unique_ptr<Archive> File;
+ std::vector<Lazy> LazySymbols;
+ llvm::DenseSet<uint64_t> Seen;
+};
+
+// .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;
+
+ std::vector<SharedSymbol<ELFT>> SymbolBodies;
+ std::vector<StringRef> Undefs;
+ StringRef SoName;
+
+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; }
+
+ static bool classof(const InputFile *F) {
+ return F->kind() == Base::SharedKind;
+ }
+
+ explicit SharedFile(MemoryBufferRef M);
+
+ void parseSoName();
+ void parse();
+
+ // Used for --as-needed
+ bool AsNeeded = false;
+ bool IsUsed = false;
+ bool isNeeded() const { return !AsNeeded || IsUsed; }
+};
+
+template <template <class> class T>
+std::unique_ptr<InputFile> createELFFile(MemoryBufferRef MB);
+
+} // namespace elf2
+} // namespace lld
+
+#endif
diff --git a/ELF/InputSection.cpp b/ELF/InputSection.cpp
new file mode 100644
index 000000000000..2548200feb65
--- /dev/null
+++ b/ELF/InputSection.cpp
@@ -0,0 +1,399 @@
+//===- InputSection.cpp ---------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InputSection.h"
+#include "Config.h"
+#include "Error.h"
+#include "InputFiles.h"
+#include "OutputSections.h"
+#include "Target.h"
+
+using namespace llvm;
+using namespace llvm::ELF;
+using namespace llvm::object;
+
+using namespace lld;
+using namespace lld::elf2;
+
+template <class ELFT>
+InputSectionBase<ELFT>::InputSectionBase(ObjectFile<ELFT> *File,
+ const Elf_Shdr *Header,
+ Kind SectionKind)
+ : Header(Header), File(File), SectionKind(SectionKind) {}
+
+template <class ELFT> StringRef InputSectionBase<ELFT>::getSectionName() const {
+ ErrorOr<StringRef> Name = File->getObj().getSectionName(this->Header);
+ error(Name);
+ return *Name;
+}
+
+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;
+}
+
+template <class ELFT>
+typename ELFFile<ELFT>::uintX_t
+InputSectionBase<ELFT>::getOffset(uintX_t Offset) {
+ switch (SectionKind) {
+ case Regular:
+ return cast<InputSection<ELFT>>(this)->OutSecOff + Offset;
+ case EHFrame:
+ return cast<EHInputSection<ELFT>>(this)->getOffset(Offset);
+ case Merge:
+ return cast<MergeInputSection<ELFT>>(this)->getOffset(Offset);
+ case MipsReginfo:
+ return cast<MipsReginfoInputSection<ELFT>>(this)->getOffset(Offset);
+ }
+ 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);
+}
+
+// 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;
+}
+
+template <class ELFT>
+InputSectionBase<ELFT> *
+InputSectionBase<ELFT>::getRelocTarget(const Elf_Rela &Rel) {
+ return getRelocTarget(reinterpret_cast<const Elf_Rel &>(Rel));
+}
+
+template <class ELFT>
+InputSection<ELFT>::InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header)
+ : InputSectionBase<ELFT>(F, Header, Base::Regular) {}
+
+template <class ELFT>
+bool InputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
+ return S->SectionKind == Base::Regular;
+}
+
+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;
+}
+
+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;
+}
+
+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;
+
+ uint8_t *BufLoc = Buf + Offset;
+ uintX_t AddrLoc = OutSec->getVA() + Offset;
+ auto NextRelocs = llvm::make_range(&RI, Rels.end());
+
+ if (Target->isTlsLocalDynamicReloc(Type) &&
+ !Target->isTlsOptimized(Type, nullptr)) {
+ Target->relocateOne(BufLoc, BufEnd, Type, AddrLoc,
+ Out<ELFT>::Got->getLocalTlsIndexVA() +
+ getAddend<ELFT>(RI));
+ continue;
+ }
+
+ 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;
+ }
+
+ // 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;
+ }
+
+ 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 SymVA = getSymVA<ELFT>(*Body);
+ if (Target->relocNeedsPlt(Type, *Body)) {
+ SymVA = Out<ELFT>::Plt->getEntryAddr(*Body);
+ Type = Target->getPltRefReloc(Type);
+ } 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) ||
+ Target->isSizeDynReloc(Type, *Body)) {
+ 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;
+ }
+ 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;
+ // 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));
+ }
+}
+
+template <class ELFT>
+SplitInputSection<ELFT>::SplitInputSection(
+ 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,
+ 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.
+ this->Live = true;
+}
+
+template <class ELFT>
+bool EHInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
+ return S->SectionKind == InputSectionBase<ELFT>::EHFrame;
+}
+
+template <class ELFT>
+typename EHInputSection<ELFT>::uintX_t
+EHInputSection<ELFT>::getOffset(uintX_t Offset) {
+ // 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))
+ return -1; // Not in the output
+
+ uintX_t Addend = Offset - I->first;
+ return Base + Addend;
+}
+
+template <class ELFT>
+MergeInputSection<ELFT>::MergeInputSection(ObjectFile<ELFT> *F,
+ const Elf_Shdr *Header)
+ : SplitInputSection<ELFT>(F, Header, InputSectionBase<ELFT>::Merge) {}
+
+template <class ELFT>
+bool MergeInputSection<ELFT>::classof(const InputSectionBase<ELFT> *S) {
+ return S->SectionKind == InputSectionBase<ELFT>::Merge;
+}
+
+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) {
+ 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");
+
+ // 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;
+ --I;
+ return std::make_pair(&*I, End);
+}
+
+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;
+}
+
+template <class ELFT>
+MipsReginfoInputSection<ELFT>::MipsReginfoInputSection(ObjectFile<ELFT> *F,
+ const Elf_Shdr *Header)
+ : InputSectionBase<ELFT>(F, Header, InputSectionBase<ELFT>::MipsReginfo) {}
+
+template <class ELFT>
+uint32_t MipsReginfoInputSection<ELFT>::getGeneralMask() const {
+ ArrayRef<uint8_t> D = this->getSectionData();
+ if (D.size() != sizeof(Elf_Mips_RegInfo))
+ error("Invalid size of .reginfo section");
+ return reinterpret_cast<const Elf_Mips_RegInfo *>(D.data())->ri_gprmask;
+}
+
+template <class ELFT> uint32_t MipsReginfoInputSection<ELFT>::getGp0() const {
+ ArrayRef<uint8_t> D = this->getSectionData();
+ if (D.size() != sizeof(Elf_Mips_RegInfo))
+ error("Invalid size of .reginfo section");
+ return reinterpret_cast<const Elf_Mips_RegInfo *>(D.data())->ri_gp_value;
+}
+
+template <class ELFT>
+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>;
+}
+}
diff --git a/ELF/InputSection.h b/ELF/InputSection.h
new file mode 100644
index 000000000000..d4dc9864ae91
--- /dev/null
+++ b/ELF/InputSection.h
@@ -0,0 +1,187 @@
+//===- InputSection.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_INPUT_SECTION_H
+#define LLD_ELF_INPUT_SECTION_H
+
+#include "Config.h"
+#include "lld/Core/LLVM.h"
+#include "llvm/Object/ELF.h"
+
+namespace lld {
+namespace elf2 {
+
+template <class ELFT> class ObjectFile;
+template <class ELFT> class OutputSection;
+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;
+ const Elf_Shdr *Header;
+
+ // The file this section is from.
+ ObjectFile<ELFT> *File;
+
+public:
+ enum Kind { Regular, EHFrame, Merge, MipsReginfo };
+ Kind SectionKind;
+
+ InputSectionBase(ObjectFile<ELFT> *File, const Elf_Shdr *Header,
+ Kind SectionKind);
+ OutputSectionBase<ELFT> *OutSec = nullptr;
+
+ // Used for garbage collection.
+ // Live bit makes sense only when Config->GcSections is true.
+ bool isLive() const { return !Config->GcSections || Live; }
+ bool Live = false;
+
+ // Returns the size of this section (even if this is a common or BSS.)
+ size_t getSize() const { return Header->sh_size; }
+
+ 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);
+
+ // Translate an offset in the input section to an offset in the output
+ // section.
+ uintX_t getOffset(uintX_t Offset);
+
+ 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);
+
+ template <bool isRela>
+ using RelIteratorRange =
+ llvm::iterator_range<const llvm::object::Elf_Rel_Impl<ELFT, isRela> *>;
+
+ template <bool isRela>
+ void relocate(uint8_t *Buf, uint8_t *BufEnd, RelIteratorRange<isRela> Rels);
+
+private:
+ template <bool isRela>
+ uint8_t *findMipsPairedReloc(uint8_t *Buf, uint32_t SymIndex, uint32_t Type,
+ RelIteratorRange<isRela> Rels);
+};
+
+template <class ELFT>
+InputSectionBase<ELFT>
+ InputSectionBase<ELFT>::Discarded(nullptr, nullptr,
+ InputSectionBase<ELFT>::Regular);
+
+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;
+
+public:
+ SplitInputSection(ObjectFile<ELFT> *File, const Elf_Shdr *Header,
+ typename InputSectionBase<ELFT>::Kind SectionKind);
+ std::vector<std::pair<uintX_t, uintX_t>> Offsets;
+ std::pair<std::pair<uintX_t, uintX_t> *, uintX_t>
+ getRangeAndSize(uintX_t Offset);
+};
+
+// 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;
+
+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);
+};
+
+// This corresponds to a .eh_frame section of an input file.
+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);
+ 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);
+
+ // Relocation section that refer to this one.
+ const Elf_Shdr *RelocSection = nullptr;
+};
+
+// This corresponds to a non SHF_MERGE section of an input file.
+template <class ELFT> class InputSection : public InputSectionBase<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;
+
+public:
+ InputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header);
+
+ // Write this section to a mmap'ed file, assuming Buf is pointing to
+ // beginning of the output section.
+ void writeTo(uint8_t *Buf);
+
+ // Relocation sections that refer to this one.
+ SmallVector<const Elf_Shdr *, 1> 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);
+};
+
+// MIPS .reginfo section provides information on the registers used by the code
+// in the object file. Linker should collect this information and write a single
+// .reginfo section in the output file. The output section contains a union of
+// used registers masks taken from input .reginfo sections and final value
+// of the `_gp` symbol. For details: Chapter 4 / "Register Information" at
+// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+template <class ELFT>
+class MipsReginfoInputSection : public InputSectionBase<ELFT> {
+ typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
+
+public:
+ MipsReginfoInputSection(ObjectFile<ELFT> *F, const Elf_Shdr *Header);
+
+ uint32_t getGeneralMask() const;
+ uint32_t getGp0() const;
+
+ static bool classof(const InputSectionBase<ELFT> *S);
+};
+
+} // namespace elf2
+} // namespace lld
+
+#endif
diff --git a/ELF/LinkerScript.cpp b/ELF/LinkerScript.cpp
new file mode 100644
index 000000000000..883b623f9e2c
--- /dev/null
+++ b/ELF/LinkerScript.cpp
@@ -0,0 +1,318 @@
+//===- LinkerScript.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 "Config.h"
+#include "Driver.h"
+#include "SymbolTable.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 lld;
+using namespace lld::elf2;
+
+namespace {
+class LinkerScript {
+public:
+ LinkerScript(BumpPtrAllocator *A, StringRef S, bool B)
+ : Saver(*A), Tokens(tokenize(S)), IsUnderSysroot(B) {}
+ void 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);
+
+ void addFile(StringRef Path);
+
+ void readAsNeeded();
+ void readEntry();
+ void readExtern();
+ void readGroup();
+ void readInclude();
+ void readOutput();
+ void readOutputArch();
+ void readOutputFormat();
+ void readSearchDir();
+ void readSections();
+
+ void readOutputSectionDescription();
+
+ StringSaver Saver;
+ std::vector<StringRef> Tokens;
+ size_t Pos = 0;
+ bool IsUnderSysroot;
+};
+}
+
+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);
+ }
+ }
+}
+
+// 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;
+ }
+
+ // 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 /**/-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);
+ continue;
+ }
+ size_t Size = S.size();
+ S = S.ltrim();
+ if (S.size() == Size)
+ return S;
+ }
+}
+
+StringRef LinkerScript::next() {
+ if (atEOF())
+ error("unexpected EOF");
+ return Tokens[Pos++];
+}
+
+bool LinkerScript::skip(StringRef Tok) {
+ if (atEOF())
+ error("unexpected EOF");
+ if (Tok != Tokens[Pos])
+ return false;
+ ++Pos;
+ return true;
+}
+
+void LinkerScript::expect(StringRef Expect) {
+ StringRef Tok = next();
+ if (Tok != Expect)
+ error(Expect + " expected, but got " + Tok);
+}
+
+void LinkerScript::addFile(StringRef S) {
+ if (IsUnderSysroot && S.startswith("/")) {
+ SmallString<128> Path;
+ (Config->Sysroot + S).toStringRef(Path);
+ if (sys::fs::exists(Path)) {
+ Driver->addFile(Saver.save(Path.str()));
+ return;
+ }
+ }
+
+ if (sys::path::is_absolute(S)) {
+ Driver->addFile(S);
+ } else if (S.startswith("=")) {
+ if (Config->Sysroot.empty())
+ Driver->addFile(S.substr(1));
+ else
+ Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1)));
+ } else if (S.startswith("-l")) {
+ Driver->addFile(searchLibrary(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));
+ }
+}
+
+void LinkerScript::readAsNeeded() {
+ expect("(");
+ bool Orig = Config->AsNeeded;
+ Config->AsNeeded = true;
+ for (;;) {
+ StringRef Tok = next();
+ if (Tok == ")")
+ break;
+ addFile(Tok);
+ }
+ Config->AsNeeded = Orig;
+}
+
+void LinkerScript::readEntry() {
+ // -e <symbol> takes predecence over ENTRY(<symbol>).
+ expect("(");
+ StringRef Tok = next();
+ if (Config->Entry.empty())
+ Config->Entry = Tok;
+ expect(")");
+}
+
+void LinkerScript::readExtern() {
+ expect("(");
+ for (;;) {
+ StringRef Tok = next();
+ if (Tok == ")")
+ return;
+ Config->Undefined.push_back(Tok);
+ }
+}
+
+void LinkerScript::readGroup() {
+ expect("(");
+ for (;;) {
+ StringRef Tok = next();
+ if (Tok == ")")
+ return;
+ if (Tok == "AS_NEEDED") {
+ readAsNeeded();
+ continue;
+ }
+ addFile(Tok);
+ }
+}
+
+void LinkerScript::readInclude() {
+ StringRef Tok = next();
+ auto MBOrErr = MemoryBuffer::getFile(Tok);
+ error(MBOrErr, "cannot open " + Tok);
+ 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() {
+ // -o <file> takes predecence over OUTPUT(<file>).
+ expect("(");
+ StringRef Tok = next();
+ if (Config->OutputFile.empty())
+ Config->OutputFile = Tok;
+ expect(")");
+}
+
+void LinkerScript::readOutputArch() {
+ // Error checking only for now.
+ expect("(");
+ next();
+ expect(")");
+}
+
+void LinkerScript::readOutputFormat() {
+ // Error checking only for now.
+ expect("(");
+ next();
+ StringRef Tok = next();
+ if (Tok == ")")
+ return;
+ if (Tok != ",")
+ error("unexpected token: " + Tok);
+ next();
+ expect(",");
+ next();
+ expect(")");
+}
+
+void LinkerScript::readSearchDir() {
+ expect("(");
+ Config->SearchPaths.push_back(next());
+ expect(")");
+}
+
+void LinkerScript::readSections() {
+ expect("{");
+ while (!skip("}"))
+ readOutputSectionDescription();
+}
+
+void LinkerScript::readOutputSectionDescription() {
+ StringRef Name = next();
+ std::vector<StringRef> &InputSections = Config->OutputSections[Name];
+
+ expect(":");
+ expect("{");
+ while (!skip("}")) {
+ next(); // Skip input file name.
+ expect("(");
+ while (!skip(")"))
+ InputSections.push_back(next());
+ }
+}
+
+static bool isUnderSysroot(StringRef Path) {
+ if (Config->Sysroot == "")
+ return false;
+ for (; !Path.empty(); Path = sys::path::parent_path(Path))
+ if (sys::fs::equivalent(Config->Sysroot, Path))
+ return true;
+ return false;
+}
+
+// Entry point. The other functions or classes are private to this file.
+void lld::elf2::readLinkerScript(BumpPtrAllocator *A, MemoryBufferRef MB) {
+ StringRef Path = MB.getBufferIdentifier();
+ LinkerScript(A, MB.getBuffer(), isUnderSysroot(Path)).run();
+}
diff --git a/ELF/MarkLive.cpp b/ELF/MarkLive.cpp
new file mode 100644
index 000000000000..1ad9b01af4e8
--- /dev/null
+++ b/ELF/MarkLive.cpp
@@ -0,0 +1,131 @@
+//===- MarkLive.cpp -------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements --gc-sections, which is a feature to remove unused
+// sections from output. Unused sections are sections that are not reachable
+// from known GC-root symbols or sections. Naturally the feature is
+// implemented as a mark-sweep garbage collector.
+//
+// Here's how it works. Each InputSectionBase has a "Live" bit. The bit is off
+// by default. Starting with GC-root symbols or sections, markLive function
+// defined in this file visits all reachable sections to set their Live
+// bits. Writer will then ignore sections whose Live bits are off, so that
+// such sections are removed from output.
+//
+//===----------------------------------------------------------------------===//
+
+#include "InputSection.h"
+#include "OutputSections.h"
+#include "SymbolTable.h"
+#include "Symbols.h"
+#include "Writer.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Object/ELF.h"
+#include <functional>
+#include <vector>
+
+using namespace llvm;
+using namespace llvm::ELF;
+using namespace llvm::object;
+
+using namespace lld;
+using namespace lld::elf2;
+
+// Calls Fn for each section that Sec refers to.
+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);
+ }
+ }
+}
+
+// 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) {
+ switch (Sec->getSectionHdr()->sh_type) {
+ case SHT_FINI_ARRAY:
+ case SHT_INIT_ARRAY:
+ case SHT_NOTE:
+ case SHT_PREINIT_ARRAY:
+ return true;
+ default:
+ StringRef S = Sec->getSectionName();
+ return S.startswith(".ctors") || S.startswith(".dtors") ||
+ S.startswith(".init") || S.startswith(".fini") ||
+ S.startswith(".jcr");
+ }
+}
+
+// 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 lld::elf2::markLive(SymbolTable<ELFT> *Symtab) {
+ SmallVector<InputSection<ELFT> *, 256> Q;
+
+ auto Enqueue = [&](InputSectionBase<ELFT> *Sec) {
+ if (!Sec || Sec->Live)
+ return;
+ Sec->Live = true;
+ if (InputSection<ELFT> *S = dyn_cast<InputSection<ELFT>>(Sec))
+ Q.push_back(S);
+ };
+
+ auto MarkSymbol = [&](SymbolBody *Sym) {
+ if (Sym)
+ if (auto *D = dyn_cast<DefinedRegular<ELFT>>(Sym->repl()))
+ Enqueue(D->Section);
+ };
+
+ // Add GC root symbols.
+ MarkSymbol(Config->EntrySym);
+ MarkSymbol(Symtab->find(Config->Init));
+ MarkSymbol(Symtab->find(Config->Fini));
+ for (StringRef S : Config->Undefined)
+ MarkSymbol(Symtab->find(S));
+
+ // Preserve externally-visible symbols if the symbols defined by this
+ // file could override 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);
+ }
+ }
+
+ // Preserve special sections.
+ for (const std::unique_ptr<ObjectFile<ELFT>> &F : Symtab->getObjectFiles())
+ for (InputSectionBase<ELFT> *Sec : F->getSections())
+ if (Sec && Sec != &InputSection<ELFT>::Discarded)
+ if (isReserved(Sec))
+ Enqueue(Sec);
+
+ // Mark all reachable sections.
+ while (!Q.empty())
+ forEachSuccessor<ELFT>(Q.pop_back_val(), Enqueue);
+}
+
+template void lld::elf2::markLive<ELF32LE>(SymbolTable<ELF32LE> *);
+template void lld::elf2::markLive<ELF32BE>(SymbolTable<ELF32BE> *);
+template void lld::elf2::markLive<ELF64LE>(SymbolTable<ELF64LE> *);
+template void lld::elf2::markLive<ELF64BE>(SymbolTable<ELF64BE> *);
diff --git a/ELF/Options.td b/ELF/Options.td
new file mode 100644
index 000000000000..622cbb93bf11
--- /dev/null
+++ b/ELF/Options.td
@@ -0,0 +1,161 @@
+include "llvm/Option/OptParser.td"
+
+def Bsymbolic: Flag<["-"], "Bsymbolic">,
+ HelpText<"Bind defined symbols locally">;
+
+def Bdynamic: Flag<["-"], "Bdynamic">,
+ HelpText<"Link against shared libraries">;
+
+def Bstatic: Flag<["-"], "Bstatic">,
+ HelpText<"Do not link against shared libraries">;
+
+def L : JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">,
+ HelpText<"Directory to search for libraries">;
+
+def O : Joined<["-"], "O">, HelpText<"Optimize">;
+
+def allow_multiple_definition: Flag<["--"], "allow-multiple-definition">,
+ HelpText<"Allow multiple definitions">;
+
+def allow_shlib_undefined : Flag<["--", "-"], "allow-shlib-undefined">;
+
+def as_needed : Flag<["--"], "as-needed">;
+
+def disable_new_dtags : Flag<["--"], "disable-new-dtags">,
+ HelpText<"Disable new dynamic tags">;
+
+def discard_all : Flag<["-"], "discard-all">,
+ HelpText<"Delete all local symbols">;
+
+def discard_locals : Flag<["-"], "discard-locals">,
+ HelpText<"Delete temporary local symbols">;
+
+def discard_none : Flag<["-"], "discard-none">,
+ HelpText<"Keep all symbols in the symbol table">;
+
+def dynamic_linker : Separate<["--", "-"], "dynamic-linker">,
+ HelpText<"Which dynamic linker to use">;
+
+def enable_new_dtags : Flag<["--"], "enable-new-dtags">,
+ HelpText<"Enable new dynamic tags">;
+
+def entry : Separate<["--", "-"], "entry">, MetaVarName<"<entry>">,
+ HelpText<"Name of entry point symbol">;
+
+def export_dynamic : Flag<["--", "-"], "export-dynamic">,
+ HelpText<"Put symbols in the dynamic symbol table">;
+
+def fini : Separate<["-"], "fini">, MetaVarName<"<symbol>">,
+ HelpText<"Specify a finalizer function">;
+
+def hash_style : Separate<["--", "-"], "hash-style">,
+ HelpText<"Specify hash style (sysv, gnu or both)">;
+
+def gc_sections : Flag<["--"], "gc-sections">,
+ HelpText<"Enable garbage collection of unused sections">;
+
+def init : Separate<["-"], "init">, MetaVarName<"<symbol>">,
+ HelpText<"Specify an initializer function">;
+
+def l : JoinedOrSeparate<["-"], "l">, MetaVarName<"<libName>">,
+ HelpText<"Root name of library to use">;
+
+def m : JoinedOrSeparate<["-"], "m">,
+ HelpText<"Set target emulation">;
+
+def no_allow_shlib_undefined : Flag<["--"], "no-allow-shlib-undefined">;
+
+def no_as_needed : Flag<["--"], "no-as-needed">;
+
+def no_whole_archive : Flag<["--", "-"], "no-whole-archive">,
+ HelpText<"Restores the default behavior of loading archive members">;
+
+def noinhibit_exec : Flag<["--"], "noinhibit-exec">,
+ HelpText<"Retain the executable output file whenever it is still usable">;
+
+def no_undefined : Flag<["--"], "no-undefined">,
+ HelpText<"Report unresolved symbols even if the linker is creating a shared library">;
+
+def o : Separate<["-"], "o">, MetaVarName<"<path>">,
+ HelpText<"Path to file to write output">;
+
+def print_gc_sections: Flag<["--"], "print-gc-sections">,
+ HelpText<"List removed unused sections">;
+
+def rpath : Separate<["-"], "rpath">,
+ HelpText<"Add a DT_RUNPATH to the output">;
+
+def relocatable : Flag<["--"], "relocatable">;
+
+def script : Separate<["--"], "script">, HelpText<"Read linker script">;
+
+def shared : Flag<["-"], "shared">,
+ HelpText<"Build a shared object">;
+
+def soname : Joined<["-"], "soname=">,
+ HelpText<"Set DT_SONAME">;
+
+def strip_all : Flag<["--"], "strip-all">,
+ HelpText<"Strip all symbols">;
+
+def sysroot : Joined<["--"], "sysroot=">,
+ HelpText<"Set the system root">;
+
+def undefined : Joined<["--"], "undefined=">,
+ HelpText<"Force undefined symbol during linking">;
+
+def verbose : Flag<["--"], "verbose">;
+
+def whole_archive : Flag<["--", "-"], "whole-archive">,
+ HelpText<"Force load of all members in a static library">;
+
+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_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_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_strip_all: Flag<["-"], "s">, Alias<strip_all>;
+def alias_undefined_u : Separate<["-"], "u">, Alias<undefined>;
+
+// 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_paren: Flag<["-"], ")">;
+def start_group : Flag<["--"], "start-group">;
+def start_group_paren: Flag<["-"], "(">;
+
+// 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">;
+
+// Aliases for ignored options
+def alias_version_script_version_script : Joined<["--"], "version-script=">, Alias<version_script>;
diff --git a/ELF/OutputSections.cpp b/ELF/OutputSections.cpp
new file mode 100644
index 000000000000..8bdc2b0e5c4f
--- /dev/null
+++ b/ELF/OutputSections.cpp
@@ -0,0 +1,1534 @@
+//===- OutputSections.cpp -------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "OutputSections.h"
+#include "Config.h"
+#include "SymbolTable.h"
+#include "Target.h"
+#include "llvm/Support/MathExtras.h"
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::support::endian;
+using namespace llvm::ELF;
+
+using namespace lld;
+using namespace lld::elf2;
+
+bool lld::elf2::HasGotOffRel = false;
+
+template <class ELFT>
+OutputSectionBase<ELFT>::OutputSectionBase(StringRef Name, uint32_t sh_type,
+ uintX_t sh_flags)
+ : Name(Name) {
+ memset(&Header, 0, sizeof(Elf_Shdr));
+ Header.sh_type = sh_type;
+ Header.sh_flags = sh_flags;
+}
+
+template <class ELFT>
+GotPltSection<ELFT>::GotPltSection()
+ : OutputSectionBase<ELFT>(".got.plt", llvm::ELF::SHT_PROGBITS,
+ llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE) {
+ this->Header.sh_addralign = sizeof(uintX_t);
+}
+
+template <class ELFT> void GotPltSection<ELFT>::addEntry(SymbolBody *Sym) {
+ Sym->GotPltIndex = Target->getGotPltHeaderEntriesNum() + 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);
+}
+
+template <class ELFT> void GotPltSection<ELFT>::writeTo(uint8_t *Buf) {
+ Target->writeGotPltHeaderEntries(Buf);
+ Buf += Target->getGotPltHeaderEntriesNum() * sizeof(uintX_t);
+ for (const SymbolBody *B : Entries) {
+ Target->writeGotPltEntry(Buf, Out<ELFT>::Plt->getEntryAddr(*B));
+ Buf += sizeof(uintX_t);
+ }
+}
+
+template <class ELFT>
+GotSection<ELFT>::GotSection()
+ : OutputSectionBase<ELFT>(".got", llvm::ELF::SHT_PROGBITS,
+ llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE) {
+ if (Config->EMachine == EM_MIPS)
+ this->Header.sh_flags |= llvm::ELF::SHF_MIPS_GPREL;
+ this->Header.sh_addralign = sizeof(uintX_t);
+}
+
+template <class ELFT> void GotSection<ELFT>::addEntry(SymbolBody *Sym) {
+ Sym->GotIndex = Target->getGotHeaderEntriesNum() + Entries.size();
+ Entries.push_back(Sym);
+}
+
+template <class ELFT> bool GotSection<ELFT>::addDynTlsEntry(SymbolBody *Sym) {
+ if (Sym->hasGlobalDynIndex())
+ return false;
+ Sym->GlobalDynIndex = Target->getGotHeaderEntriesNum() + Entries.size();
+ // Global Dynamic TLS entries take two GOT slots.
+ Entries.push_back(Sym);
+ Entries.push_back(nullptr);
+ return true;
+}
+
+template <class ELFT> bool GotSection<ELFT>::addCurrentModuleTlsIndex() {
+ if (LocalTlsIndexOff != uint32_t(-1))
+ return false;
+ 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);
+}
+
+template <class ELFT>
+typename GotSection<ELFT>::uintX_t
+GotSection<ELFT>::getGlobalDynAddr(const SymbolBody &B) const {
+ return this->getVA() + B.GlobalDynIndex * sizeof(uintX_t);
+}
+
+template <class ELFT>
+const SymbolBody *GotSection<ELFT>::getMipsFirstGlobalEntry() const {
+ return Entries.empty() ? nullptr : Entries.front();
+}
+
+template <class ELFT>
+unsigned GotSection<ELFT>::getMipsLocalEntriesNum() const {
+ // TODO: Update when the suppoort of GOT entries for local symbols is added.
+ return Target->getGotHeaderEntriesNum();
+}
+
+template <class ELFT> void GotSection<ELFT>::finalize() {
+ this->Header.sh_size =
+ (Target->getGotHeaderEntriesNum() + Entries.size()) * sizeof(uintX_t);
+}
+
+template <class ELFT> void GotSection<ELFT>::writeTo(uint8_t *Buf) {
+ Target->writeGotHeaderEntries(Buf);
+ Buf += Target->getGotHeaderEntriesNum() * sizeof(uintX_t);
+ 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))
+ continue; // The dynamic linker will take care of it.
+ uintX_t VA = getSymVA<ELFT>(*B);
+ write<uintX_t, ELFT::TargetEndianness, sizeof(uintX_t)>(Entry, VA);
+ }
+}
+
+template <class ELFT>
+PltSection<ELFT>::PltSection()
+ : OutputSectionBase<ELFT>(".plt", llvm::ELF::SHT_PROGBITS,
+ llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_EXECINSTR) {
+ this->Header.sh_addralign = 16;
+}
+
+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();
+ }
+ for (auto &I : Entries) {
+ const SymbolBody *E = 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 Plt = this->getVA() + Off;
+ Target->writePltEntry(Buf + Off, GotVA, GotE, Plt, E->PltIndex, RelOff);
+ Off += Target->getPltEntrySize();
+ }
+}
+
+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>::finalize() {
+ this->Header.sh_size = Target->getPltZeroEntrySize() +
+ Entries.size() * Target->getPltEntrySize();
+}
+
+template <class ELFT>
+RelocationSection<ELFT>::RelocationSection(StringRef Name, bool IsRela)
+ : OutputSectionBase<ELFT>(Name,
+ IsRela ? llvm::ELF::SHT_RELA : llvm::ELF::SHT_REL,
+ llvm::ELF::SHF_ALLOC),
+ IsRela(IsRela) {
+ this->Header.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
+ this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
+}
+
+// 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;
+ }
+
+ 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> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {
+ const unsigned EntrySize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
+ for (const DynamicReloc<ELFT> &Rel : Relocs) {
+ auto *P = reinterpret_cast<Elf_Rel *>(Buf);
+ Buf += EntrySize;
+
+ // Skip placeholder for global dynamic TLS relocation pair. It was already
+ // handled by the previous relocation.
+ if (!Rel.C || !Rel.RI)
+ 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();
+
+ 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 CanBePreempted = canBePreempted(Body, NeedsGot);
+ bool LazyReloc = Body && Target->supportsLazyRelocations() &&
+ Target->relocNeedsPlt(Type, *Body);
+ bool IsDynRelative = Type == Target->getRelativeReloc();
+
+ unsigned Sym = CanBePreempted ? Body->DynamicSymbolTableIndex : 0;
+ unsigned Reloc;
+ if (!CanBePreempted && Body && isGnuIFunc<ELFT>(*Body))
+ Reloc = Target->getIRelativeReloc();
+ else if (!CanBePreempted || 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() +
+ dyn_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 (CanBePreempted || 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)));
+ else
+ Addend = getLocalRelTarget(File, RI, 0);
+
+ if (IsRela)
+ static_cast<Elf_Rela *>(P)->r_addend = Addend;
+ }
+}
+
+template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() {
+ const unsigned EntrySize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
+ return EntrySize * Relocs.size();
+}
+
+template <class ELFT> void RelocationSection<ELFT>::finalize() {
+ this->Header.sh_link = Static ? Out<ELFT>::SymTab->SectionIndex
+ : Out<ELFT>::DynSymTab->SectionIndex;
+ this->Header.sh_size = Relocs.size() * this->Header.sh_entsize;
+}
+
+template <class ELFT>
+InterpSection<ELFT>::InterpSection()
+ : OutputSectionBase<ELFT>(".interp", llvm::ELF::SHT_PROGBITS,
+ llvm::ELF::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->getOffset(Name);
+ *SHdr = Header;
+}
+
+template <class ELFT> void InterpSection<ELFT>::writeTo(uint8_t *Buf) {
+ memcpy(Buf, Config->DynamicLinker.data(), Config->DynamicLinker.size());
+}
+
+template <class ELFT>
+HashTableSection<ELFT>::HashTableSection()
+ : OutputSectionBase<ELFT>(".hash", llvm::ELF::SHT_HASH,
+ llvm::ELF::SHF_ALLOC) {
+ this->Header.sh_entsize = sizeof(Elf_Word);
+ this->Header.sh_addralign = sizeof(Elf_Word);
+}
+
+static uint32_t hashSysv(StringRef Name) {
+ uint32_t H = 0;
+ for (char C : Name) {
+ H = (H << 4) + C;
+ uint32_t G = H & 0xf0000000;
+ if (G)
+ H ^= G >> 24;
+ H &= ~G;
+ }
+ return H;
+}
+
+template <class ELFT> void HashTableSection<ELFT>::finalize() {
+ this->Header.sh_link = Out<ELFT>::DynSymTab->SectionIndex;
+
+ unsigned NumEntries = 2; // nbucket and nchain.
+ NumEntries += Out<ELFT>::DynSymTab->getNumSymbols(); // The chain entries.
+
+ // Create as many buckets as there are symbols.
+ // FIXME: This is simplistic. We can try to optimize it, but implementing
+ // support for SHT_GNU_HASH is probably even more profitable.
+ NumEntries += Out<ELFT>::DynSymTab->getNumSymbols();
+ this->Header.sh_size = NumEntries * sizeof(Elf_Word);
+}
+
+template <class ELFT> void HashTableSection<ELFT>::writeTo(uint8_t *Buf) {
+ unsigned NumSymbols = Out<ELFT>::DynSymTab->getNumSymbols();
+ auto *P = reinterpret_cast<Elf_Word *>(Buf);
+ *P++ = NumSymbols; // nbucket
+ *P++ = NumSymbols; // nchain
+
+ Elf_Word *Buckets = P;
+ Elf_Word *Chains = P + NumSymbols;
+
+ for (SymbolBody *Body : Out<ELFT>::DynSymTab->getSymbols()) {
+ StringRef Name = Body->getName();
+ unsigned I = Body->DynamicSymbolTableIndex;
+ uint32_t Hash = hashSysv(Name) % NumSymbols;
+ Chains[I] = Buckets[Hash];
+ Buckets[Hash] = I;
+ }
+}
+
+static uint32_t hashGnu(StringRef Name) {
+ uint32_t H = 5381;
+ for (uint8_t C : Name)
+ H = (H << 5) + H + C;
+ return H;
+}
+
+template <class ELFT>
+GnuHashTableSection<ELFT>::GnuHashTableSection()
+ : OutputSectionBase<ELFT>(".gnu.hash", llvm::ELF::SHT_GNU_HASH,
+ llvm::ELF::SHF_ALLOC) {
+ this->Header.sh_entsize = ELFT::Is64Bits ? 0 : 4;
+ this->Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
+}
+
+template <class ELFT>
+unsigned GnuHashTableSection<ELFT>::calcNBuckets(unsigned NumHashed) {
+ if (!NumHashed)
+ return 0;
+
+ // These values are prime numbers which are not greater than 2^(N-1) + 1.
+ // In result, for any particular NumHashed we return a prime number
+ // which is not greater than NumHashed.
+ static const unsigned Primes[] = {
+ 1, 1, 3, 3, 7, 13, 31, 61, 127, 251,
+ 509, 1021, 2039, 4093, 8191, 16381, 32749, 65521, 131071};
+
+ return Primes[std::min<unsigned>(Log2_32_Ceil(NumHashed),
+ array_lengthof(Primes) - 1)];
+}
+
+// Bloom filter estimation: at least 8 bits for each hashed symbol.
+// GNU Hash table requirement: it should be a power of 2,
+// the minimum value is 1, even for an empty table.
+// Expected results for a 32-bit target:
+// calcMaskWords(0..4) = 1
+// calcMaskWords(5..8) = 2
+// calcMaskWords(9..16) = 4
+// For a 64-bit target:
+// calcMaskWords(0..8) = 1
+// calcMaskWords(9..16) = 2
+// calcMaskWords(17..32) = 4
+template <class ELFT>
+unsigned GnuHashTableSection<ELFT>::calcMaskWords(unsigned NumHashed) {
+ if (!NumHashed)
+ return 1;
+ return NextPowerOf2((NumHashed - 1) / sizeof(Elf_Off));
+}
+
+template <class ELFT> void GnuHashTableSection<ELFT>::finalize() {
+ unsigned NumHashed = HashedSymbols.size();
+ NBuckets = calcNBuckets(NumHashed);
+ MaskWords = calcMaskWords(NumHashed);
+ // Second hash shift estimation: just predefined values.
+ Shift2 = ELFT::Is64Bits ? 6 : 5;
+
+ this->Header.sh_link = Out<ELFT>::DynSymTab->SectionIndex;
+ this->Header.sh_size = sizeof(Elf_Word) * 4 // Header
+ + sizeof(Elf_Off) * MaskWords // Bloom Filter
+ + sizeof(Elf_Word) * NBuckets // Hash Buckets
+ + sizeof(Elf_Word) * NumHashed; // Hash Values
+}
+
+template <class ELFT> void GnuHashTableSection<ELFT>::writeTo(uint8_t *Buf) {
+ writeHeader(Buf);
+ if (HashedSymbols.empty())
+ return;
+ writeBloomFilter(Buf);
+ writeHashTable(Buf);
+}
+
+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++ = MaskWords;
+ *P++ = Shift2;
+ Buf = reinterpret_cast<uint8_t *>(P);
+}
+
+template <class ELFT>
+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));
+ Masks[Pos] |= V;
+ }
+ Buf += sizeof(Elf_Off) * MaskWords;
+}
+
+template <class ELFT>
+void GnuHashTableSection<ELFT>::writeHashTable(uint8_t *Buf) {
+ Elf_Word *Buckets = reinterpret_cast<Elf_Word *>(Buf);
+ Elf_Word *Values = Buckets + NBuckets;
+
+ int PrevBucket = -1;
+ int I = 0;
+ for (const HashedSymbolData &Item : HashedSymbols) {
+ int Bucket = Item.Hash % NBuckets;
+ assert(PrevBucket <= Bucket);
+ if (Bucket != PrevBucket) {
+ Buckets[Bucket] = Item.Body->DynamicSymbolTableIndex;
+ PrevBucket = Bucket;
+ if (I > 0)
+ Values[I - 1] |= 1;
+ }
+ Values[I] = Item.Hash & ~1;
+ ++I;
+ }
+ if (I > 0)
+ Values[I - 1] |= 1;
+}
+
+static bool includeInGnuHashTable(SymbolBody *B) {
+ // Assume that includeInDynamicSymtab() is already checked.
+ return !B->isUndefined();
+}
+
+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())
+ return;
+
+ unsigned NBuckets = calcNBuckets(HashedSymbols.size());
+ std::stable_sort(HashedSymbols.begin(), HashedSymbols.end(),
+ [&](const HashedSymbolData &L, const HashedSymbolData &R) {
+ return L.Hash % NBuckets < R.Hash % NBuckets;
+ });
+
+ Symbols = std::move(NotHashed);
+ for (const HashedSymbolData &Item : HashedSymbols)
+ Symbols.push_back(Item.Body);
+}
+
+template <class ELFT>
+DynamicSection<ELFT>::DynamicSection(SymbolTable<ELFT> &SymTab)
+ : OutputSectionBase<ELFT>(".dynamic", llvm::ELF::SHT_DYNAMIC,
+ llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE),
+ SymTab(SymTab) {
+ Elf_Shdr &Header = this->Header;
+ Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
+ Header.sh_entsize = ELFT::Is64Bits ? 16 : 8;
+
+ // .dynamic section is not writable on MIPS.
+ // See "Special Section" in Chapter 4 in the following document:
+ // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
+ if (Config->EMachine == EM_MIPS)
+ Header.sh_flags = llvm::ELF::SHF_ALLOC;
+}
+
+template <class ELFT> void DynamicSection<ELFT>::finalize() {
+ if (this->Header.sh_size)
+ return; // Already finalized.
+
+ Elf_Shdr &Header = this->Header;
+ Header.sh_link = Out<ELFT>::DynStrTab->SectionIndex;
+
+ unsigned NumEntries = 0;
+ if (Out<ELFT>::RelaDyn->hasRelocs()) {
+ ++NumEntries; // DT_RELA / DT_REL
+ ++NumEntries; // DT_RELASZ / DT_RELSZ
+ ++NumEntries; // DT_RELAENT / DT_RELENT
+ }
+ if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
+ ++NumEntries; // DT_JMPREL
+ ++NumEntries; // DT_PLTRELSZ
+ ++NumEntries; // DT_PLTGOT / DT_MIPS_PLTGOT
+ ++NumEntries; // DT_PLTREL
+ }
+
+ ++NumEntries; // DT_SYMTAB
+ ++NumEntries; // DT_SYMENT
+ ++NumEntries; // DT_STRTAB
+ ++NumEntries; // DT_STRSZ
+ if (Out<ELFT>::GnuHashTab)
+ ++NumEntries; // DT_GNU_HASH
+ if (Out<ELFT>::HashTab)
+ ++NumEntries; // DT_HASH
+
+ if (!Config->RPath.empty()) {
+ ++NumEntries; // DT_RUNPATH / DT_RPATH
+ Out<ELFT>::DynStrTab->add(Config->RPath);
+ }
+
+ if (!Config->SoName.empty()) {
+ ++NumEntries; // DT_SONAME
+ Out<ELFT>::DynStrTab->add(Config->SoName);
+ }
+
+ 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->add(F->getSoName());
+ ++NumEntries;
+ }
+
+ 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 (Config->Bsymbolic)
+ DtFlags |= DF_SYMBOLIC;
+ if (Config->ZNodelete)
+ DtFlags1 |= DF_1_NODELETE;
+ if (Config->ZNow) {
+ DtFlags |= DF_BIND_NOW;
+ DtFlags1 |= DF_1_NOW;
+ }
+ if (Config->ZOrigin) {
+ DtFlags |= DF_ORIGIN;
+ DtFlags1 |= DF_1_ORIGIN;
+ }
+
+ if (DtFlags)
+ ++NumEntries; // DT_FLAGS
+ if (DtFlags1)
+ ++NumEntries; // DT_FLAGS_1
+
+ 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
+ if (Out<ELFT>::MipsRldMap)
+ ++NumEntries; // DT_MIPS_RLD_MAP
+ }
+
+ ++NumEntries; // DT_NULL
+
+ Header.sh_size = NumEntries * 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;
+ ++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->data().size());
+ 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->getOffset(Config->RPath));
+
+ if (!Config->SoName.empty())
+ WriteVal(DT_SONAME, Out<ELFT>::DynStrTab->getOffset(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->getOffset(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);
+
+ // 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());
+ }
+
+ WriteVal(DT_NULL, 0);
+}
+
+template <class ELFT>
+OutputSection<ELFT>::OutputSection(StringRef Name, uint32_t sh_type,
+ uintX_t sh_flags)
+ : OutputSectionBase<ELFT>(Name, sh_type, sh_flags) {}
+
+template <class ELFT>
+void OutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
+ 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;
+
+ uintX_t Off = this->Header.sh_size;
+ Off = RoundUpToAlignment(Off, Align);
+ S->OutSecOff = Off;
+ Off += S->getSize();
+ this->Header.sh_size = Off;
+}
+
+template <class ELFT>
+typename ELFFile<ELFT>::uintX_t lld::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;
+ 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
+lld::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;
+ }
+ return VA + Section->getOffset(Offset) + Addend;
+}
+
+// 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 lld::elf2::canBePreempted(const SymbolBody *Body, bool NeedsGot) {
+ if (!Body)
+ return false; // Body is a local symbol.
+ if (Body->isShared())
+ return true;
+
+ 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)
+ return false;
+ return Body->getVisibility() == STV_DEFAULT;
+}
+
+template <class ELFT> void OutputSection<ELFT>::writeTo(uint8_t *Buf) {
+ for (InputSection<ELFT> *C : Sections)
+ C->writeTo(Buf);
+}
+
+template <class ELFT>
+EHOutputSection<ELFT>::EHOutputSection(StringRef Name, uint32_t sh_type,
+ uintX_t sh_flags)
+ : OutputSectionBase<ELFT>(Name, sh_type, sh_flags) {}
+
+template <class ELFT>
+EHRegion<ELFT>::EHRegion(EHInputSection<ELFT> *S, unsigned Index)
+ : S(S), Index(Index) {}
+
+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>
+Cie<ELFT>::Cie(EHInputSection<ELFT> *S, unsigned Index)
+ : EHRegion<ELFT>(S, Index) {}
+
+template <class ELFT>
+template <bool IsRela>
+void EHOutputSection<ELFT>::addSectionAux(
+ EHInputSection<ELFT> *S,
+ iterator_range<const Elf_Rel_Impl<ELFT, IsRela> *> Rels) {
+ const endianness E = ELFT::TargetEndianness;
+
+ S->OutSec = this;
+ uint32_t Align = S->getAlign();
+ if (Align > this->Header.sh_addralign)
+ this->Header.sh_addralign = Align;
+
+ Sections.push_back(S);
+
+ ArrayRef<uint8_t> SecData = S->getSectionData();
+ ArrayRef<uint8_t> D = SecData;
+ uintX_t Offset = 0;
+ auto RelI = Rels.begin();
+ auto RelE = Rels.end();
+
+ DenseMap<unsigned, unsigned> OffsetToIndex;
+ while (!D.empty()) {
+ unsigned Index = S->Offsets.size();
+ S->Offsets.push_back(std::make_pair(Offset, -1));
+
+ uintX_t Length = readEntryLength(D);
+ StringRef Entry((const char *)D.data(), Length);
+
+ while (RelI != RelE && RelI->r_offset < Offset)
+ ++RelI;
+ uintX_t NextOffset = Offset + Length;
+ bool HasReloc = RelI != RelE && RelI->r_offset < NextOffset;
+
+ uint32_t ID = read32<E>(D.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 += RoundUpToAlignment(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 += RoundUpToAlignment(Length, sizeof(uintX_t));
+ }
+ }
+
+ Offset = NextOffset;
+ D = D.slice(Length);
+ }
+}
+
+template <class ELFT>
+typename EHOutputSection<ELFT>::uintX_t
+EHOutputSection<ELFT>::readEntryLength(ArrayRef<uint8_t> D) {
+ const endianness E = ELFT::TargetEndianness;
+
+ 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 (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;
+}
+
+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));
+}
+
+template <class ELFT>
+static typename ELFFile<ELFT>::uintX_t writeAlignedCieOrFde(StringRef Data,
+ uint8_t *Buf) {
+ typedef typename ELFFile<ELFT>::uintX_t uintX_t;
+ const endianness E = ELFT::TargetEndianness;
+ uint64_t Len = RoundUpToAlignment(Data.size(), sizeof(uintX_t));
+ write32<E>(Buf, Len - 4);
+ memcpy(Buf + 4, Data.data() + 4, Data.size() - 4);
+ return Len;
+}
+
+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 (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));
+ }
+}
+
+template <class ELFT>
+MergeOutputSection<ELFT>::MergeOutputSection(StringRef Name, uint32_t sh_type,
+ uintX_t sh_flags)
+ : OutputSectionBase<ELFT>(Name, sh_type, sh_flags) {}
+
+template <class ELFT> void MergeOutputSection<ELFT>::writeTo(uint8_t *Buf) {
+ if (shouldTailMerge()) {
+ StringRef Data = Builder.data();
+ memcpy(Buf, Data.data(), Data.size());
+ return;
+ }
+ for (const std::pair<StringRef, size_t> &P : Builder.getMap()) {
+ StringRef Data = P.first;
+ 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;
+}
+
+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;
+ uintX_t Offset = 0;
+
+ if (this->Header.sh_flags & SHF_STRINGS) {
+ 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(Offset, OutputOffset));
+ Offset += EntSize;
+ }
+ }
+}
+
+template <class ELFT>
+unsigned MergeOutputSection<ELFT>::getOffset(StringRef Val) {
+ return Builder.getOffset(Val);
+}
+
+template <class ELFT> bool MergeOutputSection<ELFT>::shouldTailMerge() const {
+ return Config->Optimize >= 2 && this->Header.sh_flags & SHF_STRINGS;
+}
+
+template <class ELFT> void MergeOutputSection<ELFT>::finalize() {
+ if (shouldTailMerge())
+ Builder.finalize();
+ this->Header.sh_size = Builder.getSize();
+}
+
+template <class ELFT>
+StringTableSection<ELFT>::StringTableSection(StringRef Name, bool Dynamic)
+ : OutputSectionBase<ELFT>(Name, llvm::ELF::SHT_STRTAB,
+ Dynamic ? (uintX_t)llvm::ELF::SHF_ALLOC : 0),
+ Dynamic(Dynamic) {
+ this->Header.sh_addralign = 1;
+}
+
+template <class ELFT> void StringTableSection<ELFT>::writeTo(uint8_t *Buf) {
+ StringRef Data = StrTabBuilder.data();
+ memcpy(Buf, Data.data(), Data.size());
+}
+
+template <class ELFT>
+bool lld::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;
+
+ if (Config->DiscardLocals)
+ return false;
+
+ return !(Sec->getSectionHdr()->sh_flags & SHF_MERGE);
+}
+
+template <class ELFT>
+SymbolTableSection<ELFT>::SymbolTableSection(
+ SymbolTable<ELFT> &Table, StringTableSection<ELFT> &StrTabSec)
+ : OutputSectionBase<ELFT>(
+ StrTabSec.isDynamic() ? ".dynsym" : ".symtab",
+ StrTabSec.isDynamic() ? llvm::ELF::SHT_DYNSYM : llvm::ELF::SHT_SYMTAB,
+ StrTabSec.isDynamic() ? (uintX_t)llvm::ELF::SHF_ALLOC : 0),
+ Table(Table), StrTabSec(StrTabSec) {
+ typedef OutputSectionBase<ELFT> Base;
+ typename Base::Elf_Shdr &Header = this->Header;
+
+ Header.sh_entsize = sizeof(Elf_Sym);
+ Header.sh_addralign = ELFT::Is64Bits ? 8 : 4;
+}
+
+// Orders symbols according to their positions in the GOT,
+// in compliance with MIPS ABI rules.
+// 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;
+}
+
+template <class ELFT> void SymbolTableSection<ELFT>::finalize() {
+ if (this->Header.sh_size)
+ return; // Already finalized.
+
+ this->Header.sh_size = getNumSymbols() * sizeof(Elf_Sym);
+ this->Header.sh_link = StrTabSec.SectionIndex;
+ this->Header.sh_info = NumLocals + 1;
+
+ if (!StrTabSec.isDynamic()) {
+ std::stable_sort(Symbols.begin(), Symbols.end(),
+ [](SymbolBody *L, SymbolBody *R) {
+ return getSymbolBinding(L) == STB_LOCAL &&
+ getSymbolBinding(R) != STB_LOCAL;
+ });
+ return;
+ }
+ if (Out<ELFT>::GnuHashTab)
+ // NB: It also sorts Symbols to meet the GNU hash table requirements.
+ Out<ELFT>::GnuHashTab->addSymbols(Symbols);
+ 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;
+}
+
+template <class ELFT>
+void SymbolTableSection<ELFT>::addLocalSymbol(StringRef Name) {
+ StrTabSec.add(Name);
+ ++NumVisible;
+ ++NumLocals;
+}
+
+template <class ELFT>
+void SymbolTableSection<ELFT>::addSymbol(SymbolBody *Body) {
+ StrTabSec.add(Body->getName());
+ Symbols.push_back(Body);
+ ++NumVisible;
+}
+
+template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {
+ Buf += sizeof(Elf_Sym);
+
+ // All symbols with STB_LOCAL binding precede the weak and global symbols.
+ // .dynsym only contains global symbols.
+ if (!Config->DiscardAll && !StrTabSec.isDynamic())
+ writeLocalSymbols(Buf);
+
+ writeGlobalSymbols(Buf);
+}
+
+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;
+
+ auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);
+ uintX_t VA = 0;
+ if (Sym.st_shndx == SHN_ABS) {
+ ESym->st_shndx = SHN_ABS;
+ VA = Sym.st_value;
+ } else {
+ InputSectionBase<ELFT> *Section = File->getSection(Sym);
+ if (!Section->isLive())
+ continue;
+ const OutputSectionBase<ELFT> *OutSec = Section->OutSec;
+ ESym->st_shndx = OutSec->SectionIndex;
+ VA += OutSec->getVA() + Section->getOffset(Sym);
+ }
+ ESym->st_name = StrTabSec.getOffset(SymName);
+ ESym->st_size = Sym.st_size;
+ ESym->setBindingAndType(Sym.getBinding(), Sym.getType());
+ ESym->st_value = VA;
+ 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;
+
+ 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.getOffset(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;
+ }
+
+ ESym->setBindingAndType(getSymbolBinding(Body), Type);
+ ESym->st_size = Size;
+ ESym->setVisibility(Body->getVisibility());
+ ESym->st_value = getSymVA<ELFT>(*Body);
+
+ if (OutSec)
+ ESym->st_shndx = OutSec->SectionIndex;
+ else if (isa<DefinedRegular<ELFT>>(Body))
+ ESym->st_shndx = SHN_ABS;
+
+ ++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;
+}
+
+template <class ELFT>
+MipsReginfoOutputSection<ELFT>::MipsReginfoOutputSection()
+ : OutputSectionBase<ELFT>(".reginfo", SHT_MIPS_REGINFO, SHF_ALLOC) {
+ this->Header.sh_addralign = 4;
+ this->Header.sh_entsize = sizeof(Elf_Mips_RegInfo);
+ this->Header.sh_size = sizeof(Elf_Mips_RegInfo);
+}
+
+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_gprmask = GeneralMask;
+}
+
+template <class ELFT>
+void MipsReginfoOutputSection<ELFT>::addSection(InputSectionBase<ELFT> *C) {
+ auto *S = cast<MipsReginfoInputSection<ELFT>>(C);
+ GeneralMask |= S->getGeneralMask();
+}
+
+namespace lld {
+namespace elf2 {
+template class OutputSectionBase<ELF32LE>;
+template class OutputSectionBase<ELF32BE>;
+template class OutputSectionBase<ELF64LE>;
+template class OutputSectionBase<ELF64BE>;
+
+template class GotPltSection<ELF32LE>;
+template class GotPltSection<ELF32BE>;
+template class GotPltSection<ELF64LE>;
+template class GotPltSection<ELF64BE>;
+
+template class GotSection<ELF32LE>;
+template class GotSection<ELF32BE>;
+template class GotSection<ELF64LE>;
+template class GotSection<ELF64BE>;
+
+template class PltSection<ELF32LE>;
+template class PltSection<ELF32BE>;
+template class PltSection<ELF64LE>;
+template class PltSection<ELF64BE>;
+
+template class RelocationSection<ELF32LE>;
+template class RelocationSection<ELF32BE>;
+template class RelocationSection<ELF64LE>;
+template class RelocationSection<ELF64BE>;
+
+template class InterpSection<ELF32LE>;
+template class InterpSection<ELF32BE>;
+template class InterpSection<ELF64LE>;
+template class InterpSection<ELF64BE>;
+
+template class GnuHashTableSection<ELF32LE>;
+template class GnuHashTableSection<ELF32BE>;
+template class GnuHashTableSection<ELF64LE>;
+template class GnuHashTableSection<ELF64BE>;
+
+template class HashTableSection<ELF32LE>;
+template class HashTableSection<ELF32BE>;
+template class HashTableSection<ELF64LE>;
+template class HashTableSection<ELF64BE>;
+
+template class DynamicSection<ELF32LE>;
+template class DynamicSection<ELF32BE>;
+template class DynamicSection<ELF64LE>;
+template class DynamicSection<ELF64BE>;
+
+template class OutputSection<ELF32LE>;
+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 MipsReginfoOutputSection<ELF32LE>;
+template class MipsReginfoOutputSection<ELF32BE>;
+template class MipsReginfoOutputSection<ELF64LE>;
+template class MipsReginfoOutputSection<ELF64BE>;
+
+template class MergeOutputSection<ELF32LE>;
+template class MergeOutputSection<ELF32BE>;
+template class MergeOutputSection<ELF64LE>;
+template class MergeOutputSection<ELF64BE>;
+
+template class StringTableSection<ELF32LE>;
+template class StringTableSection<ELF32BE>;
+template class StringTableSection<ELF64LE>;
+template class StringTableSection<ELF64BE>;
+
+template class SymbolTableSection<ELF32LE>;
+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 &);
+}
+}
diff --git a/ELF/OutputSections.h b/ELF/OutputSections.h
new file mode 100644
index 000000000000..6dca2b570308
--- /dev/null
+++ b/ELF/OutputSections.h
@@ -0,0 +1,485 @@
+//===- OutputSections.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_OUTPUT_SECTIONS_H
+#define LLD_ELF_OUTPUT_SECTIONS_H
+
+#include "lld/Core/LLVM.h"
+
+#include "llvm/ADT/MapVector.h"
+#include "llvm/MC/StringTableBuilder.h"
+#include "llvm/Object/ELF.h"
+
+#include "Config.h"
+
+#include <type_traits>
+
+namespace lld {
+namespace elf2 {
+
+class SymbolBody;
+template <class ELFT> class SymbolTable;
+template <class ELFT> class SymbolTableSection;
+template <class ELFT> class StringTableSection;
+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 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.
+// The writer creates multiple OutputSections and assign them unique,
+// 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;
+
+ OutputSectionBase(StringRef Name, uint32_t sh_type, uintX_t sh_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 writeHeaderTo(Elf_Shdr *SHdr);
+ StringRef getName() { return Name; }
+
+ virtual void addSection(InputSectionBase<ELFT> *C) {}
+
+ unsigned SectionIndex;
+
+ // 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;
+ }
+
+ virtual void finalize() {}
+ virtual void writeTo(uint8_t *Buf) = 0;
+ virtual ~OutputSectionBase() = default;
+
+protected:
+ StringRef Name;
+ Elf_Shdr Header;
+};
+
+template <class ELFT> class GotSection final : public OutputSectionBase<ELFT> {
+ typedef OutputSectionBase<ELFT> Base;
+ typedef typename Base::uintX_t 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;
+ uintX_t getGlobalDynAddr(const SymbolBody &B) const;
+ uintX_t getNumEntries() const { return Entries.size(); }
+
+ // Returns the symbol which corresponds to the first entry of the global part
+ // of GOT on MIPS platform. It is required to fill up MIPS-specific dynamic
+ // table properties.
+ // Returns nullptr if the global part is empty.
+ const SymbolBody *getMipsFirstGlobalEntry() const;
+
+ // Returns the number of entries in the local part of GOT including
+ // the number of reserved entries. This method is MIPS-specific.
+ unsigned getMipsLocalEntriesNum() const;
+
+ uint32_t getLocalTlsIndexVA() { return Base::getVA() + LocalTlsIndexOff; }
+
+private:
+ std::vector<const SymbolBody *> Entries;
+ uint32_t LocalTlsIndexOff = -1;
+};
+
+template <class ELFT>
+class GotPltSection final : public OutputSectionBase<ELFT> {
+ typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+
+public:
+ GotPltSection();
+ void finalize() override;
+ void writeTo(uint8_t *Buf) override;
+ void addEntry(SymbolBody *Sym);
+ bool empty() const;
+ uintX_t getEntryAddr(const SymbolBody &B) const;
+
+private:
+ std::vector<const SymbolBody *> Entries;
+};
+
+template <class ELFT> class PltSection final : public OutputSectionBase<ELFT> {
+ typedef OutputSectionBase<ELFT> Base;
+ typedef typename Base::uintX_t uintX_t;
+
+public:
+ PltSection();
+ void finalize() override;
+ void writeTo(uint8_t *Buf) override;
+ 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 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);
+
+ 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; }
+
+ ArrayRef<SymbolBody *> getSymbols() const { return Symbols; }
+
+private:
+ void writeLocalSymbols(uint8_t *&Buf);
+ void writeGlobalSymbols(uint8_t *Buf);
+
+ static uint8_t getSymbolBinding(SymbolBody *Body);
+
+ SymbolTable<ELFT> &Table;
+ StringTableSection<ELFT> &StrTabSec;
+ std::vector<SymbolBody *> Symbols;
+ unsigned NumVisible = 0;
+ unsigned NumLocals = 0;
+};
+
+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;
+
+public:
+ RelocationSection(StringRef Name, bool IsRela);
+ void addReloc(const DynamicReloc<ELFT> &Reloc) { Relocs.push_back(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);
+
+ 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);
+ void addSection(InputSectionBase<ELFT> *C) override;
+ void writeTo(uint8_t *Buf) override;
+
+private:
+ 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;
+
+public:
+ MergeOutputSection(StringRef Name, uint32_t sh_type, uintX_t sh_flags);
+ void addSection(InputSectionBase<ELFT> *S) override;
+ void writeTo(uint8_t *Buf) override;
+ unsigned getOffset(StringRef Val);
+ void finalize() override;
+
+private:
+ llvm::StringTableBuilder Builder{llvm::StringTableBuilder::RAW};
+};
+
+// 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;
+};
+
+template <class ELFT>
+class EHOutputSection final : public OutputSectionBase<ELFT> {
+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);
+ 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 addSection(InputSectionBase<ELFT> *S) override;
+
+private:
+ uintX_t readEntryLength(ArrayRef<uint8_t> D);
+
+ std::vector<EHInputSection<ELFT> *> Sections;
+ std::vector<Cie<ELFT>> Cies;
+
+ // Maps CIE content + personality to a index in Cies.
+ llvm::DenseMap<std::pair<StringRef, StringRef>, unsigned> CieMap;
+};
+
+template <class ELFT>
+class InterpSection final : public OutputSectionBase<ELFT> {
+public:
+ InterpSection();
+ void writeTo(uint8_t *Buf) override;
+};
+
+template <class ELFT>
+class StringTableSection final : public OutputSectionBase<ELFT> {
+public:
+ typedef typename llvm::object::ELFFile<ELFT>::uintX_t uintX_t;
+ StringTableSection(StringRef Name, bool Dynamic);
+ void add(StringRef S) { StrTabBuilder.add(S); }
+ size_t getOffset(StringRef S) const { return StrTabBuilder.getOffset(S); }
+ StringRef data() const { return StrTabBuilder.data(); }
+ void writeTo(uint8_t *Buf) override;
+
+ void finalize() override {
+ StrTabBuilder.finalize();
+ this->Header.sh_size = StrTabBuilder.data().size();
+ }
+
+ bool isDynamic() const { return Dynamic; }
+
+private:
+ const bool Dynamic;
+ llvm::StringTableBuilder StrTabBuilder{llvm::StringTableBuilder::ELF};
+};
+
+template <class ELFT>
+class HashTableSection final : public OutputSectionBase<ELFT> {
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Word Elf_Word;
+
+public:
+ HashTableSection();
+ void finalize() override;
+ void writeTo(uint8_t *Buf) override;
+};
+
+// Outputs GNU Hash section. For detailed explanation see:
+// 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;
+
+public:
+ GnuHashTableSection();
+ void finalize() override;
+ void writeTo(uint8_t *Buf) override;
+
+ // Adds symbols to the hash table.
+ // Sorts the input to satisfy GNU hash section requirements.
+ void addSymbols(std::vector<SymbolBody *> &Symbols);
+
+private:
+ static unsigned calcNBuckets(unsigned NumHashed);
+ static unsigned calcMaskWords(unsigned NumHashed);
+
+ void writeHeader(uint8_t *&Buf);
+ void writeBloomFilter(uint8_t *&Buf);
+ void writeHashTable(uint8_t *Buf);
+
+ struct HashedSymbolData {
+ SymbolBody *Body;
+ uint32_t Hash;
+ };
+
+ std::vector<HashedSymbolData> HashedSymbols;
+
+ unsigned MaskWords;
+ unsigned NBuckets;
+ unsigned Shift2;
+};
+
+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;
+
+public:
+ DynamicSection(SymbolTable<ELFT> &SymTab);
+ 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>
+class MipsReginfoOutputSection final : public OutputSectionBase<ELFT> {
+ typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;
+
+public:
+ MipsReginfoOutputSection();
+ void writeTo(uint8_t *Buf) override;
+ void addSection(InputSectionBase<ELFT> *S) override;
+
+private:
+ uint32_t GeneralMask = 0;
+};
+
+// 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;
+ static DynamicSection<ELFT> *Dynamic;
+ static GnuHashTableSection<ELFT> *GnuHashTab;
+ static GotPltSection<ELFT> *GotPlt;
+ static GotSection<ELFT> *Got;
+ static HashTableSection<ELFT> *HashTab;
+ static InterpSection<ELFT> *Interp;
+ static OutputSection<ELFT> *Bss;
+ static OutputSection<ELFT> *MipsRldMap;
+ static OutputSectionBase<ELFT> *Opd;
+ static uint8_t *OpdBuf;
+ static PltSection<ELFT> *Plt;
+ static RelocationSection<ELFT> *RelaDyn;
+ static RelocationSection<ELFT> *RelaPlt;
+ static StringTableSection<ELFT> *DynStrTab;
+ static StringTableSection<ELFT> *ShStrTab;
+ static StringTableSection<ELFT> *StrTab;
+ static SymbolTableSection<ELFT> *DynSymTab;
+ static SymbolTableSection<ELFT> *SymTab;
+ static Elf_Phdr *TlsPhdr;
+};
+
+template <class ELFT> DynamicSection<ELFT> *Out<ELFT>::Dynamic;
+template <class ELFT> GnuHashTableSection<ELFT> *Out<ELFT>::GnuHashTab;
+template <class ELFT> GotPltSection<ELFT> *Out<ELFT>::GotPlt;
+template <class ELFT> GotSection<ELFT> *Out<ELFT>::Got;
+template <class ELFT> HashTableSection<ELFT> *Out<ELFT>::HashTab;
+template <class ELFT> InterpSection<ELFT> *Out<ELFT>::Interp;
+template <class ELFT> OutputSection<ELFT> *Out<ELFT>::Bss;
+template <class ELFT> OutputSection<ELFT> *Out<ELFT>::MipsRldMap;
+template <class ELFT> OutputSectionBase<ELFT> *Out<ELFT>::Opd;
+template <class ELFT> uint8_t *Out<ELFT>::OpdBuf;
+template <class ELFT> PltSection<ELFT> *Out<ELFT>::Plt;
+template <class ELFT> RelocationSection<ELFT> *Out<ELFT>::RelaDyn;
+template <class ELFT> RelocationSection<ELFT> *Out<ELFT>::RelaPlt;
+template <class ELFT> StringTableSection<ELFT> *Out<ELFT>::DynStrTab;
+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
+} // namespace lld
+
+#endif // LLD_ELF_OUTPUT_SECTIONS_H
diff --git a/ELF/README.md b/ELF/README.md
new file mode 100644
index 000000000000..49b8167bbfe0
--- /dev/null
+++ b/ELF/README.md
@@ -0,0 +1,21 @@
+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.
diff --git a/ELF/SymbolTable.cpp b/ELF/SymbolTable.cpp
new file mode 100644
index 000000000000..e022ecd2e90d
--- /dev/null
+++ b/ELF/SymbolTable.cpp
@@ -0,0 +1,267 @@
+//===- SymbolTable.cpp ----------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Symbol table is a bag of all known symbols. We put all symbols of
+// all input files to the symbol table. The symbol Table is basically
+// a hash table with the logic to resolve symbol name conflicts using
+// the symbol types.
+//
+//===----------------------------------------------------------------------===//
+
+#include "SymbolTable.h"
+#include "Config.h"
+#include "Error.h"
+#include "Symbols.h"
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::ELF;
+
+using namespace lld;
+using namespace lld::elf2;
+
+template <class ELFT> SymbolTable<ELFT>::SymbolTable() {}
+
+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;
+ StringRef A = F->getName();
+ StringRef B = Config->Emulation;
+ if (B.empty())
+ B = Config->FirstElf->getName();
+ error(A + " is incompatible with " + B);
+}
+
+template <class ELFT>
+void SymbolTable<ELFT>::addFile(std::unique_ptr<InputFile> File) {
+ InputFile *FileP = File.get();
+ checkCompatibility<ELFT>(FileP);
+
+ // .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);
+ return;
+ }
+
+ // .so file
+ if (auto *F = dyn_cast<SharedFile<ELFT>>(FileP)) {
+ // DSOs are uniquified not by filename but by soname.
+ F->parseSoName();
+ if (!IncludedSoNames.insert(F->getSoName()).second)
+ return;
+
+ SharedFiles.emplace_back(cast<SharedFile<ELFT>>(File.release()));
+ F->parse();
+ for (SharedSymbol<ELFT> &B : F->getSharedSymbols())
+ resolve(&B);
+ return;
+ }
+
+ // .o file
+ auto *F = cast<ObjectFile<ELFT>>(FileP);
+ ObjectFiles.emplace_back(cast<ObjectFile<ELFT>>(File.release()));
+ F->parse(Comdats);
+ 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;
+}
+
+// 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;
+}
+
+template <class ELFT>
+void SymbolTable<ELFT>::addAbsolute(StringRef Name,
+ typename ELFFile<ELFT>::Elf_Sym &ESym) {
+ resolve(new (Alloc) DefinedRegular<ELFT>(Name, ESym, nullptr));
+}
+
+template <class ELFT>
+void SymbolTable<ELFT>::addSynthetic(StringRef Name,
+ OutputSectionBase<ELFT> &Section,
+ typename ELFFile<ELFT>::uintX_t Value) {
+ auto *Sym = new (Alloc) DefinedSynthetic<ELFT>(Name, Value, Section);
+ resolve(Sym);
+}
+
+template <class ELFT>
+SymbolBody *SymbolTable<ELFT>::addIgnored(StringRef Name) {
+ auto *Sym = new (Alloc)
+ DefinedRegular<ELFT>(Name, ElfSym<ELFT>::IgnoreUndef, nullptr);
+ resolve(Sym);
+ return Sym;
+}
+
+template <class ELFT> bool SymbolTable<ELFT>::isUndefined(StringRef Name) {
+ if (SymbolBody *Sym = find(Name))
+ return Sym->isUndefined();
+ return false;
+}
+
+// Returns a file from which symbol B was created.
+// If B does not belong to any file in ObjectFiles, returns a nullptr.
+template <class ELFT>
+ELFFileBase<ELFT> *
+elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles,
+ const 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();
+ }
+ return nullptr;
+}
+
+template <class ELFT>
+std::string SymbolTable<ELFT>::conflictMsg(SymbolBody *Old, SymbolBody *New) {
+ ELFFileBase<ELFT> *OldFile = findFile<ELFT>(ObjectFiles, Old);
+ ELFFileBase<ELFT> *NewFile = findFile<ELFT>(ObjectFiles, New);
+
+ StringRef Sym = Old->getName();
+ StringRef F1 = OldFile ? OldFile->getName() : "(internal)";
+ StringRef F2 = NewFile ? NewFile->getName() : "(internal)";
+ return (Sym + " in " + F1 + " and " + F2).str();
+}
+
+// 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;
+
+ SymbolBody *Existing = Sym->Body;
+
+ if (Lazy *L = dyn_cast<Lazy>(Existing)) {
+ if (auto *Undef = dyn_cast<Undefined>(New)) {
+ addMemberFile(Undef, L);
+ return;
+ }
+ // Found a definition for something also in an archive.
+ // Ignore the archive definition.
+ Sym->Body = New;
+ return;
+ }
+
+ 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;
+ }
+ if (comp < 0)
+ Sym->Body = New;
+}
+
+template <class ELFT> Symbol *SymbolTable<ELFT>::insert(SymbolBody *New) {
+ // Find an existing Symbol or create and insert a new one.
+ StringRef Name = New->getName();
+ Symbol *&Sym = Symtab[Name];
+ if (!Sym)
+ Sym = new (Alloc) Symbol{New};
+ New->setBackref(Sym);
+ return Sym;
+}
+
+template <class ELFT> SymbolBody *SymbolTable<ELFT>::find(StringRef Name) {
+ auto It = Symtab.find(Name);
+ if (It == Symtab.end())
+ return nullptr;
+ return It->second->Body;
+}
+
+template <class ELFT> void SymbolTable<ELFT>::addLazy(Lazy *L) {
+ Symbol *Sym = insert(L);
+ if (Sym->Body == L)
+ return;
+ if (auto *Undef = dyn_cast<Undefined>(Sym->Body)) {
+ Sym->Body = L;
+ addMemberFile(Undef, L);
+ }
+}
+
+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();
+ return;
+ }
+
+ // 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));
+}
+
+// This function takes care of the case in which shared libraries depend on
+// the user program (not the other way, which is usual). Shared libraries
+// may have undefined symbols, expecting that the user program provides
+// the definitions for them. An example is BSD's __progname symbol.
+// We need to put such symbols to the main program's .dynsym so that
+// shared libraries can find them.
+// Except this, we ignore undefined symbols in DSOs.
+template <class ELFT> void SymbolTable<ELFT>::scanShlibUndefined() {
+ for (std::unique_ptr<SharedFile<ELFT>> &File : SharedFiles)
+ for (StringRef U : File->getUndefinedSymbols())
+ if (SymbolBody *Sym = find(U))
+ if (Sym->isDefined())
+ Sym->setUsedInDynamicReloc();
+}
+
+template class lld::elf2::SymbolTable<ELF32LE>;
+template class lld::elf2::SymbolTable<ELF32BE>;
+template class lld::elf2::SymbolTable<ELF64LE>;
+template class lld::elf2::SymbolTable<ELF64BE>;
+
+template ELFFileBase<ELF32LE> *
+lld::elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELF32LE>>>,
+ const SymbolBody *);
+template ELFFileBase<ELF32BE> *
+lld::elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELF32BE>>>,
+ const SymbolBody *);
+template ELFFileBase<ELF64LE> *
+lld::elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELF64LE>>>,
+ const SymbolBody *);
+template ELFFileBase<ELF64BE> *
+lld::elf2::findFile(ArrayRef<std::unique_ptr<ObjectFile<ELF64BE>>>,
+ const SymbolBody *);
diff --git a/ELF/SymbolTable.h b/ELF/SymbolTable.h
new file mode 100644
index 000000000000..aa905e027d48
--- /dev/null
+++ b/ELF/SymbolTable.h
@@ -0,0 +1,98 @@
+//===- SymbolTable.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_TABLE_H
+#define LLD_ELF_SYMBOL_TABLE_H
+
+#include "InputFiles.h"
+#include "llvm/ADT/MapVector.h"
+
+namespace lld {
+namespace elf2 {
+class Lazy;
+template <class ELFT> class OutputSectionBase;
+struct Symbol;
+class Undefined;
+
+// SymbolTable is a bucket of all known symbols, including defined,
+// undefined, or lazy symbols (the last one is symbols in archive
+// files whose archive members are not yet loaded).
+//
+// We put all symbols of all files to a SymbolTable, and the
+// SymbolTable selects the "best" symbols if there are name
+// 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().
+template <class ELFT> class SymbolTable {
+public:
+ SymbolTable();
+
+ void addFile(std::unique_ptr<InputFile> File);
+
+ const llvm::MapVector<StringRef, Symbol *> &getSymbols() const {
+ return Symtab;
+ }
+
+ const std::vector<std::unique_ptr<ObjectFile<ELFT>>> &getObjectFiles() const {
+ return ObjectFiles;
+ }
+
+ const std::vector<std::unique_ptr<SharedFile<ELFT>>> &getSharedFiles() const {
+ return SharedFiles;
+ }
+
+ SymbolBody *addUndefined(StringRef Name);
+ SymbolBody *addUndefinedOpt(StringRef Name);
+ void addAbsolute(StringRef Name,
+ typename llvm::object::ELFFile<ELFT>::Elf_Sym &ESym);
+ void addSynthetic(StringRef Name, OutputSectionBase<ELFT> &Section,
+ typename llvm::object::ELFFile<ELFT>::uintX_t Value);
+ SymbolBody *addIgnored(StringRef Name);
+ bool isUndefined(StringRef Name);
+ void scanShlibUndefined();
+ SymbolBody *find(StringRef Name);
+
+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<std::unique_ptr<ArchiveFile>> ArchiveFiles;
+
+ // 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.
+ // FIXME: Experiment with passing in a custom hashing or sorting the symbols
+ // once symbol resolution is finished.
+ llvm::MapVector<StringRef, Symbol *> Symtab;
+ llvm::BumpPtrAllocator Alloc;
+
+ llvm::DenseSet<StringRef> Comdats;
+
+ // The writer needs to infer the machine type from the object files.
+ std::vector<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles;
+
+ std::vector<std::unique_ptr<SharedFile<ELFT>>> SharedFiles;
+ llvm::DenseSet<StringRef> IncludedSoNames;
+};
+
+template <class ELFT>
+ELFFileBase<ELFT> *
+findFile(ArrayRef<std::unique_ptr<ObjectFile<ELFT>>> ObjectFiles,
+ const SymbolBody *B);
+
+} // namespace elf2
+} // namespace lld
+
+#endif
diff --git a/ELF/Symbols.cpp b/ELF/Symbols.cpp
new file mode 100644
index 000000000000..f8d585242a86
--- /dev/null
+++ b/ELF/Symbols.cpp
@@ -0,0 +1,148 @@
+//===- Symbols.cpp --------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Symbols.h"
+#include "InputSection.h"
+#include "Error.h"
+#include "InputFiles.h"
+
+#include "llvm/ADT/STLExtras.h"
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::ELF;
+
+using namespace lld;
+using namespace lld::elf2;
+
+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 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());
+
+ // Normalize
+ if (L > R)
+ return -Other->compare<ELFT>(this);
+
+ Visibility = Other->Visibility =
+ getMinVisibility(Visibility, Other->Visibility);
+
+ if (IsUsedInRegularObj || Other->IsUsedInRegularObj)
+ IsUsedInRegularObj = Other->IsUsedInRegularObj = true;
+
+ if (L != R)
+ return -1;
+ if (!L.first || !L.second)
+ return 1;
+ 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 0;
+}
+
+Defined::Defined(Kind K, StringRef Name, bool IsWeak, uint8_t Visibility,
+ bool IsTls)
+ : SymbolBody(K, Name, IsWeak, Visibility, IsTls) {}
+
+Undefined::Undefined(SymbolBody::Kind K, StringRef N, bool IsWeak,
+ uint8_t Visibility, bool IsTls)
+ : SymbolBody(K, N, IsWeak, Visibility, IsTls), CanKeepUndefined(false) {}
+
+Undefined::Undefined(StringRef N, bool IsWeak, uint8_t Visibility,
+ bool CanKeepUndefined)
+ : Undefined(SymbolBody::UndefinedKind, N, IsWeak, Visibility,
+ /*IsTls*/ false) {
+ this->CanKeepUndefined = CanKeepUndefined;
+}
+
+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) {}
+
+template <typename ELFT>
+DefinedSynthetic<ELFT>::DefinedSynthetic(StringRef N, uintX_t Value,
+ OutputSectionBase<ELFT> &Section)
+ : Defined(SymbolBody::DefinedSyntheticKind, N, false, STV_DEFAULT, false),
+ 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;
+}
+
+std::unique_ptr<InputFile> Lazy::getMember() {
+ 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 createELFFile<ObjectFile>(MBRef);
+}
+
+template <class ELFT> static void doInitSymbols() {
+ ElfSym<ELFT>::End.setBinding(STB_GLOBAL);
+ ElfSym<ELFT>::IgnoreUndef.setBinding(STB_WEAK);
+ ElfSym<ELFT>::IgnoreUndef.setVisibility(STV_HIDDEN);
+}
+
+void lld::elf2::initSymbols() {
+ doInitSymbols<ELF32LE>();
+ doInitSymbols<ELF32BE>();
+ doInitSymbols<ELF64LE>();
+ doInitSymbols<ELF64BE>();
+}
+
+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 class lld::elf2::UndefinedElf<ELF32LE>;
+template class lld::elf2::UndefinedElf<ELF32BE>;
+template class lld::elf2::UndefinedElf<ELF64LE>;
+template class lld::elf2::UndefinedElf<ELF64BE>;
+
+template class lld::elf2::DefinedSynthetic<ELF32LE>;
+template class lld::elf2::DefinedSynthetic<ELF32BE>;
+template class lld::elf2::DefinedSynthetic<ELF64LE>;
+template class lld::elf2::DefinedSynthetic<ELF64BE>;
diff --git a/ELF/Symbols.h b/ELF/Symbols.h
new file mode 100644
index 000000000000..8556452dbb13
--- /dev/null
+++ b/ELF/Symbols.h
@@ -0,0 +1,327 @@
+//===- Symbols.h ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// 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
+#define LLD_ELF_SYMBOLS_H
+
+#include "InputSection.h"
+
+#include "lld/Core/LLVM.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/ELF.h"
+
+namespace lld {
+namespace elf2 {
+
+class ArchiveFile;
+class InputFile;
+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;
+};
+
+// The base class for real symbol classes.
+class SymbolBody {
+public:
+ enum Kind {
+ DefinedFirst,
+ DefinedRegularKind = DefinedFirst,
+ SharedKind,
+ DefinedElfLast = SharedKind,
+ DefinedCommonKind,
+ DefinedSyntheticKind,
+ DefinedLast = DefinedSyntheticKind,
+ UndefinedElfKind,
+ UndefinedKind,
+ LazyKind
+ };
+
+ Kind kind() const { return static_cast<Kind>(SymbolKind); }
+
+ bool isWeak() const { return IsWeak; }
+ bool isUndefined() const {
+ return SymbolKind == UndefinedKind || SymbolKind == UndefinedElfKind;
+ }
+ bool isDefined() const { return SymbolKind <= DefinedLast; }
+ bool isCommon() const { return SymbolKind == DefinedCommonKind; }
+ bool isLazy() const { return SymbolKind == LazyKind; }
+ 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; }
+
+ // Returns the symbol name.
+ StringRef getName() const { return Name; }
+
+ uint8_t getVisibility() const { return Visibility; }
+
+ unsigned DynamicSymbolTableIndex = 0;
+ uint32_t GlobalDynIndex = -1;
+ uint32_t GotIndex = -1;
+ uint32_t GotPltIndex = -1;
+ uint32_t PltIndex = -1;
+ bool hasGlobalDynIndex() { return GlobalDynIndex != uint32_t(-1); }
+ bool isInGot() const { return GotIndex != -1U; }
+ bool isInGotPlt() const { return GotPltIndex != -1U; }
+ bool isInPlt() const { return PltIndex != -1U; }
+
+ // 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; }
+
+ // 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);
+
+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;
+ }
+
+ 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;
+
+ // If true, the symbol is added to .dynsym symbol table.
+ unsigned IsUsedInDynamicReloc : 1;
+
+ unsigned IsTls : 1;
+ StringRef Name;
+ Symbol *Backref = nullptr;
+};
+
+// The base class for any defined symbols.
+class Defined : public SymbolBody {
+public:
+ Defined(Kind K, StringRef Name, bool IsWeak, uint8_t Visibility, bool IsTls);
+ 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;
+
+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;
+ }
+};
+
+class DefinedCommon : public Defined {
+public:
+ DefinedCommon(StringRef N, uint64_t Size, uint64_t Alignment, bool IsWeak,
+ uint8_t Visibility);
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() == SymbolBody::DefinedCommonKind;
+ }
+
+ // The output offset of this common symbol in the output bss. Computed by the
+ // writer.
+ uint64_t OffsetInBSS;
+
+ // The maximum alignment we have seen for this symbol.
+ uint64_t MaxAlignment;
+
+ 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;
+
+public:
+ DefinedRegular(StringRef N, const Elf_Sym &Sym,
+ InputSectionBase<ELFT> *Section)
+ : DefinedElf<ELFT>(SymbolBody::DefinedRegularKind, N, Sym),
+ Section(Section) {}
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() == SymbolBody::DefinedRegularKind;
+ }
+
+ // If this is null, the symbol is absolute.
+ InputSectionBase<ELFT> *Section;
+};
+
+// 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.
+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;
+ DefinedSynthetic(StringRef N, uintX_t Value,
+ OutputSectionBase<ELFT> &Section);
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() == SymbolBody::DefinedSyntheticKind;
+ }
+
+ uintX_t Value;
+ 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;
+
+ static bool classof(const SymbolBody *S) {
+ return S->kind() == SymbolBody::UndefinedElfKind;
+ }
+};
+
+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;
+
+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) {}
+
+ SharedFile<ELFT> *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;
+ uintX_t OffsetInBSS = 0;
+};
+
+// This class represents a symbol defined in an archive file. It is
+// created from an archive file header, and it knows how to load an
+// object file from an archive to replace itself with a defined
+// symbol. If the resolver finds both Undefined and Lazy for
+// 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; }
+
+ // Returns an object file for this symbol, or a nullptr if the file
+ // was already returned.
+ std::unique_ptr<InputFile> getMember();
+
+ void setWeak() { IsWeak = true; }
+ void setUsedInRegularObj() { IsUsedInRegularObj = true; }
+
+private:
+ ArchiveFile *File;
+ const llvm::object::Archive::Symbol Sym;
+};
+
+// 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.
+template <class ELFT> struct ElfSym {
+ typedef typename llvm::object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
+
+ // Used to represent an undefined symbol which we don't want
+ // to add to the output file's symbol table.
+ static Elf_Sym IgnoreUndef;
+
+ // The content for _end and end symbols.
+ static Elf_Sym End;
+
+ // The content for _gp symbol for MIPS target.
+ static Elf_Sym MipsGp;
+
+ // __rel_iplt_start/__rel_iplt_end for signaling
+ // where R_[*]_IRELATIVE relocations do live.
+ static Elf_Sym RelaIpltStart;
+ static Elf_Sym RelaIpltEnd;
+};
+
+template <class ELFT> typename ElfSym<ELFT>::Elf_Sym ElfSym<ELFT>::IgnoreUndef;
+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;
+
+} // namespace elf2
+} // namespace lld
+
+#endif
diff --git a/ELF/Target.cpp b/ELF/Target.cpp
new file mode 100644
index 000000000000..8d848d040c61
--- /dev/null
+++ b/ELF/Target.cpp
@@ -0,0 +1,1481 @@
+//===- Target.cpp ---------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Machine-specific things, such as applying relocations, creation of
+// 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.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Target.h"
+#include "Error.h"
+#include "OutputSections.h"
+#include "Symbols.h"
+
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/Object/ELF.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/ELF.h"
+
+using namespace llvm;
+using namespace llvm::object;
+using namespace llvm::support::endian;
+using namespace llvm::ELF;
+
+namespace lld {
+namespace elf2 {
+
+std::unique_ptr<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); }
+
+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");
+}
+
+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");
+}
+
+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");
+}
+
+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);
+}
+
+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;
+}
+
+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;
+};
+
+class X86_64TargetInfo final : public TargetInfo {
+public:
+ X86_64TargetInfo();
+ unsigned getPltRefReloc(unsigned Type) const override;
+ 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 isSizeDynReloc(uint32_t 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;
+
+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;
+};
+
+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;
+};
+
+class AArch64TargetInfo final : public TargetInfo {
+public:
+ AArch64TargetInfo();
+ unsigned getDynReloc(unsigned Type) const override;
+ unsigned getPltRefReloc(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;
+ 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;
+};
+
+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;
+};
+} // anonymous namespace
+
+TargetInfo *createTarget() {
+ switch (Config->EMachine) {
+ case EM_386:
+ return new X86TargetInfo();
+ case EM_AARCH64:
+ return new AArch64TargetInfo();
+ case EM_MIPS:
+ switch (Config->EKind) {
+ case ELF32LEKind:
+ return new MipsTargetInfo<ELF32LE>();
+ case ELF32BEKind:
+ return new MipsTargetInfo<ELF32BE>();
+ default:
+ error("Unsupported MIPS target");
+ }
+ case EM_PPC64:
+ return new PPC64TargetInfo();
+ case EM_X86_64:
+ return new X86_64TargetInfo();
+ }
+ error("Unknown target machine");
+}
+
+TargetInfo::~TargetInfo() {}
+
+bool TargetInfo::isTlsOptimized(unsigned Type, const SymbolBody *S) const {
+ return false;
+}
+
+uint64_t TargetInfo::getVAStart() const { return Config->Shared ? 0 : VAStart; }
+
+bool TargetInfo::needsCopyRel(uint32_t Type, const SymbolBody &S) const {
+ return false;
+}
+
+bool TargetInfo::isGotRelative(uint32_t Type) const { return false; }
+
+unsigned TargetInfo::getPltRefReloc(unsigned Type) const { return PCRelReloc; }
+
+bool TargetInfo::isRelRelative(uint32_t Type) const { return true; }
+
+bool TargetInfo::isSizeDynReloc(uint32_t Type, const SymbolBody &S) const {
+ return false;
+}
+
+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::writeGotHeaderEntries(uint8_t *Buf) const {}
+
+void TargetInfo::writeGotPltHeaderEntries(uint8_t *Buf) const {}
+
+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;
+ PltEntrySize = 16;
+ PltZeroEntrySize = 16;
+}
+
+void X86TargetInfo::writeGotPltHeaderEntries(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);
+}
+
+unsigned X86TargetInfo::getDynReloc(unsigned Type) const {
+ if (Type == R_386_TLS_LE)
+ return R_386_TLS_TPOFF;
+ if (Type == R_386_TLS_LE_32)
+ return R_386_TLS_TPOFF32;
+ return Type;
+}
+
+unsigned X86TargetInfo::getTlsGotReloc(unsigned Type) const {
+ if (Type == R_386_TLS_IE)
+ return Type;
+ return TlsGotReloc;
+}
+
+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;
+}
+
+void X86TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr) const {
+ // Executable files and shared object files have
+ // separate procedure linkage tables.
+ if (Config->Shared) {
+ 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
+ };
+ memcpy(Buf, V, sizeof(V));
+ return;
+ }
+
+ 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
+ };
+ memcpy(Buf, PltData, sizeof(PltData));
+ write32le(Buf + 2, GotEntryAddr + 4); // GOT+4
+ write32le(Buf + 8, GotEntryAddr + 8); // GOT+8
+}
+
+void X86TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
+ 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);
+ write32le(Buf + 7, RelOff);
+ write32le(Buf + 12, -Index * PltEntrySize - PltZeroEntrySize - 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 {
+ switch (Type) {
+ case R_386_32:
+ add32le(Loc, SA);
+ break;
+ case R_386_GOT32:
+ 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;
+ }
+ 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;
+}
+
+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 {
+ const uint8_t Inst[] = {
+ 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %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,
+ 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 {
+ const uint8_t Inst[] = {
+ 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %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,
+ 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));
+}
+
+// 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 {
+ // 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;
+ } else {
+ *Inst = IsMov ? 0xc7 : 0x81;
+ *Op = 0xc0 | ((*Op >> 3) & 7);
+ }
+ } 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);
+ }
+ 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;
+ PltEntrySize = 16;
+ PltZeroEntrySize = 16;
+}
+
+void X86_64TargetInfo::writeGotPltHeaderEntries(uint8_t *Buf) const {
+ write64le(Buf, Out<ELF64LE>::Dynamic->getVA());
+}
+
+void X86_64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {
+ // Skip 6 bytes of "jmpq *got(%rip)"
+ write32le(Buf, Plt + 6);
+}
+
+void X86_64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr) 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
+}
+
+void X86_64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
+ 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>
+ 0xe9, 0x00, 0x00, 0x00, 0x00 // jmpq plt[0]
+ };
+ memcpy(Buf, Inst, sizeof(Inst));
+
+ 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;
+}
+
+unsigned X86_64TargetInfo::getPltRefReloc(unsigned Type) const {
+ if (Type == R_X86_64_PLT32)
+ return R_X86_64_PC32;
+ return Type;
+}
+
+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);
+ }
+}
+
+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:
+ case R_X86_64_SIZE32:
+ case R_X86_64_SIZE64:
+ return true;
+ }
+}
+
+bool X86_64TargetInfo::isSizeDynReloc(uint32_t Type,
+ const SymbolBody &S) const {
+ return (Type == R_X86_64_SIZE32 || Type == R_X86_64_SIZE64) &&
+ canBePreempted(&S, false);
+}
+
+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));
+}
+
+// "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 {
+ 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 {
+ 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);
+}
+
+// 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;
+ 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;
+ }
+ case R_X86_64_TLSLD:
+ relocateTlsLdToLe(Loc, BufEnd, P, SA);
+ // The next relocation should be against __tls_get_addr, so skip it
+ return 1;
+ }
+ llvm_unreachable("Unknown TLS optimization");
+}
+
+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 {
+ switch (Type) {
+ case R_X86_64_32:
+ checkUInt<32>(SA, Type);
+ write32le(Loc, SA);
+ 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_GOTPCREL:
+ case R_X86_64_PC32:
+ case R_X86_64_PLT32:
+ case R_X86_64_TLSGD:
+ case R_X86_64_TLSLD:
+ write32le(Loc, SA - P);
+ break;
+ 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);
+ break;
+ default:
+ error("unrecognized reloc " + Twine(Type));
+ }
+}
+
+// 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
+// document.
+static uint16_t applyPPCLo(uint64_t V) { return V; }
+static uint16_t applyPPCHi(uint64_t V) { return V >> 16; }
+static uint16_t applyPPCHa(uint64_t V) { return (V + 0x8000) >> 16; }
+static uint16_t applyPPCHigher(uint64_t V) { return V >> 32; }
+static uint16_t applyPPCHighera(uint64_t V) { return (V + 0x8000) >> 32; }
+static uint16_t applyPPCHighest(uint64_t V) { return V >> 48; }
+static uint16_t applyPPCHighesta(uint64_t V) { return (V + 0x8000) >> 48; }
+
+PPC64TargetInfo::PPC64TargetInfo() {
+ PCRelReloc = R_PPC64_REL24;
+ GotReloc = R_PPC64_GLOB_DAT;
+ RelativeReloc = R_PPC64_RELATIVE;
+ PltEntrySize = 32;
+
+ // We need 64K pages (at least under glibc/Linux, the loader won't
+ // set different permissions on a finer granularity than that).
+ PageSize = 65536;
+
+ // The PPC64 ELF ABI v1 spec, says:
+ //
+ // It is normally desirable to put segments with different characteristics
+ // in separate 256 Mbyte portions of the address space, to give the
+ // operating system full paging flexibility in the 64-bit address space.
+ //
+ // And because the lowest non-zero 256M boundary is 0x10000000, PPC64 linkers
+ // use 0x10000000 as the starting address.
+ VAStart = 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.
+
+ // 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 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;
+}
+
+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 {
+ uint64_t Off = GotEntryAddr - getPPC64TocBase();
+
+ // FIXME: What we should do, in theory, is get the offset of the function
+ // descriptor in the .opd section, and use that as the offset from %r2 (the
+ // TOC-base pointer). Instead, we have the GOT-entry offset, and that will
+ // be a pointer to the function descriptor in the .opd section. Using
+ // this scheme is simpler, but requires an extra indirection per PLT dispatch.
+
+ write32be(Buf, 0xf8410028); // std %r2, 40(%r1)
+ write32be(Buf + 4, 0x3d620000 | applyPPCHa(Off)); // addis %r11, %r2, X@ha
+ write32be(Buf + 8, 0xe98b0000 | applyPPCLo(Off)); // ld %r12, X@l(%r11)
+ write32be(Buf + 12, 0xe96c0000); // ld %r11,0(%r12)
+ write32be(Buf + 16, 0x7d6903a6); // mtctr %r11
+ write32be(Buf + 20, 0xe84c0008); // ld %r2,8(%r12)
+ write32be(Buf + 24, 0xe96c0010); // ld %r11,16(%r12)
+ write32be(Buf + 28, 0x4e800420); // bctr
+}
+
+bool PPC64TargetInfo::relocNeedsGot(uint32_t Type, const SymbolBody &S) const {
+ if (relocNeedsPlt(Type, S))
+ return true;
+
+ 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;
+ }
+}
+
+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;
+ }
+
+ switch (Type) {
+ case R_PPC64_ADDR14: {
+ checkAlignment<4>(SA, Type);
+ // Preserve the AA/LK bits in the branch instruction
+ uint8_t AALK = Loc[3];
+ write16be(Loc + 2, (AALK & 3) | (SA & 0xfffc));
+ break;
+ }
+ case R_PPC64_ADDR16:
+ checkInt<16>(SA, Type);
+ write16be(Loc, SA);
+ break;
+ case R_PPC64_ADDR16_DS:
+ checkInt<16>(SA, Type);
+ write16be(Loc, (read16be(Loc) & 3) | (SA & ~3));
+ break;
+ case R_PPC64_ADDR16_HA:
+ write16be(Loc, applyPPCHa(SA));
+ break;
+ case R_PPC64_ADDR16_HI:
+ write16be(Loc, applyPPCHi(SA));
+ break;
+ case R_PPC64_ADDR16_HIGHER:
+ write16be(Loc, applyPPCHigher(SA));
+ break;
+ case R_PPC64_ADDR16_HIGHERA:
+ write16be(Loc, applyPPCHighera(SA));
+ break;
+ case R_PPC64_ADDR16_HIGHEST:
+ write16be(Loc, applyPPCHighest(SA));
+ break;
+ case R_PPC64_ADDR16_HIGHESTA:
+ write16be(Loc, applyPPCHighesta(SA));
+ break;
+ case R_PPC64_ADDR16_LO:
+ write16be(Loc, applyPPCLo(SA));
+ break;
+ case R_PPC64_ADDR16_LO_DS:
+ write16be(Loc, (read16be(Loc) & 3) | (applyPPCLo(SA) & ~3));
+ break;
+ case R_PPC64_ADDR32:
+ checkInt<32>(SA, Type);
+ write32be(Loc, SA);
+ 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));
+ 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)
+ 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));
+ }
+}
+
+AArch64TargetInfo::AArch64TargetInfo() {
+ CopyReloc = R_AARCH64_COPY;
+ GotReloc = R_AARCH64_GLOB_DAT;
+ PltReloc = R_AARCH64_JUMP_SLOT;
+ LazyRelocations = true;
+ PltEntrySize = 16;
+ PltZeroEntrySize = 32;
+}
+
+unsigned AArch64TargetInfo::getDynReloc(unsigned 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.");
+}
+
+unsigned AArch64TargetInfo::getPltRefReloc(unsigned Type) const { return Type; }
+
+void AArch64TargetInfo::writeGotPltEntry(uint8_t *Buf, uint64_t Plt) const {
+ write64le(Buf, Out<ELF64LE>::Plt->getVA());
+}
+
+void AArch64TargetInfo::writePltZeroEntry(uint8_t *Buf, uint64_t GotEntryAddr,
+ uint64_t PltEntryAddr) const {
+ const uint8_t PltData[] = {
+ 0xf0, 0x7b, 0xbf, 0xa9, // stp x16, x30, [sp,#-16]!
+ 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[2]))
+ 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[2]))]
+ 0x10, 0x02, 0x00, 0x91, // add x16, x16, Offset(&(.plt.got[2]))
+ 0x20, 0x02, 0x1f, 0xd6, // br x17
+ 0x1f, 0x20, 0x03, 0xd5, // nop
+ 0x1f, 0x20, 0x03, 0xd5, // nop
+ 0x1f, 0x20, 0x03, 0xd5 // nop
+ };
+ 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);
+}
+
+void AArch64TargetInfo::writePltEntry(uint8_t *Buf, uint64_t GotAddr,
+ 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]))]
+ 0x10, 0x02, 0x00, 0x91, // add x16, x16, Offset(&(.plt.got[n]))
+ 0x20, 0x02, 0x1f, 0xd6 // br x17
+ };
+ 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);
+}
+
+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 {
+ return Type == R_AARCH64_ADR_GOT_PAGE || Type == R_AARCH64_LD64_GOT_LO12_NC ||
+ relocNeedsPlt(Type, S);
+}
+
+bool AArch64TargetInfo::relocNeedsPlt(uint32_t Type,
+ const SymbolBody &S) const {
+ switch (Type) {
+ default:
+ return false;
+ case R_AARCH64_CALL26:
+ case R_AARCH64_JUMP26:
+ return canBePreempted(&S, true);
+ }
+}
+
+static void updateAArch64Adr(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);
+ 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));
+}
+
+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 {
+ switch (Type) {
+ case R_AARCH64_ABS16:
+ checkIntUInt<16>(SA, Type);
+ write16le(Loc, SA);
+ break;
+ case R_AARCH64_ABS32:
+ checkIntUInt<32>(SA, Type);
+ write32le(Loc, SA);
+ break;
+ case R_AARCH64_ABS64:
+ write64le(Loc, SA);
+ 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);
+ break;
+ }
+ case R_AARCH64_ADR_PREL_PG_HI21: {
+ uint64_t X = getAArch64Page(SA) - getAArch64Page(P);
+ checkInt<33>(X, Type);
+ updateAArch64Adr(Loc, (X >> 12) & 0x1FFFFF); // X[32:12]
+ break;
+ }
+ case R_AARCH64_CALL26:
+ case R_AARCH64_JUMP26: {
+ uint64_t X = SA - P;
+ checkInt<28>(X, Type);
+ or32le(Loc, (X & 0x0FFFFFFC) >> 2);
+ break;
+ }
+ case R_AARCH64_LD64_GOT_LO12_NC:
+ checkAlignment<8>(SA, Type);
+ or32le(Loc, (SA & 0xFF8) << 7);
+ break;
+ case R_AARCH64_LDST8_ABS_LO12_NC:
+ or32le(Loc, (SA & 0xFFF) << 10);
+ break;
+ case R_AARCH64_LDST32_ABS_LO12_NC:
+ or32le(Loc, (SA & 0xFFC) << 8);
+ break;
+ case R_AARCH64_LDST64_ABS_LO12_NC:
+ or32le(Loc, (SA & 0xFF8) << 7);
+ break;
+ case R_AARCH64_PREL16:
+ checkIntUInt<16>(SA - P, Type);
+ write16le(Loc, SA - P);
+ break;
+ case R_AARCH64_PREL32:
+ checkIntUInt<32>(SA - P, Type);
+ write32le(Loc, SA - P);
+ break;
+ case R_AARCH64_PREL64:
+ write64le(Loc, SA - P);
+ break;
+ default:
+ error("unrecognized reloc " + Twine(Type));
+ }
+}
+
+template <class ELFT> MipsTargetInfo<ELFT>::MipsTargetInfo() {
+ PageSize = 65536;
+ GotHeaderEntriesNum = 2;
+}
+
+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;
+}
+
+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 {}
+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 {}
+
+template <class ELFT>
+bool MipsTargetInfo<ELFT>::relocNeedsGot(uint32_t Type,
+ const SymbolBody &S) const {
+ return Type == R_MIPS_GOT16 || Type == R_MIPS_CALL16;
+}
+
+template <class ELFT>
+bool MipsTargetInfo<ELFT>::relocNeedsPlt(uint32_t Type,
+ const SymbolBody &S) const {
+ return false;
+}
+
+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);
+ 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));
+}
+
+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 {
+ const endianness E = ELFT::TargetEndianness;
+ switch (Type) {
+ 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:
+ 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));
+ }
+ 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);
+ break;
+ case R_MIPS_PC19_S2:
+ applyMipsPcReloc<E, 19>(Loc, Type, P, SA);
+ break;
+ case R_MIPS_PC21_S2:
+ applyMipsPcReloc<E, 21>(Loc, Type, P, SA);
+ 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));
+ }
+ 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));
+ break;
+ }
+ default:
+ error("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;
+ }
+}
+
+// _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
new file mode 100644
index 000000000000..52c2697dc60d
--- /dev/null
+++ b/ELF/Target.h
@@ -0,0 +1,117 @@
+//===- Target.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_TARGET_H
+#define LLD_ELF_TARGET_H
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Object/ELF.h"
+
+#include <memory>
+
+namespace lld {
+namespace elf2 {
+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 getPltRefReloc(unsigned Type) const;
+ 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;
+ virtual bool isRelRelative(uint32_t Type) const;
+ virtual bool isSizeDynReloc(uint32_t Type, const SymbolBody &S) 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 ~TargetInfo();
+
+protected:
+ unsigned PageSize = 4096;
+
+ // On freebsd x86_64 the first page cannot be mmaped.
+ // On linux that is controled by vm.mmap_min_addr. At least on some x86_64
+ // installs that is 65536, so the first 15 pages cannot be used.
+ // 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;
+ unsigned GotPltHeaderEntriesNum = 3;
+ bool LazyRelocations = false;
+};
+
+uint64_t getPPC64TocBase();
+
+template <class ELFT>
+typename llvm::object::ELFFile<ELFT>::uintX_t getMipsGpAddr();
+
+template <class ELFT> bool isGnuIFunc(const SymbolBody &S);
+
+extern std::unique_ptr<TargetInfo> Target;
+TargetInfo *createTarget();
+}
+}
+
+#endif
diff --git a/ELF/Writer.cpp b/ELF/Writer.cpp
new file mode 100644
index 000000000000..bdcb720a8a48
--- /dev/null
+++ b/ELF/Writer.cpp
@@ -0,0 +1,1282 @@
+//===- Writer.cpp ---------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Writer.h"
+#include "Config.h"
+#include "OutputSections.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"
+
+using namespace llvm;
+using namespace llvm::ELF;
+using namespace llvm::object;
+
+using namespace lld;
+using namespace lld::elf2;
+
+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;
+ Writer(SymbolTable<ELFT> &S) : Symtab(S) {}
+ void run();
+
+private:
+ void copyLocalSymbols();
+ void addReservedSymbols();
+ void createSections();
+ void addPredefinedSections();
+
+ 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 assignAddresses();
+ void buildSectionMap();
+ void fixAbsoluteSymbols();
+ void openFile(StringRef OutputPath);
+ void writeHeader();
+ void writeSections();
+ bool isDiscarded(InputSectionBase<ELFT> *IS) const;
+ StringRef getOutputSectionName(StringRef S) const;
+ bool needsInterpSection() const {
+ return !Symtab.getSharedFiles().empty() && !Config->DynamicLinker.empty();
+ }
+ bool isOutputDynamic() const {
+ return !Symtab.getSharedFiles().empty() || Config->Shared;
+ }
+ 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;
+
+ 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;
+
+ uintX_t FileSize;
+ uintX_t SectionHeaderOff;
+
+ llvm::StringMap<llvm::StringRef> InputToOutputSection;
+};
+} // anonymous namespace
+
+template <class ELFT> static bool shouldUseRela() {
+ ELFKind K = cast<ELFFileBase<ELFT>>(Config->FirstElf)->getELFKind();
+ return K == ELF64LEKind || K == ELF64BEKind;
+}
+
+template <class ELFT> void lld::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;
+ GotSection<ELFT> Got;
+ Out<ELFT>::Got = &Got;
+ GotPltSection<ELFT> GotPlt;
+ if (Target->supportsLazyRelocations())
+ Out<ELFT>::GotPlt = &GotPlt;
+ PltSection<ELFT> Plt;
+ Out<ELFT>::Plt = &Plt;
+ std::unique_ptr<SymbolTableSection<ELFT>> SymTab;
+ if (!Config->StripAll) {
+ SymTab.reset(new SymbolTableSection<ELFT>(*Symtab, *Out<ELFT>::StrTab));
+ Out<ELFT>::SymTab = SymTab.get();
+ }
+ SymbolTableSection<ELFT> DynSymTab(*Symtab, *Out<ELFT>::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;
+
+ 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());
+}
+
+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;
+ }
+};
+}
+
+// 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;
+
+ 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});
+ }
+
+ 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);
+ }
+ }
+ }
+
+ // 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;
+ }
+
+ if (Config->EMachine == EM_MIPS && 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;
+ }
+ bool CBP = canBePreempted(Body, NeedsGot);
+ if (!CBP && (!Config->Shared || Target->isRelRelative(Type)))
+ continue;
+ if (CBP)
+ Body->setUsedInDynamicReloc();
+ if (NeedsPlt && Target->supportsLazyRelocations())
+ Out<ELFT>::RelaPlt->addReloc({&C, &RI});
+ else
+ Out<ELFT>::RelaDyn->addReloc({&C, &RI});
+ }
+}
+
+template <class ELFT> void Writer<ELFT>::scanRelocs(InputSection<ELFT> &C) {
+ if (!(C.getSectionHdr()->sh_flags & SHF_ALLOC))
+ return;
+
+ for (const Elf_Shdr *RelSec : C.RelocSections)
+ scanRelocs(C, *RelSec);
+}
+
+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));
+}
+
+template <class ELFT>
+static void reportUndefined(const SymbolTable<ELFT> &S, const SymbolBody &Sym) {
+ if (Config->Shared && !Config->NoUndefined)
+ return;
+
+ ELFFileBase<ELFT> *SymFile = findFile<ELFT>(S.getObjectFiles(), &Sym);
+ std::string Message = "undefined symbol: " + Sym.getName().str();
+ if (SymFile)
+ Message += " in " + SymFile->getName().str();
+ if (Config->NoInhibitExec)
+ warning(Message);
+ else
+ error(Message);
+}
+
+// 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))
+ continue;
+ if (Out<ELFT>::SymTab)
+ Out<ELFT>::SymTab->addLocalSymbol(SymName);
+ }
+ }
+}
+
+// PPC64 has a number of special SHT_PROGBITS+SHF_ALLOC+SHF_WRITE sections that
+// we would like to make sure appear is a specific order to maximize their
+// coverage by a single signed 16-bit offset from the TOC base pointer.
+// Conversely, the special .tocbss section should be first among all SHT_NOBITS
+// sections. This will put it next to the loaded special PPC64 sections (and,
+// 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);
+}
+
+template <class ELFT> static bool isRelroSection(OutputSectionBase<ELFT> *Sec) {
+ typename OutputSectionBase<ELFT>::uintX_t Flags = Sec->getFlags();
+ if (!(Flags & SHF_ALLOC) || !(Flags & SHF_WRITE))
+ return false;
+ if (Flags & SHF_TLS)
+ return true;
+ uint32_t Type = Sec->getType();
+ if (Type == SHT_INIT_ARRAY || Type == SHT_FINI_ARRAY ||
+ Type == SHT_PREINIT_ARRAY)
+ return true;
+ if (Sec == Out<ELFT>::GotPlt)
+ return Config->ZNow;
+ if (Sec == Out<ELFT>::Dynamic || Sec == Out<ELFT>::Got)
+ return true;
+ StringRef S = Sec->getName();
+ return S == ".data.rel.ro" || S == ".ctors" || S == ".dtors" || S == ".jcr" ||
+ S == ".eh_frame";
+}
+
+// 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;
+
+ uintX_t AFlags = A->getFlags();
+ uintX_t BFlags = B->getFlags();
+
+ // Allocatable sections go first to reduce the total PT_LOAD size and
+ // so debug info doesn't change addresses in actual code.
+ bool AIsAlloc = AFlags & SHF_ALLOC;
+ bool BIsAlloc = BFlags & SHF_ALLOC;
+ if (AIsAlloc != BIsAlloc)
+ return AIsAlloc;
+
+ // We don't have any special requirements for the relative order of
+ // two non allocatable sections.
+ if (!AIsAlloc)
+ return false;
+
+ // We want the read only sections first so that they go in the PT_LOAD
+ // covering the program headers at the start of the file.
+ bool AIsWritable = AFlags & SHF_WRITE;
+ bool BIsWritable = BFlags & SHF_WRITE;
+ if (AIsWritable != BIsWritable)
+ return BIsWritable;
+
+ // For a corresponding reason, put non exec sections first (the program
+ // header PT_LOAD is not executable).
+ bool AIsExec = AFlags & SHF_EXECINSTR;
+ bool BIsExec = BFlags & SHF_EXECINSTR;
+ if (AIsExec != BIsExec)
+ return BIsExec;
+
+ // If we got here we know that both A and B are in the same PT_LOAD.
+
+ // The TLS initialization block needs to be a single contiguous block in a R/W
+ // PT_LOAD, so stick TLS sections directly before R/W sections. The TLS NOBITS
+ // sections are placed here as they don't take up virtual address space in the
+ // PT_LOAD.
+ bool AIsTls = AFlags & SHF_TLS;
+ bool BIsTls = BFlags & SHF_TLS;
+ if (AIsTls != BIsTls)
+ return AIsTls;
+
+ // The next requirement we have is to put nobits sections last. The
+ // reason is that the only thing the dynamic linker will see about
+ // them is a p_memsz that is larger than p_filesz. Seeing that it
+ // zeros the end of the PT_LOAD, so that has to correspond to the
+ // nobits sections.
+ bool AIsNoBits = A->getType() == SHT_NOBITS;
+ bool BIsNoBits = B->getType() == SHT_NOBITS;
+ if (AIsNoBits != BIsNoBits)
+ return BIsNoBits;
+
+ // We place RelRo section before plain r/w ones.
+ bool AIsRelRo = isRelroSection(A);
+ bool BIsRelRo = isRelroSection(B);
+ if (AIsRelRo != BIsRelRo)
+ return AIsRelRo;
+
+ // Some architectures have additional ordering restrictions for sections
+ // within the same PT_LOAD.
+ if (Config->EMachine == EM_PPC64)
+ return getPPC64SectionRank(A->getName()) <
+ getPPC64SectionRank(B->getName());
+
+ 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>
+void Writer<ELFT>::addCommonSymbols(std::vector<DefinedCommon *> &Syms) {
+ typedef typename ELFFile<ELFT>::uintX_t uintX_t;
+
+ if (Syms.empty())
+ return;
+
+ // 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;
+ });
+
+ uintX_t Off = getBSS()->getSize();
+ for (DefinedCommon *C : Syms) {
+ uintX_t Align = C->MaxAlignment;
+ Off = RoundUpToAlignment(Off, Align);
+ C->OffsetInBSS = Off;
+ Off += C->Size;
+ }
+
+ 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 = RoundUpToAlignment(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;
+}
+
+// The beginning and the ending of .rel[a].plt section are marked
+// with __rel[a]_iplt_{start,end} symbols if it is a statically linked
+// executable. The runtime needs these symbols in order to resolve
+// 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() {
+ 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>::IgnoreUndef)
+ return false;
+
+ 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);
+ OutputSectionBase<ELFT> *createAux(InputSectionBase<ELFT> *C,
+ const SectionKey<ELFT::Is64Bits> &Key);
+
+ 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};
+ Sec = createAux(C, Key);
+ return {Sec, true};
+}
+
+template <class ELFT>
+OutputSectionBase<ELFT> *
+OutputSectionFactory<ELFT>::createAux(InputSectionBase<ELFT> *C,
+ const SectionKey<ELFT::Is64Bits> &Key) {
+ switch (C->SectionKind) {
+ case InputSectionBase<ELFT>::Regular:
+ return new OutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
+ case InputSectionBase<ELFT>::EHFrame:
+ return new EHOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
+ case InputSectionBase<ELFT>::Merge:
+ return new MergeOutputSection<ELFT>(Key.Name, Key.Type, Key.Flags);
+ case InputSectionBase<ELFT>::MipsReginfo:
+ return new MipsReginfoOutputSection<ELFT>();
+ }
+ llvm_unreachable("Unknown output section type");
+}
+
+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};
+}
+
+// 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() {
+ // __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
+ // to avoid the undefined symbol error.
+ 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);
+}
+
+// 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 (InputSectionBase<ELFT> *C : F->getSections()) {
+ if (isDiscarded(C)) {
+ reportDiscarded(C, F);
+ continue;
+ }
+ OutputSectionBase<ELFT> *Sec;
+ bool IsNew;
+ std::tie(Sec, IsNew) =
+ Factory.create(C, getOutputSectionName(C->getSectionName()));
+ if (IsNew) {
+ OwningSections.emplace_back(Sec);
+ OutputSections.push_back(Sec);
+ RegularSections.push_back(Sec);
+ }
+ Sec->addSection(C);
+ }
+ }
+
+ 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.
+ Out<ELFT>::Opd = Factory.lookup(".opd", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC);
+
+ Out<ELFT>::Dynamic->PreInitArraySec = Factory.lookup(
+ ".preinit_array", SHT_PREINIT_ARRAY, SHF_WRITE | SHF_ALLOC);
+ Out<ELFT>::Dynamic->InitArraySec =
+ Factory.lookup(".init_array", SHT_INIT_ARRAY, SHF_WRITE | SHF_ALLOC);
+ Out<ELFT>::Dynamic->FiniArraySec =
+ Factory.lookup(".fini_array", SHT_FINI_ARRAY, 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);
+
+ // 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 (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 (S->RelocSection)
+ scanRelocs(*S, *S->RelocSection);
+ }
+ }
+
+ // Define __rel[a]_iplt_{start,end} symbols if needed.
+ addRelIpltSymbols();
+
+ // 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);
+
+ 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))
+ Out<ELFT>::DynSymTab->addSymbol(Body);
+ }
+ addCommonSymbols(CommonSymbols);
+ addCopyRelSymbols(CopyRelSymbols);
+
+ // So far we have added sections from input object files.
+ // This function adds linker-created Out<ELFT>::* sections.
+ addPredefinedSections();
+
+ 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]));
+ }
+
+ for (OutputSectionBase<ELFT> *Sec : OutputSections)
+ Out<ELFT>::ShStrTab->add(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();
+ if (isOutputDynamic())
+ Out<ELFT>::DynSymTab->finalize();
+
+ // Fill other section headers.
+ for (OutputSectionBase<ELFT> *Sec : OutputSections)
+ Sec->finalize();
+}
+
+// This function add Out<ELFT>::* sections to OutputSections.
+template <class ELFT> void Writer<ELFT>::addPredefinedSections() {
+ auto Add = [&](OutputSectionBase<ELFT> *C) {
+ if (C)
+ OutputSections.push_back(C);
+ };
+
+ // This order is not the same as the final output order
+ // because we sort the sections using their attributes below.
+ Add(Out<ELFT>::SymTab);
+ Add(Out<ELFT>::ShStrTab);
+ Add(Out<ELFT>::StrTab);
+ if (isOutputDynamic()) {
+ Add(Out<ELFT>::DynSymTab);
+ 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);
+ }
+ }
+
+ // We always need to add rel[a].plt to output if it has entries.
+ // Even during static linking it can contain R_[*]_IRELATIVE relocations.
+ if (Out<ELFT>::RelaPlt && Out<ELFT>::RelaPlt->hasRelocs()) {
+ Add(Out<ELFT>::RelaPlt);
+ 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)
+ 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);
+}
+
+// The linker is expected to define SECNAME_start and SECNAME_end
+// symbols for a few sections. This function defines them.
+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());
+ } else {
+ Symtab.addIgnored(Start);
+ Symtab.addIgnored(End);
+ }
+ };
+
+ Define("__preinit_array_start", "__preinit_array_end",
+ Out<ELFT>::Dynamic->PreInitArraySec);
+ Define("__init_array_start", "__init_array_end",
+ Out<ELFT>::Dynamic->InitArraySec);
+ Define("__fini_array_start", "__fini_array_end",
+ 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,
+// respectively. This is not requested by the ELF standard, but GNU ld and
+// gold provide the feature, and used by many programs.
+template <class ELFT>
+void Writer<ELFT>::addStartStopSymbols(OutputSectionBase<ELFT> *Sec) {
+ StringRef S = Sec->getName();
+ if (!isValidCIdentifier(S))
+ return;
+ StringSaver Saver(Alloc);
+ StringRef Start = Saver.save("__start_" + S);
+ StringRef Stop = Saver.save("__stop_" + S);
+ if (Symtab.isUndefined(Start))
+ Symtab.addSynthetic(Start, *Sec, 0);
+ if (Symtab.isUndefined(Stop))
+ Symtab.addSynthetic(Stop, *Sec, Sec->getSize());
+}
+
+template <class ELFT> static bool needsPhdr(OutputSectionBase<ELFT> *Sec) {
+ return Sec->getFlags() & SHF_ALLOC;
+}
+
+static uint32_t toPhdrFlags(uint64_t Flags) {
+ uint32_t Ret = PF_R;
+ if (Flags & SHF_WRITE)
+ Ret |= PF_W;
+ if (Flags & SHF_EXECINSTR)
+ Ret |= PF_X;
+ return Ret;
+}
+
+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);
+
+ // 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();
+
+ // 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;
+
+ // PT_INTERP must be the second entry if exists.
+ int PhdrIdx = 0;
+ Elf_Phdr *Interp = nullptr;
+ if (needsInterpSection())
+ Interp = &Phdrs[++PhdrIdx];
+
+ // 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.
+ 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 = RoundUpToAlignment(VA, Target->getPageSize());
+ FileOff = RoundUpToAlignment(FileOff, Target->getPageSize());
+ if (FirstNonRelRo)
+ RelroAligned = true;
+ }
+
+ if (PH->p_flags != Flags) {
+ // Flags changed. Create a new PT_LOAD.
+ PH = &Phdrs[++PhdrIdx];
+ setPhdr(PH, PT_LOAD, Flags, FileOff, VA, 0, Target->getPageSize());
+ }
+
+ 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 = RoundUpToAlignment(VA, Sec->getAlign());
+ uintX_t TVA = RoundUpToAlignment(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 = RoundUpToAlignment(VA, Sec->getAlign());
+ Sec->setVA(VA);
+ VA += Sec->getSize();
+ if (InRelRo)
+ updateRelro(PH, &GnuRelroPhdr, VA);
+ }
+ }
+
+ FileOff = RoundUpToAlignment(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 (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 = RoundUpToAlignment(TlsPhdr.p_memsz, TlsPhdr.p_align);
+ Phdrs[++PhdrIdx] = TlsPhdr;
+ Out<ELFT>::TlsPhdr = &Phdrs[PhdrIdx];
+ }
+
+ // Add an entry for .dynamic.
+ if (isOutputDynamic()) {
+ Elf_Phdr *PH = &Phdrs[++PhdrIdx];
+ PH->p_type = PT_DYNAMIC;
+ copyPhdr(PH, Out<ELFT>::Dynamic);
+ }
+
+ if (HasRelro) {
+ Elf_Phdr *PH = &Phdrs[++PhdrIdx];
+ *PH = GnuRelroPhdr;
+ }
+
+ // 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;
+ }
+
+ // 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);
+ }
+
+ // Add space for section headers.
+ SectionHeaderOff = RoundUpToAlignment(FileOff, ELFT::Is64Bits ? 8 : 4);
+ FileSize = SectionHeaderOff + getNumSections() * sizeof(Elf_Shdr);
+
+ // Update "_end" and "end" symbols so that they
+ // point to the end of the data segment.
+ ElfSym<ELFT>::End.st_value = VA;
+}
+
+// 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;
+ }
+ }
+ if (Tls)
+ ++I;
+ if (HasRelro)
+ ++I;
+ return I;
+}
+
+static uint32_t getELFFlags() {
+ if (Config->EMachine != EM_MIPS)
+ return 0;
+ // FIXME: In fact ELF flags depends on ELF flags of input object files
+ // and selected emulation. For now just use hadr coded values.
+ uint32_t V = EF_MIPS_ABI_O32 | EF_MIPS_CPIC | 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;
+ }
+ if (Config->EntryAddr != uint64_t(-1))
+ return Config->EntryAddr;
+ return 0;
+}
+
+// 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();
+ }
+
+ // 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>();
+}
+
+template <class ELFT> void Writer<ELFT>::writeHeader() {
+ uint8_t *Buf = Buffer->getBufferStart();
+ memcpy(Buf, "\177ELF", 4);
+
+ // 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_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_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_shstrndx = Out<ELFT>::ShStrTab->SectionIndex;
+
+ // Write the program header table.
+ memcpy(Buf + EHdr->e_phoff, &Phdrs[0], Phdrs.size() * sizeof(Phdrs[0]));
+
+ // Write the section header table. Note that the first table entry is null.
+ 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) {
+ ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
+ FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable);
+ error(BufferOrErr, "failed to open " + Path);
+ Buffer = std::move(*BufferOrErr);
+}
+
+// Write section contents to a mmap'ed file.
+template <class ELFT> void Writer<ELFT>::writeSections() {
+ uint8_t *Buf = Buffer->getBufferStart();
+
+ // PPC64 needs to process relocations in the .opd section before processing
+ // relocations in code-containing sections.
+ if (OutputSectionBase<ELFT> *Sec = Out<ELFT>::Opd) {
+ Out<ELFT>::OpdBuf = Buf + Sec->getFileOff();
+ Sec->writeTo(Buf + Sec->getFileOff());
+ }
+
+ for (OutputSectionBase<ELFT> *Sec : OutputSections)
+ if (Sec != Out<ELFT>::Opd)
+ 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>::buildSectionMap() {
+ for (const std::pair<StringRef, std::vector<StringRef>> &OutSec :
+ Config->OutputSections)
+ for (StringRef Name : OutSec.second)
+ InputToOutputSection[Name] = OutSec.first;
+}
+
+template void lld::elf2::writeResult<ELF32LE>(SymbolTable<ELF32LE> *Symtab);
+template void lld::elf2::writeResult<ELF32BE>(SymbolTable<ELF32BE> *Symtab);
+template void lld::elf2::writeResult<ELF64LE>(SymbolTable<ELF64LE> *Symtab);
+template void lld::elf2::writeResult<ELF64BE>(SymbolTable<ELF64BE> *Symtab);
diff --git a/ELF/Writer.h b/ELF/Writer.h
new file mode 100644
index 000000000000..40a1711e2bd2
--- /dev/null
+++ b/ELF/Writer.h
@@ -0,0 +1,24 @@
+//===- Writer.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_WRITER_H
+#define LLD_ELF_WRITER_H
+
+namespace lld {
+namespace elf2 {
+
+template <class ELFT> class SymbolTable;
+
+template <class ELFT> void writeResult(SymbolTable<ELFT> *Symtab);
+
+template <class ELFT> void markLive(SymbolTable<ELFT> *Symtab);
+}
+}
+
+#endif
diff --git a/Makefile b/Makefile
deleted file mode 100644
index e1b6a678fc23..000000000000
--- a/Makefile
+++ /dev/null
@@ -1,86 +0,0 @@
-##===- Makefile --------------------------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-# If LLD_LEVEL is not set, then we are the top-level Makefile. Otherwise, we
-# are being included from a subdirectory makefile.
-
-ifndef LLD_LEVEL
-
-IS_TOP_LEVEL := 1
-LLD_LEVEL := .
-DIRS := include lib tools unittests
-
-PARALLEL_DIRS :=
-
-endif
-
-ifeq ($(MAKECMDGOALS),libs-only)
- DIRS := $(filter-out tools docs, $(DIRS))
- OPTIONAL_DIRS :=
-endif
-ifeq ($(BUILD_LLD_ONLY),YES)
- DIRS := $(filter-out docs unittests, $(DIRS))
- OPTIONAL_DIRS :=
-endif
-
-###
-# Common Makefile code, shared by all lld Makefiles.
-
-# Set LLVM source root level.
-LEVEL := $(LLD_LEVEL)/../..
-
-# Include LLVM common makefile.
-include $(LEVEL)/Makefile.common
-
-ifneq ($(ENABLE_DOCS),1)
- DIRS := $(filter-out docs, $(DIRS))
-endif
-
-CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/include
-CPP.Flags += -I$(PROJ_OBJ_DIR)/$(LLD_LEVEL)/include
-
-###
-# lld Top Level specific stuff.
-
-ifeq ($(IS_TOP_LEVEL),1)
-
-ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT))
-$(RecursiveTargets)::
- $(Verb) for dir in test unittests; do \
- if [ -f $(PROJ_SRC_DIR)/$${dir}/Makefile ] && [ ! -f $${dir}/Makefile ]; then \
- $(MKDIR) $${dir}; \
- $(CP) $(PROJ_SRC_DIR)/$${dir}/Makefile $${dir}/Makefile; \
- fi \
- done
-endif
-
-test::
- @ $(MAKE) -C test
-
-report::
- @ $(MAKE) -C test report
-
-clean::
- @ $(MAKE) -C test clean
-
-libs-only: all
-
-tags::
- $(Verb) etags `find . -type f -name '*.h' -or -name '*.cpp' | \
- grep -v /lib/Headers | grep -v /test/`
-
-cscope.files:
- find tools lib include -name '*.cpp' \
- -or -name '*.def' \
- -or -name '*.td' \
- -or -name '*.h' > cscope.files
-
-.PHONY: test report clean cscope.files
-
-endif
diff --git a/docs/Makefile b/docs/Makefile
deleted file mode 100644
index 4c147eb11137..000000000000
--- a/docs/Makefile
+++ /dev/null
@@ -1,155 +0,0 @@
-# Makefile for Sphinx documentation
-#
-
-# You can set these variables from the command line.
-SPHINXOPTS =
-SPHINXBUILD = sphinx-build
-PAPER =
-BUILDDIR = _build
-
-# Internal variables.
-PAPEROPT_a4 = -D latex_paper_size=a4
-PAPEROPT_letter = -D latex_paper_size=letter
-ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-# the i18n builder cannot share the environment and doctrees with the others
-I18NSPHINXOPTS = $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
-
-.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest gettext
-
-all: html
-
-help:
- @echo "Please use \`make <target>' where <target> is one of"
- @echo " html to make standalone HTML files"
- @echo " dirhtml to make HTML files named index.html in directories"
- @echo " singlehtml to make a single large HTML file"
- @echo " pickle to make pickle files"
- @echo " json to make JSON files"
- @echo " htmlhelp to make HTML files and a HTML help project"
- @echo " qthelp to make HTML files and a qthelp project"
- @echo " devhelp to make HTML files and a Devhelp project"
- @echo " epub to make an epub"
- @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
- @echo " latexpdf to make LaTeX files and run them through pdflatex"
- @echo " text to make text files"
- @echo " man to make manual pages"
- @echo " texinfo to make Texinfo files"
- @echo " info to make Texinfo files and run them through makeinfo"
- @echo " gettext to make PO message catalogs"
- @echo " changes to make an overview of all changed/added/deprecated items"
- @echo " linkcheck to check all external links for integrity"
- @echo " doctest to run all doctests embedded in the documentation (if enabled)"
-
-clean:
- -rm -rf $(BUILDDIR)/*
-
-html:
- $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
-
-dirhtml:
- $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
- @echo
- @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
-
-singlehtml:
- $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
- @echo
- @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
-
-pickle:
- $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
- @echo
- @echo "Build finished; now you can process the pickle files."
-
-json:
- $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
- @echo
- @echo "Build finished; now you can process the JSON files."
-
-htmlhelp:
- $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
- @echo
- @echo "Build finished; now you can run HTML Help Workshop with the" \
- ".hhp project file in $(BUILDDIR)/htmlhelp."
-
-qthelp:
- $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
- @echo
- @echo "Build finished; now you can run "qcollectiongenerator" with the" \
- ".qhcp project file in $(BUILDDIR)/qthelp, like this:"
- @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/lld.qhcp"
- @echo "To view the help file:"
- @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/lld.qhc"
-
-devhelp:
- $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
- @echo
- @echo "Build finished."
- @echo "To view the help file:"
- @echo "# mkdir -p $$HOME/.local/share/devhelp/lld"
- @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/lld"
- @echo "# devhelp"
-
-epub:
- $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
- @echo
- @echo "Build finished. The epub file is in $(BUILDDIR)/epub."
-
-latex:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo
- @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
- @echo "Run \`make' in that directory to run these through (pdf)latex" \
- "(use \`make latexpdf' here to do that automatically)."
-
-latexpdf:
- $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
- @echo "Running LaTeX files through pdflatex..."
- $(MAKE) -C $(BUILDDIR)/latex all-pdf
- @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
-
-text:
- $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
- @echo
- @echo "Build finished. The text files are in $(BUILDDIR)/text."
-
-man:
- $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
- @echo
- @echo "Build finished. The manual pages are in $(BUILDDIR)/man."
-
-texinfo:
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
- @echo
- @echo "Build finished. The Texinfo files are in $(BUILDDIR)/texinfo."
- @echo "Run \`make' in that directory to run these through makeinfo" \
- "(use \`make info' here to do that automatically)."
-
-info:
- $(SPHINXBUILD) -b texinfo $(ALLSPHINXOPTS) $(BUILDDIR)/texinfo
- @echo "Running Texinfo files through makeinfo..."
- make -C $(BUILDDIR)/texinfo info
- @echo "makeinfo finished; the Info files are in $(BUILDDIR)/texinfo."
-
-gettext:
- $(SPHINXBUILD) -b gettext $(I18NSPHINXOPTS) $(BUILDDIR)/locale
- @echo
- @echo "Build finished. The message catalogs are in $(BUILDDIR)/locale."
-
-changes:
- $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
- @echo
- @echo "The overview file is in $(BUILDDIR)/changes."
-
-linkcheck:
- $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
- @echo
- @echo "Link check complete; look for any errors in the above output " \
- "or in $(BUILDDIR)/linkcheck/output.txt."
-
-doctest:
- $(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
- @echo "Testing of doctests in the sources finished, look at the " \
- "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/docs/Readers.rst b/docs/Readers.rst
index e00406b8c4ce..f9499635b72c 100644
--- a/docs/Readers.rst
+++ b/docs/Readers.rst
@@ -52,10 +52,9 @@ Where to start
--------------
The lld project already has a skeleton of source code for Readers for
-``ELF``, ``PECOFF``, ``MachO``, and lld's native Atom graph format
-(both binary ``Native`` and ``YAML`` representations). If your file format
-is a variant of one of those, you should modify the existing Reader to
-support your variant. This is done by customizing the Options
+``ELF``, ``PECOFF``, ``MachO``, and lld's native ``YAML`` graph format.
+If your file format is a variant of one of those, you should modify the
+existing Reader to support your variant. This is done by customizing the Options
class for the Reader and making appropriate changes to the ``.cpp`` file to
interpret those options and act accordingly.
diff --git a/docs/design.rst b/docs/design.rst
index 06d356527f58..408b8acaf890 100644
--- a/docs/design.rst
+++ b/docs/design.rst
@@ -300,60 +300,13 @@ and the ivars programmatically set.
lld::File representations
-------------------------
-Just as LLVM has three representations of its IR model, lld has three
+Just as LLVM has three representations of its IR model, lld has two
representations of its File/Atom/Reference model:
* In memory, abstract C++ classes (lld::Atom, lld::Reference, and lld::File).
* textual (in YAML)
- * binary format ("native")
-
-Binary File Format
-~~~~~~~~~~~~~~~~~~
-
-In theory, lld::File objects could be written to disk in an existing Object File
-format standard (e.g. ELF). Instead we choose to define a new binary file
-format. There are two main reasons for this: fidelity and performance. In order
-for lld to work as a linker on all platforms, its internal model must be rich
-enough to model all CPU and OS linking features. But if we choose an existing
-Object File format as the lld binary format, that means an on going need to
-retrofit each platform specific feature needed from alternate platforms into the
-existing Object File format. Having our own "native" binary format side steps
-that issue. We still need to be able to binary encode all the features, but
-once the in-memory model can represent the feature, it is straight forward to
-binary encode it.
-
-The reason to use a binary file format at all, instead of a textual file format,
-is speed. You want the binary format to be as fast as possible to read into the
-in-memory model. Given that we control the in-memory model and the binary
-format, the obvious way to make reading super fast it to make the file format be
-basically just an array of atoms. The reader just mmaps in the file and looks
-at the header to see how many atoms there are and instantiate that many atom
-objects with the atom attribute information coming from that array. The trick
-is designing this in a way that can be extended as the Atom mode evolves and new
-attributes are added.
-
-The native object file format starts with a header that lists how many "chunks"
-are in the file. A chunk is an array of "ivar data". The native file reader
-instantiates an array of Atom objects (with one large malloc call). Each atom
-contains just a pointer to its vtable and a pointer to its ivar data. All
-methods on lld::Atom are virtual, so all the method implementations return
-values based on the ivar data to which it has a pointer. If a new linking
-features is added which requires a change to the lld::Atom model, a new native
-reader class (e.g. version 2) is defined which knows how to read the new feature
-information from the new ivar data. The old reader class (e.g. version 1) is
-updated to do its best to model (the lack of the new feature) given the old ivar
-data in existing native object files.
-
-With this model for the native file format, files can be read and turned
-into the in-memory graph of lld::Atoms with just a few memory allocations.
-And the format can easily adapt over time to new features.
-
-The binary file format follows the ReaderWriter patterns used in lld. The lld
-library comes with the classes: ReaderNative and WriterNative. So, switching
-between file formats is as easy as switching which Reader subclass is used.
-
Textual representations in YAML
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -406,11 +359,7 @@ test is a text file with comments telling lit how to run the test and check the
result To facilitate testing, the lld project builds a tool called lld-core.
This tool reads a YAML file (default from stdin), parses it into one or more
lld::File objects in memory and then feeds those lld::File objects to the
-resolver phase. The output of the resolver is written as a native object file.
-It is then read back in using the native object file reader and then pass to the
-YAML writer. This round-about path means that all three representations
-(in-memory, binary, and text) are exercised, and any new feature has to work in
-all the representations to pass the test.
+resolver phase.
Resolver testing
diff --git a/docs/getting_started.rst b/docs/getting_started.rst
index 986a406c1cb7..4b0e44e63a11 100644
--- a/docs/getting_started.rst
+++ b/docs/getting_started.rst
@@ -56,7 +56,7 @@ On Unix-like Systems
5. Test::
- $ make lld-test
+ $ make check-lld
Using Visual Studio
~~~~~~~~~~~~~~~~~~~
@@ -64,7 +64,7 @@ Using Visual Studio
#. Get the required tools.
* `CMake 2.8`_\+.
- * `Visual Studio 11 (2012) or later`_ (required for C++11 support)
+ * `Visual Studio 12 (2013) or later`_ (required for C++11 support)
* `Python 2.4`_\+ (not 3.x) for running tests.
.. _CMake 2.8: http://www.cmake.org/cmake/resources/software.html
diff --git a/docs/index.rst b/docs/index.rst
index 7a87ad8d0583..88c6f217531a 100644
--- a/docs/index.rst
+++ b/docs/index.rst
@@ -3,15 +3,18 @@
lld - The LLVM Linker
=====================
-lld is a new set of modular code for creating linker tools.
+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)
- * Fast link times
- * Minimal memory use
* Remove clang's reliance on "the system linker"
* Uses the LLVM `"UIUC" BSD-Style license`__.
@@ -26,8 +29,6 @@ lld is a new set of modular code for creating linker tools.
* Extensive unit tests
* Internal linker model can be dumped/read to textual format
- * Internal linker model can be dumped/read to a new native format
- * Native format designed to be fast to read and write
* Additional linking features can be plugged in as "passes"
* OS specific and CPU specific code factored out
diff --git a/docs/open_projects.rst b/docs/open_projects.rst
index eb146c8b7542..448e967b5536 100644
--- a/docs/open_projects.rst
+++ b/docs/open_projects.rst
@@ -4,7 +4,6 @@ Open Projects
=============
.. include:: ../include/lld/Core/TODO.txt
-.. include:: ../lib/Core/TODO.txt
.. include:: ../lib/Driver/TODO.rst
.. include:: ../lib/ReaderWriter/ELF/X86_64/TODO.rst
.. include:: ../lib/ReaderWriter/ELF/AArch64/TODO.rst
diff --git a/docs/windows_support.rst b/docs/windows_support.rst
index d9906a72ea1e..c4c338a0fba1 100644
--- a/docs/windows_support.rst
+++ b/docs/windows_support.rst
@@ -14,14 +14,14 @@
Windows support
===============
-LLD has some experimental Windows support. When invoked as ``link.exe`` or with
+LLD supports Windows operating system. When invoked as ``lld-link.exe`` or with
``-flavor link``, the driver for Windows operating system is used to parse
command line options, and it drives further linking processes. LLD accepts
almost all command line options that the linker shipped with Microsoft Visual
C++ (link.exe) supports.
-The current status is that LLD can link itself on Windows x86 using Visual C++
-2012 or 2013 as the compiler.
+The current status is that LLD can link itself on Windows x86/x64
+using Visual C++ 2013 as the compiler.
Development status
==================
@@ -55,17 +55,12 @@ Windows resource files support
COFF object file section. Both tools are shipped with MSVC.
Safe Structured Exception Handler (SEH)
- :good:`Done` for x86. :partial:`Work in progress` for x64.
+ :good:`Done` for both x86 and x64.
Module-definition file
:partial:`Partially done`. LLD currently recognizes these directives:
``EXPORTS``, ``HEAPSIZE``, ``STACKSIZE``, ``NAME``, and ``VERSION``.
-x64 (x86-64)
- :partial:`Work in progress`. LLD can create PE32+ executable but the generated
- file does not work unless source object files are very simple because of the
- lack of SEH handler table.
-
Debug info
:none:`No progress has been made`. Microsoft linker can interpret the CodeGen
debug info (old-style debug info) and PDB to emit an .pdb file. LLD doesn't
@@ -86,7 +81,7 @@ Using Visual Studio IDE/MSBuild
Alternatively, you can use msbuild if you don't like to work in an IDE::
msbuild LLVM.sln /m /target:"lld executables\lld"
-
+
MSBuild.exe had been shipped as a component of the .NET framework, but since
2013 it's part of Visual Studio. You can find it at "C:\\Program Files
(x86)\\msbuild".
@@ -100,19 +95,3 @@ Using Ninja
1. Check out LLVM and LLD from the LLVM SVN repository (or Git mirror),
#. run ``cmake -G ninja <llvm-source-dir>`` from VS command prompt,
#. run ``ninja lld``
-
-Known issues
-============
-
-Note that LLD is still in early stage in development, so there are still many
-bugs. Here is a list of notable bugs.
-
-* Symbol name resolution from library files sometimes fails. On Windows, the
- order of library files in command line does not matter, but LLD sometimes
- fails to simulate the semantics. A workaround for it is to explicitly add
- library files to command line with ``/DEFAULTLIB``.
-
-* Subsystem inference is not very reliable. Linker is supposed to set
- ``subsystem`` field in the PE/COFF header according to entry function name,
- but LLD sometimes ended up with ``unknown`` subsystem type. You need to give
- ``/SUBSYSTEM`` option if it fails to infer it.
diff --git a/include/Makefile b/include/Makefile
deleted file mode 100644
index d8903356d9fb..000000000000
--- a/include/Makefile
+++ /dev/null
@@ -1,4 +0,0 @@
-LLD_LEVEL := ..
-DIRS := lld
-
-include $(LLD_LEVEL)/Makefile
diff --git a/include/lld/Config/Makefile b/include/lld/Config/Makefile
deleted file mode 100644
index e2139220e3df..000000000000
--- a/include/lld/Config/Makefile
+++ /dev/null
@@ -1,32 +0,0 @@
-LLD_LEVEL := ../../..
-
-BUILT_SOURCES = Version.inc
-
-TABLEGEN_INC_FILES_COMMON = 1
-
-include $(LLD_LEVEL)/Makefile
-
-# Compute the lld version from the LLVM version, unless specified explicitly.
-ifndef LLD_VERSION
-LLD_VERSION := $(subst svn,,$(LLVMVersion))
-LLD_VERSION := $(subst rc,,$(LLD_VERSION))
-endif
-
-LLD_VERSION_COMPONENTS := $(subst ., ,$(LLD_VERSION))
-LLD_VERSION_MAJOR := $(word 1,$(LLD_VERSION_COMPONENTS))
-LLD_VERSION_MINOR := $(word 2,$(LLD_VERSION_COMPONENTS))
-
-LLD_REVISION := $(strip \
- $(shell $(LLVM_SRC_ROOT)/utils/GetSourceVersion $(LLVM_SRC_ROOT)/tools/lld))
-
-LLD_REPOSITORY := $(strip \
- $(shell $(LLVM_SRC_ROOT)/utils/GetRepositoryPath $(LLVM_SRC_ROOT)/tools/lld))
-
-$(ObjDir)/Version.inc.tmp : Version.inc.in Makefile $(LLVM_OBJ_ROOT)/Makefile.config $(ObjDir)/.dir
- $(Echo) "Updating LLD version info."
- $(Verb)sed -e "s#@LLD_VERSION@#$(LLD_VERSION)#g" \
- -e "s#@LLD_VERSION_MAJOR@#$(LLD_VERSION_MAJOR)#g" \
- -e "s#@LLD_VERSION_MINOR@#$(LLD_VERSION_MINOR)#g" \
- -e "s#@LLD_REVISION@#$(LLD_REVISION)#g" \
- -e "s#@LLD_REPOSITORY@#$(LLD_REPOSITORY)#g" \
- $< > $@
diff --git a/include/lld/Core/Alias.h b/include/lld/Core/Alias.h
index 610022525ecb..fa999292fbd3 100644
--- a/include/lld/Core/Alias.h
+++ b/include/lld/Core/Alias.h
@@ -33,9 +33,7 @@ namespace lld {
class AliasAtom : public SimpleDefinedAtom {
public:
AliasAtom(const File &file, StringRef name)
- : SimpleDefinedAtom(file), _target(nullptr), _name(name),
- _merge(DefinedAtom::mergeNo), _deadStrip(DefinedAtom::deadStripNormal) {
- }
+ : SimpleDefinedAtom(file), _name(name) {}
StringRef name() const override { return _name; }
uint64_t size() const override { return 0; }
@@ -91,10 +89,10 @@ private:
}
}
- mutable const DefinedAtom *_target;
std::string _name;
- llvm::Optional<Merge> _merge;
- DeadStripKind _deadStrip;
+ mutable const DefinedAtom *_target = nullptr;
+ llvm::Optional<Merge> _merge = DefinedAtom::mergeNo;
+ DeadStripKind _deadStrip = DefinedAtom::deadStripNormal;
};
} // end namespace lld
diff --git a/include/lld/Core/DefinedAtom.h b/include/lld/Core/DefinedAtom.h
index 86d880c659b4..e4d4488ccdca 100644
--- a/include/lld/Core/DefinedAtom.h
+++ b/include/lld/Core/DefinedAtom.h
@@ -151,6 +151,7 @@ public:
typeNoAlloc, // Identifies non allocatable sections [ELF]
typeGroupComdat, // Identifies a section group [ELF, COFF]
typeGnuLinkOnce, // Identifies a gnu.linkonce section [ELF]
+ typeSectCreate, // Created via the -sectcreate option [Darwin]
};
// Permission bits for atoms and segments. The order of these values are
@@ -190,23 +191,26 @@ public:
// Attributes describe a code model used by the atom.
enum CodeModel {
codeNA, // no specific code model
+ // MIPS code models
codeMipsPIC, // PIC function in a PIC / non-PIC mixed file
codeMipsMicro, // microMIPS instruction encoding
codeMipsMicroPIC, // microMIPS instruction encoding + PIC
codeMips16, // MIPS-16 instruction encoding
+ // ARM code models
codeARMThumb, // ARM Thumb instruction set
+ codeARM_a, // $a-like mapping symbol (for ARM code)
+ codeARM_d, // $d-like mapping symbol (for data)
+ codeARM_t, // $t-like mapping symbol (for Thumb code)
};
struct Alignment {
- Alignment(int p2, int m = 0)
- : powerOf2(p2)
- , modulus(m) {}
+ Alignment(int v, int m = 0) : value(v), modulus(m) {}
- uint16_t powerOf2;
+ uint16_t value;
uint16_t modulus;
bool operator==(const Alignment &rhs) const {
- return (powerOf2 == rhs.powerOf2) && (modulus == rhs.modulus);
+ return (value == rhs.value) && (modulus == rhs.modulus);
}
};
diff --git a/include/lld/Core/Error.h b/include/lld/Core/Error.h
index 7caa25018f40..a7e61f91d8e9 100644
--- a/include/lld/Core/Error.h
+++ b/include/lld/Core/Error.h
@@ -19,26 +19,9 @@
namespace lld {
-const std::error_category &native_reader_category();
-
-enum class NativeReaderError {
- success = 0,
- unknown_file_format,
- file_too_short,
- file_malformed,
- unknown_chunk_type,
- memory_error,
- conflicting_target_machine,
-};
-
-inline std::error_code make_error_code(NativeReaderError e) {
- return std::error_code(static_cast<int>(e), native_reader_category());
-}
-
const std::error_category &YamlReaderCategory();
enum class YamlReaderError {
- success = 0,
unknown_keyword,
illegal_value
};
@@ -53,7 +36,11 @@ enum class LinkerScriptReaderError {
success = 0,
parse_error,
unknown_symbol_in_expr,
- unrecognized_function_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) {
@@ -66,14 +53,13 @@ inline std::error_code make_error_code(LinkerScriptReaderError e) {
/// 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);
} // end namespace lld
namespace std {
-template <>
-struct is_error_code_enum<lld::NativeReaderError> : std::true_type {};
template <> struct is_error_code_enum<lld::YamlReaderError> : std::true_type {};
template <>
struct is_error_code_enum<lld::LinkerScriptReaderError> : std::true_type {};
diff --git a/include/lld/Core/File.h b/include/lld/Core/File.h
index 25b177ec879c..494e50065340 100644
--- a/include/lld/Core/File.h
+++ b/include/lld/Core/File.h
@@ -86,90 +86,48 @@ public:
/// Sets the command line order of the file.
void setOrdinal(uint64_t ordinal) const { _ordinal = ordinal; }
- template <typename T> class atom_iterator; // forward reference
+ /// Returns the ordinal for the next atom to be defined in this file.
+ uint64_t getNextAtomOrdinalAndIncrement() const {
+ return _nextAtomOrdinal++;
+ }
/// For allocating any objects owned by this File.
llvm::BumpPtrAllocator &allocator() const {
return _allocator;
}
- /// \brief For use interating over DefinedAtoms in this File.
- typedef atom_iterator<DefinedAtom> defined_iterator;
-
- /// \brief For use interating over UndefinedAtoms in this File.
- typedef atom_iterator<UndefinedAtom> undefined_iterator;
-
- /// \brief For use interating over SharedLibraryAtoms in this File.
- typedef atom_iterator<SharedLibraryAtom> shared_library_iterator;
+ /// The type of atom mutable container.
+ template <typename T> using AtomVector = std::vector<const T *>;
- /// \brief For use interating over AbsoluteAtoms in this File.
- typedef atom_iterator<AbsoluteAtom> absolute_iterator;
-
- /// \brief Different object file readers may instantiate and manage atoms with
- /// different data structures. This class is a collection abstraction.
- /// Each concrete File instance must implement these atom_collection
- /// methods to enable clients to interate the File's atoms.
- template <typename T>
- class atom_collection {
+ /// 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.
+ template <typename T> class AtomRange {
public:
- virtual ~atom_collection() { }
- virtual atom_iterator<T> begin() const = 0;
- virtual atom_iterator<T> end() const = 0;
- virtual const T *deref(const void *it) const = 0;
- virtual void next(const void *&it) const = 0;
- virtual uint64_t size() const = 0;
- bool empty() const { return size() == 0; }
- };
+ 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(); }
- /// \brief The class is the iterator type used to iterate through a File's
- /// Atoms. This iterator delegates the work to the associated atom_collection
- /// object. There are four kinds of Atoms, so this iterator is templated on
- /// the four base Atom kinds.
- template <typename T>
- class atom_iterator : public std::iterator<std::forward_iterator_tag, T> {
- public:
- atom_iterator(const atom_collection<T> &c, const void *it)
- : _collection(&c), _it(it) { }
-
- const T *operator*() const {
- return _collection->deref(_it);
- }
- const T *operator->() const {
- return _collection->deref(_it);
- }
-
- friend bool operator==(const atom_iterator<T> &lhs, const atom_iterator<T> &rhs) {
- return lhs._it == rhs._it;
- }
-
- friend bool operator!=(const atom_iterator<T> &lhs, const atom_iterator<T> &rhs) {
- return !(lhs == rhs);
- }
-
- atom_iterator<T> &operator++() {
- _collection->next(_it);
- return *this;
- }
private:
- const atom_collection<T> *_collection;
- const void *_it;
+ AtomVector<T> &_v;
};
- /// \brief Must be implemented to return the atom_collection object for
+ /// \brief Must be implemented to return the AtomVector object for
/// all DefinedAtoms in this File.
- virtual const atom_collection<DefinedAtom> &defined() const = 0;
+ virtual const AtomVector<DefinedAtom> &defined() const = 0;
- /// \brief Must be implemented to return the atom_collection object for
+ /// \brief Must be implemented to return the AtomVector object for
/// all UndefinedAtomw in this File.
- virtual const atom_collection<UndefinedAtom> &undefined() const = 0;
+ virtual const AtomVector<UndefinedAtom> &undefined() const = 0;
- /// \brief Must be implemented to return the atom_collection object for
+ /// \brief Must be implemented to return the AtomVector object for
/// all SharedLibraryAtoms in this File.
- virtual const atom_collection<SharedLibraryAtom> &sharedLibrary() const = 0;
+ virtual const AtomVector<SharedLibraryAtom> &sharedLibrary() const = 0;
- /// \brief Must be implemented to return the atom_collection object for
+ /// \brief Must be implemented to return the AtomVector object for
/// all AbsoluteAtoms in this File.
- virtual const atom_collection<AbsoluteAtom> &absolute() const = 0;
+ virtual const AtomVector<AbsoluteAtom> &absolute() const = 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
@@ -199,67 +157,18 @@ public:
protected:
/// \brief only subclasses of File can be instantiated
File(StringRef p, Kind kind)
- : _path(p), _kind(kind), _ordinal(UINT64_MAX) {}
+ : _path(p), _kind(kind), _ordinal(UINT64_MAX),
+ _nextAtomOrdinal(0) {}
/// \brief Subclasses should override this method to parse the
/// memory buffer passed to this file's constructor.
virtual std::error_code doParse() { return std::error_code(); }
- /// \brief This is a convenience class for File subclasses which manage their
- /// atoms as a simple std::vector<>.
- template <typename T>
- class atom_collection_vector : public atom_collection<T> {
- public:
- atom_iterator<T> begin() const override {
- auto *it = _atoms.empty() ? nullptr
- : reinterpret_cast<const void *>(_atoms.data());
- return atom_iterator<T>(*this, it);
- }
-
- atom_iterator<T> end() const override {
- auto *it = _atoms.empty() ? nullptr : reinterpret_cast<const void *>(
- _atoms.data() + _atoms.size());
- return atom_iterator<T>(*this, it);
- }
-
- const T *deref(const void *it) const override {
- return *reinterpret_cast<const T *const *>(it);
- }
-
- void next(const void *&it) const override {
- const T *const *p = reinterpret_cast<const T *const *>(it);
- ++p;
- it = reinterpret_cast<const void*>(p);
- }
-
- uint64_t size() const override { return _atoms.size(); }
-
- std::vector<const T *> _atoms;
- };
-
- /// \brief This is a convenience class for File subclasses which need to
- /// return an empty collection.
- template <typename T>
- class atom_collection_empty : public atom_collection<T> {
- public:
- atom_iterator<T> begin() const override {
- return atom_iterator<T>(*this, nullptr);
- }
- atom_iterator<T> end() const override {
- return atom_iterator<T>(*this, nullptr);
- }
- const T *deref(const void *it) const override {
- llvm_unreachable("empty collection should never be accessed");
- }
- void next(const void *&it) const override {}
- uint64_t size() const override { return 0; }
- };
-
- static atom_collection_empty<DefinedAtom> _noDefinedAtoms;
- static atom_collection_empty<UndefinedAtom> _noUndefinedAtoms;
- static atom_collection_empty<SharedLibraryAtom> _noSharedLibraryAtoms;
- static atom_collection_empty<AbsoluteAtom> _noAbsoluteAtoms;
- mutable llvm::BumpPtrAllocator _allocator;
+ static AtomVector<DefinedAtom> _noDefinedAtoms;
+ static AtomVector<UndefinedAtom> _noUndefinedAtoms;
+ static AtomVector<SharedLibraryAtom> _noSharedLibraryAtoms;
+ static AtomVector<AbsoluteAtom> _noAbsoluteAtoms;
+ mutable llvm::BumpPtrAllocator _allocator;
private:
StringRef _path;
@@ -267,29 +176,12 @@ private:
mutable std::string _archiveMemberPath;
Kind _kind;
mutable uint64_t _ordinal;
+ mutable uint64_t _nextAtomOrdinal;
std::shared_ptr<MemoryBuffer> _sharedMemoryBuffer;
llvm::Optional<std::error_code> _lastError;
std::mutex _parseMutex;
};
-/// \brief A mutable File.
-class MutableFile : public File {
-public:
- /// \brief Add an atom to the file. Invalidates iterators for all returned
- /// containters.
- virtual void addAtom(const Atom&) = 0;
-
- typedef range<std::vector<const DefinedAtom *>::iterator> DefinedAtomRange;
- virtual DefinedAtomRange definedAtoms() = 0;
-
- virtual void
- removeDefinedAtomsIf(std::function<bool(const DefinedAtom *)> pred) = 0;
-
-protected:
- /// \brief only subclasses of MutableFile can be instantiated
- MutableFile(StringRef p) : File(p, kindObject) {}
-};
-
/// An ErrorFile represents a file that doesn't exist.
/// If you try to parse a file which doesn't exist, an instance of this
/// class will be returned. That's parse method always returns an error.
@@ -302,16 +194,16 @@ public:
std::error_code doParse() override { return _ec; }
- const atom_collection<DefinedAtom> &defined() const override {
+ const AtomVector<DefinedAtom> &defined() const override {
llvm_unreachable("internal error");
}
- const atom_collection<UndefinedAtom> &undefined() const override {
+ const AtomVector<UndefinedAtom> &undefined() const override {
llvm_unreachable("internal error");
}
- const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
llvm_unreachable("internal error");
}
- const atom_collection<AbsoluteAtom> &absolute() const override {
+ const AtomVector<AbsoluteAtom> &absolute() const override {
llvm_unreachable("internal error");
}
diff --git a/include/lld/Core/LLVM.h b/include/lld/Core/LLVM.h
index 1bc1173bd48b..d532c17fbfdf 100644
--- a/include/lld/Core/LLVM.h
+++ b/include/lld/Core/LLVM.h
@@ -26,6 +26,7 @@ namespace llvm {
class StringRef;
class Twine;
class MemoryBuffer;
+ class MemoryBufferRef;
template<typename T> class ArrayRef;
template<unsigned InternalLen> class SmallString;
template<typename T, unsigned N> class SmallVector;
@@ -53,6 +54,7 @@ namespace lld {
using llvm::StringRef;
using llvm::Twine;
using llvm::MemoryBuffer;
+ using llvm::MemoryBufferRef;
using llvm::ArrayRef;
using llvm::SmallString;
using llvm::SmallVector;
diff --git a/include/lld/Core/LinkingContext.h b/include/lld/Core/LinkingContext.h
index 81a3b4b4eb71..a723854b3c91 100644
--- a/include/lld/Core/LinkingContext.h
+++ b/include/lld/Core/LinkingContext.h
@@ -41,7 +41,6 @@ public:
enum class OutputFileType : uint8_t {
Default, // The default output type for this target
YAML, // The output type is set to YAML
- Native // The output file format is Native (Atoms)
};
virtual ~LinkingContext();
@@ -62,7 +61,7 @@ public:
/// should be marked live (along with all Atoms they reference). Usually
/// this method returns false for main executables, but true for dynamic
/// shared libraries.
- bool globalsAreDeadStripRoots() const { return _globalsAreDeadStripRoots; };
+ bool globalsAreDeadStripRoots() const { return _globalsAreDeadStripRoots; }
/// Only used if deadStrip() returns true. This method returns the names
/// of DefinedAtoms that should be marked live (along with all Atoms they
@@ -273,13 +272,11 @@ public:
/// Set the various output file types that the linker would
/// create
bool setOutputFileType(StringRef outputFileType) {
- if (outputFileType.equals_lower("yaml"))
+ if (outputFileType.equals_lower("yaml")) {
_outputFileType = OutputFileType::YAML;
- else if (outputFileType.equals_lower("native"))
- _outputFileType = OutputFileType::YAML;
- else
- return false;
- return true;
+ return true;
+ }
+ return false;
}
/// Returns the output file type that that the linker needs to create.
@@ -292,7 +289,7 @@ 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 bool createImplicitFiles(std::vector<std::unique_ptr<File> > &);
+ virtual void createImplicitFiles(std::vector<std::unique_ptr<File>> &);
/// 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.
diff --git a/include/lld/Core/Parallel.h b/include/lld/Core/Parallel.h
index 65176ac2b04d..e2c38308b768 100644
--- a/include/lld/Core/Parallel.h
+++ b/include/lld/Core/Parallel.h
@@ -14,21 +14,15 @@
#include "lld/Core/LLVM.h"
#include "lld/Core/range.h"
#include "llvm/Support/MathExtras.h"
-
-#ifdef _MSC_VER
-// concrt.h depends on eh.h for __uncaught_exception declaration
-// even if we disable exceptions.
-#include <eh.h>
-#endif
+#include "llvm/Support/thread.h"
#include <algorithm>
#include <atomic>
#include <condition_variable>
#include <mutex>
-#include <thread>
#include <stack>
-#ifdef _MSC_VER
+#if defined(_MSC_VER) && LLVM_ENABLE_THREADS
#include <concrt.h>
#include <ppl.h>
#endif
@@ -104,13 +98,55 @@ private:
std::condition_variable _cond;
};
+// Classes in this namespace are implementation details of this header.
+namespace internal {
+
/// \brief An abstract class that takes closures and runs them asynchronously.
class Executor {
public:
- virtual ~Executor() {}
+ virtual ~Executor() = default;
virtual void add(std::function<void()> func) = 0;
};
+#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
+class SyncExecutor : public Executor {
+public:
+ virtual void add(std::function<void()> func) {
+ func();
+ }
+};
+
+inline Executor *getDefaultExecutor() {
+ static SyncExecutor exec;
+ return &exec;
+}
+#elif defined(_MSC_VER)
+/// \brief An Executor that runs tasks via ConcRT.
+class ConcRTExecutor : public Executor {
+ struct Taskish {
+ Taskish(std::function<void()> task) : _task(task) {}
+
+ std::function<void()> _task;
+
+ static void run(void *p) {
+ Taskish *self = static_cast<Taskish *>(p);
+ self->_task();
+ concurrency::Free(self);
+ }
+ };
+
+public:
+ virtual void add(std::function<void()> func) {
+ Concurrency::CurrentScheduler::ScheduleTask(Taskish::run,
+ new (concurrency::Alloc(sizeof(Taskish))) Taskish(func));
+ }
+};
+
+inline Executor *getDefaultExecutor() {
+ static ConcRTExecutor exec;
+ return &exec;
+}
+#else
/// \brief An implementation of an Executor that runs closures on a thread pool
/// in filo order.
class ThreadPoolExecutor : public Executor {
@@ -130,7 +166,7 @@ public:
}).detach();
}
- ~ThreadPoolExecutor() {
+ ~ThreadPoolExecutor() override {
std::unique_lock<std::mutex> lock(_mutex);
_stop = true;
lock.unlock();
@@ -169,39 +205,14 @@ private:
Latch _done;
};
-#ifdef _MSC_VER
-/// \brief An Executor that runs tasks via ConcRT.
-class ConcRTExecutor : public Executor {
- struct Taskish {
- Taskish(std::function<void()> task) : _task(task) {}
-
- std::function<void()> _task;
-
- static void run(void *p) {
- Taskish *self = static_cast<Taskish *>(p);
- self->_task();
- concurrency::Free(self);
- }
- };
-
-public:
- virtual void add(std::function<void()> func) {
- Concurrency::CurrentScheduler::ScheduleTask(Taskish::run,
- new (concurrency::Alloc(sizeof(Taskish))) Taskish(func));
- }
-};
-
-inline Executor *getDefaultExecutor() {
- static ConcRTExecutor exec;
- return &exec;
-}
-#else
inline Executor *getDefaultExecutor() {
static ThreadPoolExecutor exec;
return &exec;
}
#endif
+} // namespace internal
+
/// \brief Allows launching a number of tasks and waiting for them to finish
/// either explicitly via sync() or implicitly on destruction.
class TaskGroup {
@@ -210,7 +221,7 @@ class TaskGroup {
public:
void spawn(std::function<void()> f) {
_latch.inc();
- getDefaultExecutor()->add([&, f] {
+ internal::getDefaultExecutor()->add([&, f] {
f();
_latch.dec();
});
@@ -219,7 +230,15 @@ public:
void sync() const { _latch.sync(); }
};
-#ifdef _MSC_VER
+#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
+template <class RandomAccessIterator, class Comp>
+void parallel_sort(
+ RandomAccessIterator start, RandomAccessIterator end,
+ const Comp &comp = std::less<
+ typename std::iterator_traits<RandomAccessIterator>::value_type>()) {
+ std::sort(start, end, comp);
+}
+#elif defined(_MSC_VER)
// Use ppl parallel_sort on Windows.
template <class RandomAccessIterator, class Comp>
void parallel_sort(
@@ -286,7 +305,12 @@ template <class T> void parallel_sort(T *start, T *end) {
parallel_sort(start, end, std::less<T>());
}
-#ifdef _MSC_VER
+#if !defined(LLVM_ENABLE_THREADS) || LLVM_ENABLE_THREADS == 0
+template <class Iterator, class Func>
+void parallel_for_each(Iterator begin, Iterator end, Func func) {
+ std::for_each(begin, end, func);
+}
+#elif defined(_MSC_VER)
// Use ppl parallel_for_each on Windows.
template <class Iterator, class Func>
void parallel_for_each(Iterator begin, Iterator end, Func func) {
@@ -306,4 +330,4 @@ void parallel_for_each(Iterator begin, Iterator end, Func func) {
#endif
} // end namespace lld
-#endif
+#endif // LLD_CORE_PARALLEL_H
diff --git a/include/lld/Core/Pass.h b/include/lld/Core/Pass.h
index 7a9d2453f482..2e49cd1b8eee 100644
--- a/include/lld/Core/Pass.h
+++ b/include/lld/Core/Pass.h
@@ -17,7 +17,7 @@
#include <vector>
namespace lld {
-class MutableFile;
+class SimpleFile;
/// Once the core linking is done (which resolves references, coalesces atoms
/// and produces a complete Atom graph), the linker runs a series of passes
@@ -34,7 +34,7 @@ public:
virtual ~Pass() { }
/// Do the actual work of the Pass.
- virtual void perform(std::unique_ptr<MutableFile> &mergedFile) = 0;
+ virtual std::error_code 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 65fc4d806ceb..62aa119f8f76 100644
--- a/include/lld/Core/PassManager.h
+++ b/include/lld/Core/PassManager.h
@@ -16,7 +16,7 @@
#include <vector>
namespace lld {
-class MutableFile;
+class SimpleFile;
class Pass;
/// \brief Owns and runs a collection of passes.
@@ -31,9 +31,10 @@ public:
_passes.push_back(std::move(pass));
}
- std::error_code runOnFile(std::unique_ptr<MutableFile> &file) {
+ std::error_code runOnFile(SimpleFile &file) {
for (std::unique_ptr<Pass> &pass : _passes)
- pass->perform(file);
+ if (std::error_code EC = pass->perform(file))
+ return EC;
return std::error_code();
}
diff --git a/include/lld/Core/Reader.h b/include/lld/Core/Reader.h
index ac90c5a7e85c..9324da475e3d 100644
--- a/include/lld/Core/Reader.h
+++ b/include/lld/Core/Reader.h
@@ -31,13 +31,12 @@ class ELFLinkingContext;
class File;
class LinkingContext;
class PECOFFLinkingContext;
-class TargetHandlerBase;
class MachOLinkingContext;
/// \brief An abstract class for reading object files, library files, and
/// executable files.
///
-/// Each file format (e.g. ELF, mach-o, PECOFF, native, etc) have a concrete
+/// Each file format (e.g. ELF, mach-o, PECOFF, etc) have a concrete
/// subclass of Reader.
class Reader {
public:
@@ -46,17 +45,14 @@ public:
/// Sniffs the file to determine if this Reader can parse it.
/// The method is called with:
/// 1) the file_magic enumeration returned by identify_magic()
- /// 2) the file extension (e.g. ".obj")
- /// 3) the whole file content buffer if the above is not enough.
- virtual bool canParse(file_magic magic, StringRef fileExtension,
- const MemoryBuffer &mb) const = 0;
+ /// 2) the whole file content buffer if the above is not enough.
+ virtual bool canParse(file_magic magic, MemoryBufferRef mb) const = 0;
/// \brief Parse a supplied buffer (already filled with the contents of a
/// file) and create a File object.
/// The resulting File object takes ownership of the MemoryBuffer.
- virtual std::error_code
- loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
- std::vector<std::unique_ptr<File>> &result) const = 0;
+ virtual ErrorOr<std::unique_ptr<File>>
+ loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &) const = 0;
};
@@ -93,8 +89,8 @@ public:
/// Walk the list of registered Readers and find one that can parse the
/// supplied file and parse it.
- std::error_code loadFile(std::unique_ptr<MemoryBuffer> mb,
- std::vector<std::unique_ptr<File>> &result) const;
+ ErrorOr<std::unique_ptr<File>>
+ loadFile(std::unique_ptr<MemoryBuffer> mb) const;
/// Walk the list of registered kind tables to convert a Reference Kind
/// name to a value.
@@ -118,7 +114,6 @@ public:
// as parameters to the addSupport*() method.
void addSupportArchives(bool logLoading);
void addSupportYamlFiles();
- void addSupportNativeObjects();
void addSupportCOFFObjects(PECOFFLinkingContext &);
void addSupportCOFFImportLibraries(PECOFFLinkingContext &);
void addSupportMachOObjects(MachOLinkingContext &);
diff --git a/include/lld/Core/Reference.h b/include/lld/Core/Reference.h
index 7a804c31e182..971721eb7d54 100644
--- a/include/lld/Core/Reference.h
+++ b/include/lld/Core/Reference.h
@@ -56,7 +56,7 @@ public:
void setKindNamespace(KindNamespace ns) { _kindNamespace = (uint8_t)ns; }
// Which architecture the kind value is for.
- enum class KindArch { all, AArch64, ARM, Hexagon, Mips, x86, x86_64 };
+ enum class KindArch { all, AArch64, AMDGPU, ARM, Hexagon, Mips, x86, x86_64 };
KindArch kindArch() const { return (KindArch)_kindArch; }
void setKindArch(KindArch a) { _kindArch = (uint8_t)a; }
diff --git a/include/lld/Core/Resolver.h b/include/lld/Core/Resolver.h
index e16c07b839fa..05af7d9573ea 100644
--- a/include/lld/Core/Resolver.h
+++ b/include/lld/Core/Resolver.h
@@ -54,7 +54,7 @@ public:
/// @brief do work of merging and resolving and return list
bool resolve();
- std::unique_ptr<MutableFile> resultFile() { return std::move(_result); }
+ std::unique_ptr<SimpleFile> resultFile() { return std::move(_result); }
private:
typedef std::function<void(StringRef, bool)> UndefCallback;
diff --git a/include/lld/Core/SharedLibraryFile.h b/include/lld/Core/SharedLibraryFile.h
index 2f84624287d8..a2907287862d 100644
--- a/include/lld/Core/SharedLibraryFile.h
+++ b/include/lld/Core/SharedLibraryFile.h
@@ -34,19 +34,19 @@ public:
// the import name (Windows).
virtual StringRef getDSOName() const = 0;
- const atom_collection<DefinedAtom> &defined() const override {
+ const AtomVector<DefinedAtom> &defined() const override {
return _definedAtoms;
}
- const atom_collection<UndefinedAtom> &undefined() const override {
+ const AtomVector<UndefinedAtom> &undefined() const override {
return _undefinedAtoms;
}
- const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
return _sharedLibraryAtoms;
}
- const atom_collection<AbsoluteAtom> &absolute() const override {
+ const AtomVector<AbsoluteAtom> &absolute() const override {
return _absoluteAtoms;
}
@@ -54,10 +54,10 @@ protected:
/// only subclasses of SharedLibraryFile can be instantiated
explicit SharedLibraryFile(StringRef path) : File(path, kindSharedLibrary) {}
- atom_collection_vector<DefinedAtom> _definedAtoms;
- atom_collection_vector<UndefinedAtom> _undefinedAtoms;
- atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
- atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
+ AtomVector<DefinedAtom> _definedAtoms;
+ AtomVector<UndefinedAtom> _undefinedAtoms;
+ AtomVector<SharedLibraryAtom> _sharedLibraryAtoms;
+ AtomVector<AbsoluteAtom> _absoluteAtoms;
};
} // namespace lld
diff --git a/include/lld/Core/Simple.h b/include/lld/Core/Simple.h
index 71d0c0702301..3c204f8ba284 100644
--- a/include/lld/Core/Simple.h
+++ b/include/lld/Core/Simple.h
@@ -23,59 +23,61 @@
#include "lld/Core/UndefinedAtom.h"
#include "llvm/ADT/ilist.h"
#include "llvm/ADT/ilist_node.h"
+#include <atomic>
namespace lld {
-class SimpleFile : public MutableFile {
+class SimpleFile : public File {
public:
- SimpleFile(StringRef path) : MutableFile(path) {}
-
- void addAtom(const Atom &atom) override {
- if (auto *defAtom = dyn_cast<DefinedAtom>(&atom)) {
- _definedAtoms._atoms.push_back(defAtom);
- } else if (auto *undefAtom = dyn_cast<UndefinedAtom>(&atom)) {
- _undefinedAtoms._atoms.push_back(undefAtom);
- } else if (auto *shlibAtom = dyn_cast<SharedLibraryAtom>(&atom)) {
- _sharedLibraryAtoms._atoms.push_back(shlibAtom);
- } else if (auto *absAtom = dyn_cast<AbsoluteAtom>(&atom)) {
- _absoluteAtoms._atoms.push_back(absAtom);
+ SimpleFile(StringRef path) : File(path, kindObject) {}
+
+ 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(const Atom &atom) {
+ if (auto *p = dyn_cast<DefinedAtom>(&atom)) {
+ _defined.push_back(p);
+ } else if (auto *p = dyn_cast<UndefinedAtom>(&atom)) {
+ _undefined.push_back(p);
+ } else if (auto *p = dyn_cast<SharedLibraryAtom>(&atom)) {
+ _shared.push_back(p);
+ } else if (auto *p = dyn_cast<AbsoluteAtom>(&atom)) {
+ _absolute.push_back(p);
} else {
llvm_unreachable("atom has unknown definition kind");
}
}
- void
- removeDefinedAtomsIf(std::function<bool(const DefinedAtom *)> pred) override {
- auto &atoms = _definedAtoms._atoms;
+ void removeDefinedAtomsIf(std::function<bool(const DefinedAtom *)> pred) {
+ auto &atoms = _defined;
auto newEnd = std::remove_if(atoms.begin(), atoms.end(), pred);
atoms.erase(newEnd, atoms.end());
}
- const atom_collection<DefinedAtom> &defined() const override {
- return _definedAtoms;
- }
+ const AtomVector<DefinedAtom> &defined() const override { return _defined; }
- const atom_collection<UndefinedAtom> &undefined() const override {
- return _undefinedAtoms;
+ const AtomVector<UndefinedAtom> &undefined() const override {
+ return _undefined;
}
- const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
- return _sharedLibraryAtoms;
+ const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ return _shared;
}
- const atom_collection<AbsoluteAtom> &absolute() const override {
- return _absoluteAtoms;
+ const AtomVector<AbsoluteAtom> &absolute() const override {
+ return _absolute;
}
- DefinedAtomRange definedAtoms() override {
- return make_range(_definedAtoms._atoms);
- }
+ typedef range<std::vector<const DefinedAtom *>::iterator> DefinedAtomRange;
+ DefinedAtomRange definedAtoms() { return make_range(_defined); }
private:
- atom_collection_vector<DefinedAtom> _definedAtoms;
- atom_collection_vector<UndefinedAtom> _undefinedAtoms;
- atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
- atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
+ AtomVector<DefinedAtom> _defined;
+ AtomVector<UndefinedAtom> _undefined;
+ AtomVector<SharedLibraryAtom> _shared;
+ AtomVector<AbsoluteAtom> _absolute;
};
/// \brief Archive library file that may be used as a virtual container
@@ -86,19 +88,19 @@ public:
SimpleArchiveLibraryFile(StringRef filename)
: ArchiveLibraryFile(filename) {}
- const atom_collection<DefinedAtom> &defined() const override {
+ const AtomVector<DefinedAtom> &defined() const override {
return _definedAtoms;
}
- const atom_collection<UndefinedAtom> &undefined() const override {
+ const AtomVector<UndefinedAtom> &undefined() const override {
return _undefinedAtoms;
}
- const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
+ const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
return _sharedLibraryAtoms;
}
- const atom_collection<AbsoluteAtom> &absolute() const override {
+ const AtomVector<AbsoluteAtom> &absolute() const override {
return _absoluteAtoms;
}
@@ -114,10 +116,10 @@ public:
}
private:
- atom_collection_vector<DefinedAtom> _definedAtoms;
- atom_collection_vector<UndefinedAtom> _undefinedAtoms;
- atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
- atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
+ AtomVector<DefinedAtom> _definedAtoms;
+ AtomVector<UndefinedAtom> _undefinedAtoms;
+ AtomVector<SharedLibraryAtom> _sharedLibraryAtoms;
+ AtomVector<AbsoluteAtom> _absoluteAtoms;
};
class SimpleReference : public Reference {
@@ -204,9 +206,8 @@ namespace lld {
class SimpleDefinedAtom : public DefinedAtom {
public:
- explicit SimpleDefinedAtom(const File &f) : _file(f) {
- static uint32_t lastOrdinal = 0;
- _ordinal = lastOrdinal++;
+ explicit SimpleDefinedAtom(const File &f)
+ : _file(f), _ordinal(f.getNextAtomOrdinalAndIncrement()) {
_references.setAllocator(&f.allocator());
}
@@ -224,7 +225,7 @@ public:
Merge merge() const override { return DefinedAtom::mergeNo; }
- Alignment alignment() const override { return Alignment(0, 0); }
+ Alignment alignment() const override { return 1; }
SectionChoice sectionChoice() const override {
return DefinedAtom::sectionBasedOnContent;
diff --git a/include/lld/Core/SymbolTable.h b/include/lld/Core/SymbolTable.h
index 683ed65e3635..2e4459236d18 100644
--- a/include/lld/Core/SymbolTable.h
+++ b/include/lld/Core/SymbolTable.h
@@ -105,7 +105,7 @@ private:
bool addByName(const Atom &);
bool addByContent(const DefinedAtom &);
- LinkingContext &_context;
+ LinkingContext &_ctx;
AtomToAtom _replacedAtoms;
NameToAtom _nameTable;
NameToAtom _groupTable;
diff --git a/include/lld/Core/TODO.txt b/include/lld/Core/TODO.txt
index 8888c763ef65..8b523045de75 100644
--- a/include/lld/Core/TODO.txt
+++ b/include/lld/Core/TODO.txt
@@ -1,7 +1,7 @@
include/lld/Core
~~~~~~~~~~~~~~~~
-* The native/yaml reader/writer interfaces should be changed to return
+* The yaml reader/writer interfaces should be changed to return
an explanatory string if there is an error. The existing error_code
abstraction only works for returning low level OS errors. It does not
work for describing formatting issues.
diff --git a/include/lld/Core/Writer.h b/include/lld/Core/Writer.h
index 94c75d8d019f..8214ed6203f2 100644
--- a/include/lld/Core/Writer.h
+++ b/include/lld/Core/Writer.h
@@ -15,16 +15,15 @@
#include <vector>
namespace lld {
-class File;
class ELFLinkingContext;
+class File;
+class LinkingContext;
class MachOLinkingContext;
class PECOFFLinkingContext;
-class LinkingContext;
-class TargetHandlerBase;
/// \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, native, etc) have a concrete subclass of Writer.
+/// PECOFF, etc) have a concrete subclass of Writer.
class Writer {
public:
virtual ~Writer();
@@ -35,17 +34,16 @@ public:
/// \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
/// how file format specific atoms can be added to the link.
- virtual bool createImplicitFiles(std::vector<std::unique_ptr<File> > &);
+ virtual void createImplicitFiles(std::vector<std::unique_ptr<File>> &) {}
protected:
// only concrete subclasses can be instantiated
Writer();
};
-std::unique_ptr<Writer> createWriterELF(TargetHandlerBase *handler);
+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> createWriterNative();
std::unique_ptr<Writer> createWriterYAML(const LinkingContext &);
} // end namespace lld
diff --git a/include/lld/Driver/Driver.h b/include/lld/Driver/Driver.h
index 300d2356d050..4bf0f43f8ce5 100644
--- a/include/lld/Driver/Driver.h
+++ b/include/lld/Driver/Driver.h
@@ -35,7 +35,7 @@ class ELFLinkingContext;
typedef std::vector<std::unique_ptr<File>> FileVector;
FileVector makeErrorFile(StringRef path, std::error_code ec);
-FileVector parseMemberFiles(FileVector &files);
+FileVector parseMemberFiles(std::unique_ptr<File> File);
FileVector loadFile(LinkingContext &ctx, StringRef path, bool wholeArchive);
/// Base class for all Drivers.
@@ -46,6 +46,9 @@ protected:
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;
};
@@ -55,7 +58,7 @@ private:
class UniversalDriver : public Driver {
public:
/// Determine flavor and pass control to Driver for that flavor.
- static bool link(int argc, const char *argv[],
+ static bool link(llvm::MutableArrayRef<const char *> args,
raw_ostream &diag = llvm::errs());
private:
@@ -67,12 +70,12 @@ 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(int argc, const char *argv[],
+ 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(int argc, const char *argv[],
+ static bool parse(llvm::ArrayRef<const char *> args,
std::unique_ptr<ELFLinkingContext> &context,
raw_ostream &diag = llvm::errs());
@@ -103,12 +106,13 @@ 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(int argc, const char *argv[],
+ 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(int argc, const char *argv[], MachOLinkingContext &info,
+ static bool parse(llvm::ArrayRef<const char *> args,
+ MachOLinkingContext &info,
raw_ostream &diag = llvm::errs());
private:
@@ -116,41 +120,25 @@ private:
};
/// Driver for Windows 'link.exe' command line options
-class WinLinkDriver : public Driver {
-public:
- /// Parses command line arguments same as Windows link.exe and performs link.
- /// Returns true iff there was an error.
- static bool linkPECOFF(int argc, const char *argv[],
- raw_ostream &diag = llvm::errs());
-
- /// Uses Windows style link command line options to fill in options struct.
- /// Returns true iff there was an error.
- static bool parse(int argc, const char *argv[], PECOFFLinkingContext &info,
- raw_ostream &diag = llvm::errs(),
- bool isDirective = false);
-
- // Same as parse(), but restricted to the context of directives.
- static bool parseDirectives(int argc, const char *argv[],
- PECOFFLinkingContext &info,
- raw_ostream &diag = llvm::errs()) {
- return parse(argc, argv, info, diag, true);
- }
+namespace coff {
+void link(llvm::ArrayRef<const char *> args);
+}
-private:
- WinLinkDriver() = delete;
-};
+namespace elf2 {
+void link(llvm::ArrayRef<const char *> args);
+}
/// 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(int argc, const char *argv[],
+ 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(int argc, const char *argv[], CoreLinkingContext &info,
+ static bool parse(llvm::ArrayRef<const char *> args, CoreLinkingContext &info,
raw_ostream &diag = llvm::errs());
private:
diff --git a/include/lld/Driver/WinLinkModuleDef.h b/include/lld/Driver/WinLinkModuleDef.h
deleted file mode 100644
index 68c9a4bfef70..000000000000
--- a/include/lld/Driver/WinLinkModuleDef.h
+++ /dev/null
@@ -1,200 +0,0 @@
-//===- lld/Driver/WinLinkModuleDef.h --------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Windows module definition file parser.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_DRIVER_WIN_LINK_MODULE_DEF_H
-#define LLD_DRIVER_WIN_LINK_MODULE_DEF_H
-
-#include "lld/Core/LLVM.h"
-#include "lld/ReaderWriter/PECOFFLinkingContext.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/Support/Allocator.h"
-#include <vector>
-
-namespace lld {
-namespace moduledef {
-
-enum class Kind {
- unknown,
- eof,
- identifier,
- comma,
- equal,
- kw_base,
- kw_data,
- kw_exports,
- kw_heapsize,
- kw_library,
- kw_name,
- kw_noname,
- kw_private,
- kw_stacksize,
- kw_version,
-};
-
-class Token {
-public:
- Token() : _kind(Kind::unknown) {}
- Token(Kind kind, StringRef range) : _kind(kind), _range(range) {}
-
- Kind _kind;
- StringRef _range;
-};
-
-class Lexer {
-public:
- explicit Lexer(std::unique_ptr<MemoryBuffer> mb) : _buffer(mb->getBuffer()) {
- _sourceManager.AddNewSourceBuffer(std::move(mb), llvm::SMLoc());
- }
-
- Token lex();
- const llvm::SourceMgr &getSourceMgr() const { return _sourceManager; }
-
-private:
- StringRef _buffer;
- llvm::SourceMgr _sourceManager;
-};
-
-class Directive {
-public:
- enum class Kind { exports, heapsize, library, name, stacksize, version };
-
- Kind getKind() const { return _kind; }
- virtual ~Directive() {}
-
-protected:
- explicit Directive(Kind k) : _kind(k) {}
-
-private:
- Kind _kind;
-};
-
-class Exports : public Directive {
-public:
- explicit Exports(const std::vector<PECOFFLinkingContext::ExportDesc> &exports)
- : Directive(Kind::exports), _exports(exports) {}
-
- static bool classof(const Directive *dir) {
- return dir->getKind() == Kind::exports;
- }
-
- const std::vector<PECOFFLinkingContext::ExportDesc> &getExports() const {
- return _exports;
- }
-
-private:
- const std::vector<PECOFFLinkingContext::ExportDesc> _exports;
-};
-
-template <Directive::Kind kind>
-class MemorySize : public Directive {
-public:
- MemorySize(uint64_t reserve, uint64_t commit)
- : Directive(kind), _reserve(reserve), _commit(commit) {}
-
- static bool classof(const Directive *dir) {
- return dir->getKind() == kind;
- }
-
- uint64_t getReserve() const { return _reserve; }
- uint64_t getCommit() const { return _commit; }
-
-private:
- const uint64_t _reserve;
- const uint64_t _commit;
-};
-
-typedef MemorySize<Directive::Kind::heapsize> Heapsize;
-typedef MemorySize<Directive::Kind::stacksize> Stacksize;
-
-class Name : public Directive {
-public:
- Name(StringRef outputPath, uint64_t baseaddr)
- : Directive(Kind::name), _outputPath(outputPath), _baseaddr(baseaddr) {}
-
- static bool classof(const Directive *dir) {
- return dir->getKind() == Kind::name;
- }
-
- StringRef getOutputPath() const { return _outputPath; }
- uint64_t getBaseAddress() const { return _baseaddr; }
-
-private:
- const std::string _outputPath;
- const uint64_t _baseaddr;
-};
-
-class Library : public Directive {
-public:
- Library(StringRef name, uint64_t baseaddr)
- : Directive(Kind::library), _name(name), _baseaddr(baseaddr) {}
-
- static bool classof(const Directive *dir) {
- return dir->getKind() == Kind::library;
- }
-
- StringRef getName() const { return _name; }
- uint64_t getBaseAddress() const { return _baseaddr; }
-
-private:
- const std::string _name;
- const uint64_t _baseaddr;
-};
-
-class Version : public Directive {
-public:
- Version(int major, int minor)
- : Directive(Kind::version), _major(major), _minor(minor) {}
-
- static bool classof(const Directive *dir) {
- return dir->getKind() == Kind::version;
- }
-
- int getMajorVersion() const { return _major; }
- int getMinorVersion() const { return _minor; }
-
-private:
- const int _major;
- const int _minor;
-};
-
-class Parser {
-public:
- Parser(Lexer &lex, llvm::BumpPtrAllocator &alloc)
- : _lex(lex), _alloc(alloc) {}
-
- bool parse(std::vector<Directive *> &ret);
-
-private:
- void consumeToken();
- bool consumeTokenAsInt(uint64_t &result);
- bool expectAndConsume(Kind kind, Twine msg);
-
- void ungetToken();
- void error(const Token &tok, Twine msg);
-
- bool parseOne(Directive *&dir);
- bool parseExport(PECOFFLinkingContext::ExportDesc &result);
- bool parseMemorySize(uint64_t &reserve, uint64_t &commit);
- bool parseName(std::string &outfile, uint64_t &baseaddr);
- bool parseVersion(int &major, int &minor);
-
- Lexer &_lex;
- llvm::BumpPtrAllocator &_alloc;
- Token _tok;
- std::vector<Token> _tokBuf;
-};
-}
-}
-
-#endif
diff --git a/include/lld/Makefile b/include/lld/Makefile
deleted file mode 100644
index 5bfb8910313e..000000000000
--- a/include/lld/Makefile
+++ /dev/null
@@ -1,44 +0,0 @@
-LLD_LEVEL := ../..
-DIRS := Config
-
-include $(LLD_LEVEL)/Makefile
-
-install-local::
- $(Echo) Installing lld include files
- $(Verb) $(MKDIR) $(DESTDIR)$(PROJ_includedir)
- $(Verb) if test -d "$(PROJ_SRC_DIR)" ; then \
- cd $(PROJ_SRC_DIR)/.. && \
- for hdr in `find lld -type f \
- '(' -name LICENSE.TXT \
- -o -name '*.def' \
- -o -name '*.h' \
- -o -name '*.inc' \
- ')' -print \
- | grep -v CVS | grep -v .svn | grep -v .dir` ; do \
- instdir=$(DESTDIR)`dirname "$(PROJ_includedir)/$$hdr"` ; \
- if test \! -d "$$instdir" ; then \
- $(EchoCmd) Making install directory $$instdir ; \
- $(MKDIR) $$instdir ;\
- fi ; \
- $(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \
- done ; \
- fi
-ifneq ($(PROJ_SRC_ROOT),$(PROJ_OBJ_ROOT))
- $(Verb) if test -d "$(PROJ_OBJ_ROOT)/tools/lld/include/lld" ; then \
- cd $(PROJ_OBJ_ROOT)/tools/lld/include && \
- for hdr in `find lld -type f \
- '(' -name LICENSE.TXT \
- -o -name '*.def' \
- -o -name '*.h' \
- -o -name '*.inc' \
- ')' -print \
- | grep -v CVS | grep -v .tmp | grep -v .dir` ; do \
- instdir=$(DESTDIR)`dirname "$(PROJ_includedir)/$$hdr"` ; \
- if test \! -d "$$instdir" ; then \
- $(EchoCmd) Making install directory $$instdir ; \
- $(MKDIR) $$instdir ;\
- fi ; \
- $(DataInstall) $$hdr $(DESTDIR)$(PROJ_includedir)/$$hdr ; \
- done ; \
- fi
-endif
diff --git a/include/lld/ReaderWriter/ELFLinkingContext.h b/include/lld/ReaderWriter/ELFLinkingContext.h
index d1cd3d9f3d6b..d1a5b28bb61f 100644
--- a/include/lld/ReaderWriter/ELFLinkingContext.h
+++ b/include/lld/ReaderWriter/ELFLinkingContext.h
@@ -26,24 +26,60 @@
#include <memory>
#include <set>
+namespace llvm {
+class FileOutputBuffer;
+}
+
namespace lld {
-class DefinedAtom;
-class Reference;
+struct AtomLayout;
class File;
+class Reference;
namespace elf {
-template <typename ELFT> class TargetHandler;
-}
+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;
+};
-class TargetHandlerBase {
+} // 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 ~TargetHandlerBase() {}
- virtual void registerRelocationNames(Registry &) = 0;
+ 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;
};
@@ -52,28 +88,32 @@ public:
/// \brief The type of ELF executable that the linker
/// creates.
enum class OutputMagic : uint8_t {
- DEFAULT, // The default mode, no specific magic set
- NMAGIC, // Disallow shared libraries and don't align sections
- // PageAlign Data, Mark Text Segment/Data segment RW
- OMAGIC // Disallow shared libraries and don't align sections,
- // Mark Text Segment/Data segment RW
+ // 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; }
- // Page size.
- virtual uint64_t getPageSize() const {
- if (_maxPageSize)
- return *_maxPageSize;
- return 0x1000;
- }
- virtual void setMaxPageSize(uint64_t pagesize) {
- _maxPageSize = pagesize;
- }
+ 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; }
@@ -85,9 +125,9 @@ public:
/// created for every undefined symbol that are present in the dynamic table
/// in the shared library
bool useShlibUndefines() const { return _useShlibUndefines; }
- /// @}
- /// \brief Does this relocation belong in the dynamic relocation table?
+ /// \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.
@@ -95,20 +135,20 @@ public:
/// table.
virtual bool isDynamicRelocation(const Reference &) const { return false; }
- /// \brief Is this a copy relocation?
+ /// \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;
- }
+ virtual bool isCopyRelocation(const Reference &) const { return false; }
bool validateImpl(raw_ostream &diagnostics) override;
- /// \brief Does the linker allow dynamic libraries to be linked with?
+ /// \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
- virtual bool allowLinkWithDynamicLibraries() const {
+ bool allowLinkWithDynamicLibraries() const {
if (_outputMagic == OutputMagic::NMAGIC ||
_outputMagic == OutputMagic::OMAGIC || _noAllowDynamicLibraries)
return false;
@@ -118,7 +158,7 @@ public:
/// \brief Use Elf_Rela format to output relocation tables.
virtual bool isRelaOutputFormat() const { return true; }
- /// \brief Does this relocation belong in the dynamic plt relocation table?
+ /// \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
@@ -133,30 +173,28 @@ public:
}
/// \brief The dynamic linker path set by the --dynamic-linker option
- virtual StringRef getInterpreter() const {
- if (_dynamicLinkerArg)
- return _dynamicLinkerPath;
+ StringRef getInterpreter() const {
+ if (_dynamicLinkerPath.hasValue())
+ return _dynamicLinkerPath.getValue();
return getDefaultInterpreter();
}
- /// \brief Does the output have dynamic sections.
- virtual bool isDynamic() const;
+ /// \brief Returns true if the output have dynamic sections.
+ bool isDynamic() const;
- /// \brief Are we creating a shared library?
- virtual bool isDynamicLibrary() const {
- return _outputELFType == llvm::ELF::ET_DYN;
- }
+ /// \brief Returns true if we are creating a shared library.
+ bool isDynamicLibrary() const { return _outputELFType == llvm::ELF::ET_DYN; }
- /// \brief Is the relocation a relative relocation
+ /// \brief Returns true if a given relocation is a relative relocation.
virtual bool isRelativeReloc(const Reference &r) const;
- template <typename ELFT>
- lld::elf::TargetHandler<ELFT> &getTargetHandler() const {
+ TargetHandler &getTargetHandler() const {
assert(_targetHandler && "Got null TargetHandler!");
- return static_cast<lld::elf::TargetHandler<ELFT> &>(*_targetHandler.get());
+ return *_targetHandler;
}
- TargetHandlerBase *targetHandler() const { return _targetHandler.get(); }
+ virtual void registerRelocationNames(Registry &) = 0;
+
void addPasses(PassManager &pm) override;
void setTriple(llvm::Triple trip) { _triple = trip; }
@@ -174,19 +212,16 @@ public:
void finalizeInputFiles() override;
/// \brief Set the dynamic linker path
- void setInterpreter(StringRef dynamicLinker) {
- _dynamicLinkerArg = true;
- _dynamicLinkerPath = dynamicLinker;
- }
+ 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
- virtual void setOutputMagic(OutputMagic magic) { _outputMagic = magic; }
+ void setOutputMagic(OutputMagic magic) { _outputMagic = magic; }
/// \brief Disallow dynamic libraries during linking
- virtual void setNoAllowDynamicLibraries() { _noAllowDynamicLibraries = true; }
+ void setNoAllowDynamicLibraries() { _noAllowDynamicLibraries = true; }
/// Searches directories for a match on the input File
ErrorOr<StringRef> searchLibrary(StringRef libName) const;
@@ -220,34 +255,17 @@ public:
_absoluteSymbols[name] = addr;
}
- void setSharedObjectName(StringRef soname) {
- _soname = soname;
- }
-
StringRef sharedObjectName() const { return _soname; }
+ void setSharedObjectName(StringRef soname) { _soname = soname; }
StringRef getSysroot() const { return _sysrootPath; }
+ void setSysroot(StringRef path) { _sysrootPath = path; }
- /// \brief Set path to the system root
- 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);
- }
+ void addRpath(StringRef path) { _rpathList.push_back(path); }
+ range<const StringRef *> getRpathList() const { return _rpathList; }
- range<const StringRef *> getRpathLinkList() const {
- return _rpathLinkList;
- }
+ 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;
@@ -262,13 +280,10 @@ public:
}
// add search path to list.
- virtual bool addSearchPath(StringRef ref) {
- _inputSearchPaths.push_back(ref);
- return true;
- }
+ void addSearchPath(StringRef ref) { _inputSearchPaths.push_back(ref); }
// Retrieve search path list.
- StringRefVector getSearchPaths() { return _inputSearchPaths; };
+ 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
@@ -290,6 +305,26 @@ public:
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; }
@@ -301,6 +336,10 @@ public:
// --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);
@@ -308,43 +347,61 @@ public:
script::Sema &linkerScriptSema() { return _linkerScriptSema; }
const script::Sema &linkerScriptSema() const { return _linkerScriptSema; }
-private:
- ELFLinkingContext() = delete;
+ /// 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, std::unique_ptr<TargetHandlerBase>);
+ 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; // e.g ET_EXEC
+ uint16_t _outputELFType = llvm::ELF::ET_EXEC;
llvm::Triple _triple;
- std::unique_ptr<TargetHandlerBase> _targetHandler;
- uint64_t _baseAddress;
- bool _isStaticExecutable;
- bool _noInhibitExec;
- bool _exportDynamic;
- bool _mergeCommonStrings;
- bool _useShlibUndefines;
- bool _dynamicLinkerArg;
- bool _noAllowDynamicLibraries;
- bool _mergeRODataToTextSegment;
- bool _demangle;
- bool _stripSymbols;
- bool _alignSegments;
- bool _nostdlib;
- bool _collectStats;
- llvm::Optional<uint64_t> _maxPageSize;
-
- OutputMagic _outputMagic;
+ 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;
- StringRef _dynamicLinkerPath;
- StringRef _initFunction;
- StringRef _finiFunction;
- StringRef _sysrootPath;
+ llvm::Optional<StringRef> _dynamicLinkerPath;
+ StringRef _initFunction = "_init";
+ StringRef _finiFunction = "_fini";
+ StringRef _sysrootPath = "";
StringRef _soname;
StringRefVector _rpathList;
StringRefVector _rpathLinkList;
@@ -352,11 +409,14 @@ protected:
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/ELFTargets.h b/include/lld/ReaderWriter/ELFTargets.h
deleted file mode 100644
index 3d00339818e2..000000000000
--- a/include/lld/ReaderWriter/ELFTargets.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//===- lld/ReaderWriter/ELFTargets.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_TARGETS_H
-#define LLD_READER_WRITER_ELF_TARGETS_H
-
-#include "ELFLinkingContext.h"
-
-namespace lld {
-namespace elf {
-
-#define LLVM_TARGET(TargetName) \
- class TargetName##LinkingContext final : public ELFLinkingContext { \
- public: \
- static std::unique_ptr<ELFLinkingContext> create(llvm::Triple); \
- };
-
-// FIXME: #include "llvm/Config/Targets.def"
-LLVM_TARGET(AArch64)
-LLVM_TARGET(ARM)
-LLVM_TARGET(Hexagon)
-LLVM_TARGET(Mips)
-LLVM_TARGET(X86)
-LLVM_TARGET(Example)
-LLVM_TARGET(X86_64)
-
-#undef LLVM_TARGET
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/include/lld/ReaderWriter/LinkerScript.h b/include/lld/ReaderWriter/LinkerScript.h
index ae8d18d830c6..08ccb89ce8c1 100644
--- a/include/lld/ReaderWriter/LinkerScript.h
+++ b/include/lld/ReaderWriter/LinkerScript.h
@@ -20,6 +20,7 @@
#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"
@@ -78,6 +79,9 @@ public:
kw_entry,
kw_exclude_file,
kw_extern,
+ kw_filehdr,
+ kw_fill,
+ kw_flags,
kw_group,
kw_hidden,
kw_input,
@@ -85,6 +89,7 @@ public:
kw_length,
kw_memory,
kw_origin,
+ kw_phdrs,
kw_provide,
kw_provide_hidden,
kw_only_if_ro,
@@ -160,6 +165,7 @@ public:
enum class Kind {
Entry,
Extern,
+ Fill,
Group,
Input,
InputSectionsCmd,
@@ -170,6 +176,7 @@ public:
OutputFormat,
OutputSectionDescription,
Overlay,
+ PHDRS,
SearchDir,
Sections,
SortedGroup,
@@ -191,6 +198,14 @@ private:
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)
@@ -212,10 +227,7 @@ class OutputFormat : public Command {
public:
OutputFormat(Parser &ctx, const SmallVectorImpl<StringRef> &formats)
: Command(ctx, Kind::OutputFormat) {
- size_t numFormats = formats.size();
- StringRef *formatsStart = getAllocator().Allocate<StringRef>(numFormats);
- std::copy(std::begin(formats), std::end(formats), formatsStart);
- _formats = llvm::makeArrayRef(formatsStart, numFormats);
+ _formats = save_array<StringRef>(getAllocator(), formats);
}
static bool classof(const Command *c) {
@@ -274,10 +286,7 @@ class PathList : public Command {
public:
PathList(Parser &ctx, StringRef name, const SmallVectorImpl<Path> &paths)
: Command(ctx, K), _name(name) {
- size_t numPaths = paths.size();
- Path *pathsStart = getAllocator().template Allocate<Path>(numPaths);
- std::copy(std::begin(paths), std::end(paths), pathsStart);
- _paths = llvm::makeArrayRef(pathsStart, numPaths);
+ _paths = save_array<Path>(getAllocator(), paths);
}
static bool classof(const Command *c) { return c->getKind() == K; }
@@ -382,7 +391,8 @@ public:
Kind getKind() const { return _kind; }
inline llvm::BumpPtrAllocator &getAllocator() const;
virtual void dump(raw_ostream &os) const = 0;
- virtual ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const = 0;
+ virtual ErrorOr<int64_t>
+ evalExpr(const SymbolTableTy &symbolTable = SymbolTableTy()) const = 0;
virtual ~Expression() {}
protected:
@@ -406,7 +416,7 @@ public:
return c->getKind() == Kind::Constant;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
uint64_t _num;
@@ -422,7 +432,7 @@ public:
return c->getKind() == Kind::Symbol;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
StringRef _name;
@@ -433,11 +443,7 @@ public:
FunctionCall(Parser &ctx, StringRef name,
const SmallVectorImpl<const Expression *> &args)
: Expression(ctx, Kind::FunctionCall), _name(name) {
- size_t numArgs = args.size();
- const Expression **argsStart =
- getAllocator().Allocate<const Expression *>(numArgs);
- std::copy(std::begin(args), std::end(args), argsStart);
- _args = llvm::makeArrayRef(argsStart, numArgs);
+ _args = save_array<const Expression *>(getAllocator(), args);
}
void dump(raw_ostream &os) const override;
@@ -446,7 +452,7 @@ public:
return c->getKind() == Kind::FunctionCall;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
StringRef _name;
@@ -468,7 +474,7 @@ public:
return c->getKind() == Kind::Unary;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
Operation _op;
@@ -503,7 +509,7 @@ public:
return c->getKind() == Kind::BinOp;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
Operation _op;
@@ -538,7 +544,7 @@ public:
return c->getKind() == Kind::TernaryConditional;
}
- ErrorOr<int64_t> evalExpr(SymbolTableTy &symbolTable) const override;
+ ErrorOr<int64_t> evalExpr(const SymbolTableTy &symbolTable) const override;
private:
const Expression *_conditional;
@@ -647,11 +653,7 @@ public:
InputSectionSortedGroup(Parser &ctx, WildcardSortMode sort,
const SmallVectorImpl<const InputSection *> &sections)
: InputSection(ctx, Kind::SortedGroup), _sortMode(sort) {
- size_t numSections = sections.size();
- const InputSection **sectionsStart =
- getAllocator().Allocate<const InputSection *>(numSections);
- std::copy(std::begin(sections), std::end(sections), sectionsStart);
- _sections = llvm::makeArrayRef(sectionsStart, numSections);
+ _sections = save_array<const InputSection *>(getAllocator(), sections);
}
void dump(raw_ostream &os) const override;
@@ -691,11 +693,7 @@ public:
: Command(ctx, Kind::InputSectionsCmd), _memberName(memberName),
_archiveName(archiveName), _keep(keep), _fileSortMode(fileSortMode),
_archiveSortMode(archiveSortMode) {
- size_t numSections = sections.size();
- const InputSection **sectionsStart =
- getAllocator().Allocate<const InputSection *>(numSections);
- std::copy(std::begin(sections), std::end(sections), sectionsStart);
- _sections = llvm::makeArrayRef(sectionsStart, numSections);
+ _sections = save_array<const InputSection *>(getAllocator(), sections);
}
void dump(raw_ostream &os) const override;
@@ -720,6 +718,24 @@ private:
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:
@@ -743,18 +759,16 @@ public:
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)
+ 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) {
- size_t numCommands = outputSectionCommands.size();
- const Command **commandsStart =
- getAllocator().Allocate<const Command *>(numCommands);
- std::copy(std::begin(outputSectionCommands),
- std::end(outputSectionCommands), commandsStart);
- _outputSectionCommands = llvm::makeArrayRef(commandsStart, numCommands);
+ _outputSectionCommands =
+ save_array<const Command *>(getAllocator(), outputSectionCommands);
+ _phdrs = save_array<StringRef>(getAllocator(), phdrs);
}
static bool classof(const Command *c) {
@@ -766,6 +780,8 @@ public:
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;
@@ -779,6 +795,7 @@ private:
bool _discard;
Constraint _constraint;
llvm::ArrayRef<const Command *> _outputSectionCommands;
+ ArrayRef<StringRef> _phdrs;
};
/// Represents an Overlay structure as documented in
@@ -794,6 +811,52 @@ public:
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:
@@ -802,12 +865,8 @@ public:
Sections(Parser &ctx,
const SmallVectorImpl<const Command *> &sectionsCommands)
: Command(ctx, Kind::Sections) {
- size_t numCommands = sectionsCommands.size();
- const Command **commandsStart =
- getAllocator().Allocate<const Command *>(numCommands);
- std::copy(std::begin(sectionsCommands), std::end(sectionsCommands),
- commandsStart);
- _sectionsCommands = llvm::makeArrayRef(commandsStart, numCommands);
+ _sectionsCommands =
+ save_array<const Command *>(getAllocator(), sectionsCommands);
}
static bool classof(const Command *c) {
@@ -844,11 +903,7 @@ public:
Memory(Parser &ctx,
const SmallVectorImpl<const MemoryBlock *> &blocks)
: Command(ctx, Kind::Memory) {
- size_t numBlocks = blocks.size();
- const MemoryBlock **blocksStart =
- getAllocator().Allocate<const MemoryBlock *>(numBlocks);
- std::copy(std::begin(blocks), std::end(blocks), blocksStart);
- _blocks = llvm::makeArrayRef(blocksStart, numBlocks);
+ _blocks = save_array<const MemoryBlock *>(getAllocator(), blocks);
}
static bool classof(const Command *c) {
@@ -869,11 +924,7 @@ public:
Extern(Parser &ctx,
const SmallVectorImpl<StringRef> &symbols)
: Command(ctx, Kind::Extern) {
- size_t numSymbols = symbols.size();
- StringRef *symbolsStart =
- getAllocator().Allocate<StringRef>(numSymbols);
- std::copy(std::begin(symbols), std::end(symbols), symbolsStart);
- _symbols = llvm::makeArrayRef(symbolsStart, numSymbols);
+ _symbols = save_array<StringRef>(getAllocator(), symbols);
}
static bool classof(const Command *c) {
@@ -1133,6 +1184,8 @@ private:
/// }
const InputSectionsCmd *parseInputSectionsCmd();
+ const FillCmd *parseFillCmd();
+
/// Parse output section description statements.
/// Example:
///
@@ -1145,6 +1198,10 @@ private:
/// Stub for parsing overlay commands. Currently unimplemented.
const Overlay *parseOverlay();
+ const PHDR *parsePHDR();
+
+ PHDRS *parsePHDRS();
+
/// Parse the SECTIONS linker script command.
/// Example:
///
@@ -1231,7 +1288,7 @@ public:
/// 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.
- void perform();
+ 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
@@ -1273,6 +1330,15 @@ public:
/// 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:
@@ -1314,6 +1380,14 @@ private:
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
@@ -1370,8 +1444,6 @@ private:
void linearizeAST(const InputSectionsCmd *inputSections);
void linearizeAST(const InputSection *inputSection);
- void perform(const LinkerScript *ls);
-
std::vector<std::unique_ptr<Parser>> _scripts;
std::vector<const Command *> _layoutCommands;
std::unordered_multimap<std::string, int> _memberToLayoutOrder;
@@ -1381,6 +1453,9 @@ private:
llvm::DenseSet<int> _deliveredExprs;
mutable llvm::StringSet<> _definedSymbols;
+ llvm::StringMap<llvm::SmallVector<const PHDR *, 2>> _sectionToPHDR;
+ const PHDR *_programPHDR;
+
Expression::SymbolTableTy _symbolTable;
};
diff --git a/include/lld/ReaderWriter/MachOLinkingContext.h b/include/lld/ReaderWriter/MachOLinkingContext.h
index 8e253a1235f1..dc44d3f303f8 100644
--- a/include/lld/ReaderWriter/MachOLinkingContext.h
+++ b/include/lld/ReaderWriter/MachOLinkingContext.h
@@ -27,12 +27,13 @@ namespace mach_o {
class ArchHandler;
class MachODylibFile;
class MachOFile;
+class SectCreateFile;
}
class MachOLinkingContext : public LinkingContext {
public:
MachOLinkingContext();
- ~MachOLinkingContext();
+ ~MachOLinkingContext() override;
enum Arch {
arch_unknown,
@@ -63,6 +64,13 @@ public:
noDebugMap // -S option
};
+ enum class UndefinedMode {
+ error,
+ warning,
+ suppress,
+ dynamicLookup
+ };
+
/// 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.
@@ -72,7 +80,7 @@ public:
bool validateImpl(raw_ostream &diagnostics) override;
std::string demangle(StringRef symbolName) const override;
- bool createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
+ void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
uint32_t getCPUType() const;
uint32_t getCPUSubType() const;
@@ -129,6 +137,9 @@ public:
bool PIE() const { return _pie; }
void setPIE(bool pie) { _pie = pie; }
+ uint64_t stackSize() const { return _stackSize; }
+ void setStackSize(uint64_t stackSize) { _stackSize = stackSize; }
+
uint64_t baseAddress() const { return _baseAddress; }
void setBaseAddress(uint64_t baseAddress) { _baseAddress = baseAddress; }
@@ -201,6 +212,30 @@ public:
/// when linking a binary that does not use any of its symbols.
bool deadStrippableDylib() const { return _deadStrippableDylib; }
+ /// \brief Whether or not to use flat namespace.
+ ///
+ /// MachO usually uses a two-level namespace, where each external symbol
+ /// referenced by the target is associated with the dylib that will provide
+ /// the symbol's definition at runtime. Using flat namespace overrides this
+ /// behavior: the linker searches all dylibs on the command line and all
+ /// dylibs those original dylibs depend on, but does not record which dylib
+ /// an external symbol came from. At runtime dyld again searches all images
+ /// and uses the first definition it finds. In addition, any undefines in
+ /// loaded flat_namespace dylibs must be resolvable at build time.
+ bool useFlatNamespace() const { return _flatNamespace; }
+
+ /// \brief How to handle undefined symbols.
+ ///
+ /// Options are:
+ /// * error: Report an error and terminate linking.
+ /// * warning: Report a warning, but continue linking.
+ /// * suppress: Ignore and continue linking.
+ /// * dynamic_lookup: For use with -twolevel namespace: Records source dylibs
+ /// for symbols that are defined in a linked dylib at static link time.
+ /// Undefined symbols are handled by searching all loaded images at
+ /// runtime.
+ UndefinedMode undefinedMode() const { return _undefinedMode; }
+
/// \brief The path to the executable that will load the bundle at runtime.
///
/// When building a Mach-O bundle, this executable will be examined if there
@@ -215,6 +250,14 @@ public:
void setDeadStrippableDylib(bool deadStrippable) {
_deadStrippableDylib = deadStrippable;
}
+ void setUseFlatNamespace(bool flatNamespace) {
+ _flatNamespace = flatNamespace;
+ }
+
+ void setUndefinedMode(UndefinedMode undefinedMode) {
+ _undefinedMode = undefinedMode;
+ }
+
void setBundleLoader(StringRef loader) { _bundleLoader = loader; }
void setPrintAtoms(bool value=true) { _printAtoms = value; }
void setTestingFileUsage(bool value = true) {
@@ -228,10 +271,14 @@ public:
const StringRefVector &rpaths() const { return _rpaths; }
/// Add section alignment constraint on final layout.
- void addSectionAlignment(StringRef seg, StringRef sect, uint8_t align2);
+ void addSectionAlignment(StringRef seg, StringRef sect, uint16_t align);
+
+ /// \brief Add a section based on a command-line sectcreate option.
+ void addSectCreateSection(StringRef seg, StringRef sect,
+ std::unique_ptr<MemoryBuffer> content);
/// Returns true if specified section had alignment constraints.
- bool sectionAligned(StringRef seg, StringRef sect, uint8_t &align2) const;
+ bool sectionAligned(StringRef seg, StringRef sect, uint16_t &align) const;
StringRef dyldPath() const { return "/usr/lib/dyld"; }
@@ -241,6 +288,9 @@ public:
// GOT creation Pass should be run.
bool needsGOTPass() const;
+ /// Pass to add TLV sections.
+ bool needsTLVPass() const;
+
/// Pass to transform __compact_unwind into __unwind_info should be run.
bool needsCompactUnwindPass() const;
@@ -271,8 +321,7 @@ public:
/// If the memoryBuffer is a fat file with a slice for the current arch,
/// this method will return the offset and size of that slice.
- bool sliceFromFatFile(const MemoryBuffer &mb, uint32_t &offset,
- uint32_t &size);
+ bool sliceFromFatFile(MemoryBufferRef mb, uint32_t &offset, uint32_t &size);
/// Returns if a command line option specified dylib is an upward link.
bool isUpwardDylib(StringRef installName) const;
@@ -296,6 +345,11 @@ public:
bool customAtomOrderer(const DefinedAtom *left, const DefinedAtom *right,
bool &leftBeforeRight) const;
+ /// Return the 'flat namespace' file. This is the file that supplies
+ /// atoms for otherwise undefined symbols when the -flat_namespace or
+ /// -undefined dynamic_lookup options are used.
+ File* flatNamespaceFile() const { return _flatNamespaceFile; }
+
private:
Writer &writer() const override;
mach_o::MachODylibFile* loadIndirectDylib(StringRef path);
@@ -312,7 +366,7 @@ private:
struct SectionAlign {
StringRef segmentName;
StringRef sectionName;
- uint8_t align2;
+ uint16_t align;
};
struct OrderFileNode {
@@ -339,10 +393,13 @@ private:
uint64_t _pageZeroSize;
uint64_t _pageSize;
uint64_t _baseAddress;
+ uint64_t _stackSize;
uint32_t _compatibilityVersion;
uint32_t _currentVersion;
StringRef _installName;
StringRefVector _rpaths;
+ bool _flatNamespace;
+ UndefinedMode _undefinedMode;
bool _deadStrippableDylib;
bool _printAtoms;
bool _testingFileUsage;
@@ -356,14 +413,17 @@ private:
mutable std::set<mach_o::MachODylibFile*> _allDylibs;
mutable std::set<mach_o::MachODylibFile*> _upwardDylibs;
mutable std::vector<std::unique_ptr<File>> _indirectDylibs;
+ mutable std::mutex _dylibsMutex;
ExportMode _exportMode;
llvm::StringSet<> _exportedSymbols;
DebugInfoMode _debugInfoMode;
std::unique_ptr<llvm::raw_fd_ostream> _dependencyInfo;
llvm::StringMap<std::vector<OrderFileNode>> _orderFiles;
unsigned _orderFileEntries;
+ File *_flatNamespaceFile;
+ mach_o::SectCreateFile *_sectCreateFile = nullptr;
};
} // end namespace lld
-#endif
+#endif // LLD_READER_WRITER_MACHO_LINKING_CONTEXT_H
diff --git a/include/lld/ReaderWriter/PECOFFLinkingContext.h b/include/lld/ReaderWriter/PECOFFLinkingContext.h
deleted file mode 100644
index cccb8ac03b6e..000000000000
--- a/include/lld/ReaderWriter/PECOFFLinkingContext.h
+++ /dev/null
@@ -1,463 +0,0 @@
-//===- lld/ReaderWriter/PECOFFLinkingContext.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_PECOFF_LINKING_CONTEXT_H
-#define LLD_READER_WRITER_PECOFF_LINKING_CONTEXT_H
-
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Writer.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/COFF.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileUtilities.h"
-#include <map>
-#include <mutex>
-#include <set>
-#include <vector>
-
-using llvm::COFF::MachineTypes;
-using llvm::COFF::WindowsSubsystem;
-
-static const uint8_t DEFAULT_DOS_STUB[128] = {'M', 'Z'};
-
-namespace lld {
-
-class PECOFFLinkingContext : public LinkingContext {
-public:
- PECOFFLinkingContext()
- : _mutex(), _allocMutex(), _hasEntry(true),
- _baseAddress(invalidBaseAddress), _stackReserve(1024 * 1024),
- _stackCommit(4096), _heapReserve(1024 * 1024), _heapCommit(4096),
- _noDefaultLibAll(false), _sectionDefaultAlignment(4096),
- _subsystem(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN),
- _machineType(llvm::COFF::IMAGE_FILE_MACHINE_I386), _imageVersion(0, 0),
- _minOSVersion(6, 0), _nxCompat(true), _largeAddressAware(false),
- _allowBind(true), _allowIsolation(true), _swapRunFromCD(false),
- _swapRunFromNet(false), _baseRelocationEnabled(true),
- _terminalServerAware(true), _dynamicBaseEnabled(true),
- _createManifest(true), _embedManifest(false), _manifestId(1),
- _manifestUAC(true), _manifestLevel("'asInvoker'"),
- _manifestUiAccess("'false'"), _isDll(false), _highEntropyVA(true),
- _requireSEH(false), _noSEH(false), _implib(""), _debug(false),
- _pdbFilePath(""), _dosStub(llvm::makeArrayRef(DEFAULT_DOS_STUB)),
- _parseDirectives(nullptr) {
- setDeadStripping(true);
- }
-
- struct Version {
- Version(int v1, int v2) : majorVersion(v1), minorVersion(v2) {}
- int majorVersion;
- int minorVersion;
- };
-
- struct ExportDesc {
- ExportDesc()
- : ordinal(-1), noname(false), isData(false), isPrivate(false) {}
-
- bool operator<(const ExportDesc &other) const {
- return getExternalName().compare(other.getExternalName()) < 0;
- }
-
- StringRef getRealName() const {
- return mangledName.empty() ? name : mangledName;
- }
-
- StringRef getExternalName() const {
- return externalName.empty() ? name : externalName;
- }
-
- std::string name;
- std::string externalName;
- std::string mangledName;
- int ordinal;
- bool noname;
- bool isData;
- bool isPrivate;
- };
-
- typedef bool (*ParseDirectives)(int, const char **, PECOFFLinkingContext &,
- raw_ostream &);
-
- /// \brief Casting support
- static bool classof(const LinkingContext *info) { return true; }
-
- Writer &writer() const override;
- bool validateImpl(raw_ostream &diagnostics) override;
-
- void addPasses(PassManager &pm) override;
-
- bool createImplicitFiles(
- std::vector<std::unique_ptr<File> > &result) override;
-
- bool is64Bit() const {
- return _machineType == llvm::COFF::IMAGE_FILE_MACHINE_AMD64;
- }
-
- // Returns a set of all defined symbols in input files.
- const std::set<std::string> &definedSymbols();
-
- /// Page size of x86 processor. Some data needs to be aligned at page boundary
- /// when loaded into memory.
- uint64_t getPageSize() const {
- return 0x1000;
- }
-
- void appendInputSearchPath(StringRef dirPath) {
- _inputSearchPaths.push_back(dirPath);
- }
-
- const std::vector<StringRef> getInputSearchPaths() {
- return _inputSearchPaths;
- }
-
- void registerTemporaryFile(StringRef path) {
- std::unique_ptr<llvm::FileRemover> fileRemover(
- new llvm::FileRemover(Twine(allocate(path))));
- _tempFiles.push_back(std::move(fileRemover));
- }
-
- StringRef searchLibraryFile(StringRef path) const;
-
- StringRef decorateSymbol(StringRef name) const;
- StringRef undecorateSymbol(StringRef name) const;
-
- void setEntrySymbolName(StringRef name) { _entry = name; }
- StringRef getEntrySymbolName() const { return _entry; }
-
- void setHasEntry(bool val) { _hasEntry = val; }
- bool hasEntry() const { return _hasEntry; }
-
- void setBaseAddress(uint64_t addr) { _baseAddress = addr; }
- uint64_t getBaseAddress() const;
-
- void setStackReserve(uint64_t size) { _stackReserve = size; }
- void setStackCommit(uint64_t size) { _stackCommit = size; }
- uint64_t getStackReserve() const { return _stackReserve; }
- uint64_t getStackCommit() const { return _stackCommit; }
-
- void setHeapReserve(uint64_t size) { _heapReserve = size; }
- void setHeapCommit(uint64_t size) { _heapCommit = size; }
- uint64_t getHeapReserve() const { return _heapReserve; }
- uint64_t getHeapCommit() const { return _heapCommit; }
-
- void setSectionDefaultAlignment(uint32_t val) {
- _sectionDefaultAlignment = val;
- }
- uint32_t getSectionDefaultAlignment() const {
- return _sectionDefaultAlignment;
- }
-
- void setSubsystem(WindowsSubsystem ss) { _subsystem = ss; }
- WindowsSubsystem getSubsystem() const { return _subsystem; }
-
- void setMachineType(MachineTypes type) { _machineType = type; }
- MachineTypes getMachineType() const { return _machineType; }
-
- void setImageVersion(const Version &version) { _imageVersion = version; }
- Version getImageVersion() const { return _imageVersion; }
-
- void setMinOSVersion(const Version &version) { _minOSVersion = version; }
- Version getMinOSVersion() const { return _minOSVersion; }
-
- void setNxCompat(bool nxCompat) { _nxCompat = nxCompat; }
- bool isNxCompat() const { return _nxCompat; }
-
- void setLargeAddressAware(bool val) { _largeAddressAware = val; }
- bool getLargeAddressAware() const { return _largeAddressAware; }
-
- void setAllowBind(bool val) { _allowBind = val; }
- bool getAllowBind() const { return _allowBind; }
-
- void setAllowIsolation(bool val) { _allowIsolation = val; }
- bool getAllowIsolation() const { return _allowIsolation; }
-
- void setSwapRunFromCD(bool val) { _swapRunFromCD = val; }
- bool getSwapRunFromCD() const { return _swapRunFromCD; }
-
- void setSwapRunFromNet(bool val) { _swapRunFromNet = val; }
- bool getSwapRunFromNet() const { return _swapRunFromNet; }
-
- void setBaseRelocationEnabled(bool val) { _baseRelocationEnabled = val; }
- bool getBaseRelocationEnabled() const { return _baseRelocationEnabled; }
-
- void setTerminalServerAware(bool val) { _terminalServerAware = val; }
- bool isTerminalServerAware() const { return _terminalServerAware; }
-
- void setDynamicBaseEnabled(bool val) { _dynamicBaseEnabled = val; }
- bool getDynamicBaseEnabled() const { return _dynamicBaseEnabled; }
-
- void setCreateManifest(bool val) { _createManifest = val; }
- bool getCreateManifest() const { return _createManifest; }
-
- void setManifestOutputPath(std::string val) { _manifestOutputPath = val; }
- const std::string &getManifestOutputPath() const {
- return _manifestOutputPath;
- }
-
- void setEmbedManifest(bool val) { _embedManifest = val; }
- bool getEmbedManifest() const { return _embedManifest; }
-
- void setManifestId(int val) { _manifestId = val; }
- int getManifestId() const { return _manifestId; }
-
- void setManifestUAC(bool val) { _manifestUAC = val; }
- bool getManifestUAC() const { return _manifestUAC; }
-
- void setManifestLevel(std::string val) { _manifestLevel = std::move(val); }
- const std::string &getManifestLevel() const { return _manifestLevel; }
-
- void setManifestUiAccess(std::string val) { _manifestUiAccess = val; }
- const std::string &getManifestUiAccess() const { return _manifestUiAccess; }
-
- void setManifestDependency(std::string val) { _manifestDependency = val; }
- const std::string &getManifestDependency() const {
- return _manifestDependency;
- }
-
- void setIsDll(bool val) { _isDll = val; }
- bool isDll() const { return _isDll; }
-
- void setSafeSEH(bool val) {
- if (val)
- _requireSEH = true;
- else
- _noSEH = true;
- }
- bool requireSEH() const { return _requireSEH; }
- bool noSEH() const { return _noSEH; }
-
- void setHighEntropyVA(bool val) { _highEntropyVA = val; }
- bool getHighEntropyVA() const { return _highEntropyVA; }
-
- void setOutputImportLibraryPath(const std::string &val) { _implib = val; }
- std::string getOutputImportLibraryPath() const;
-
- void setDebug(bool val) { _debug = val; }
- bool getDebug() { return _debug; }
-
- void setPDBFilePath(StringRef str) { _pdbFilePath = str; }
- std::string getPDBFilePath() const;
-
- void addDelayLoadDLL(StringRef dll) {
- _delayLoadDLLs.insert(dll.lower());
- }
- bool isDelayLoadDLL(StringRef dll) const {
- return _delayLoadDLLs.count(dll.lower()) == 1;
- }
-
- StringRef getOutputSectionName(StringRef sectionName) const;
- bool addSectionRenaming(raw_ostream &diagnostics,
- StringRef from, StringRef to);
-
- const std::set<std::string> &getAlternateNames(StringRef name) {
- return _alternateNames[name];
- }
-
- void addAlternateName(StringRef weak, StringRef def) {
- _alternateNames[def].insert(weak);
- }
-
- void addNoDefaultLib(StringRef path) {
- if (path.endswith_lower(".lib"))
- _noDefaultLibs.insert(path.drop_back(4).lower());
- else
- _noDefaultLibs.insert(path.lower());
- }
-
- bool hasNoDefaultLib(StringRef path) const {
- if (path.endswith_lower(".lib"))
- return _noDefaultLibs.count(path.drop_back(4).lower()) > 0;
- return _noDefaultLibs.count(path.lower()) > 0;
- }
-
- void setNoDefaultLibAll(bool val) { _noDefaultLibAll = val; }
- bool getNoDefaultLibAll() const { return _noDefaultLibAll; }
-
- void setSectionSetMask(StringRef sectionName, uint32_t flags);
- void setSectionClearMask(StringRef sectionName, uint32_t flags);
- uint32_t getSectionAttributes(StringRef sectionName, uint32_t flags) const;
-
- void setDosStub(ArrayRef<uint8_t> data) { _dosStub = data; }
- ArrayRef<uint8_t> getDosStub() const { return _dosStub; }
-
- void addDllExport(ExportDesc &desc);
- std::vector<ExportDesc> &getDllExports() { return _dllExports; }
- const std::vector<ExportDesc> &getDllExports() const { return _dllExports; }
-
- StringRef getDelayLoadHelperName() const {
- return is64Bit() ? "__delayLoadHelper2" : "___delayLoadHelper2@8";
- }
-
- StringRef allocate(StringRef ref) const {
- _allocMutex.lock();
- char *x = _allocator.Allocate<char>(ref.size() + 1);
- _allocMutex.unlock();
- memcpy(x, ref.data(), ref.size());
- x[ref.size()] = '\0';
- return x;
- }
-
- ArrayRef<uint8_t> allocate(ArrayRef<uint8_t> array) const {
- size_t size = array.size();
- _allocMutex.lock();
- uint8_t *p = _allocator.Allocate<uint8_t>(size);
- _allocMutex.unlock();
- memcpy(p, array.data(), size);
- return ArrayRef<uint8_t>(p, p + array.size());
- }
-
- template <typename T> T &allocateCopy(const T &x) const {
- _allocMutex.lock();
- T *r = new (_allocator) T(x);
- _allocMutex.unlock();
- return *r;
- }
-
- void addLibraryFile(std::unique_ptr<FileNode> file);
-
- void setModuleDefinitionFile(const std::string val) {
- _moduleDefinitionFile = val;
- }
- std::string getModuleDefinitionFile() const {
- return _moduleDefinitionFile;
- }
-
- std::recursive_mutex &getMutex() { return _mutex; }
-
- void setParseDirectives(ParseDirectives parseDirectives) {
- _parseDirectives = parseDirectives;
- }
-
- ParseDirectives getParseDirectives() {
- return _parseDirectives;
- }
-
-protected:
- /// Method to create a internal file for the entry symbol
- std::unique_ptr<File> createEntrySymbolFile() const override;
-
- /// Method to create a internal file for an undefined symbol
- std::unique_ptr<File> createUndefinedSymbolFile() const override;
-
-private:
- enum : uint64_t {
- invalidBaseAddress = UINT64_MAX,
- pe32DefaultBaseAddress = 0x400000U,
- pe32PlusDefaultBaseAddress = 0x140000000U
- };
-
- std::recursive_mutex _mutex;
- mutable std::mutex _allocMutex;
-
- std::string _entry;
-
- // False if /noentry option is given.
- bool _hasEntry;
-
- // The start address for the program. The default value for the executable is
- // 0x400000, but can be altered using /base command line option.
- uint64_t _baseAddress;
-
- uint64_t _stackReserve;
- uint64_t _stackCommit;
- uint64_t _heapReserve;
- uint64_t _heapCommit;
- bool _noDefaultLibAll;
- uint32_t _sectionDefaultAlignment;
- WindowsSubsystem _subsystem;
- MachineTypes _machineType;
- Version _imageVersion;
- Version _minOSVersion;
- bool _nxCompat;
- bool _largeAddressAware;
- bool _allowBind;
- bool _allowIsolation;
- bool _swapRunFromCD;
- bool _swapRunFromNet;
- bool _baseRelocationEnabled;
- bool _terminalServerAware;
- bool _dynamicBaseEnabled;
- bool _createManifest;
- std::string _manifestOutputPath;
- bool _embedManifest;
- int _manifestId;
- bool _manifestUAC;
- std::string _manifestLevel;
- std::string _manifestUiAccess;
- std::string _manifestDependency;
- bool _isDll;
- bool _highEntropyVA;
-
- // True if /SAFESEH option is specified. Valid only for x86. If true, LLD will
- // produce an image with SEH table. If any modules were not compatible with
- // SEH, LLD will exit with an error.
- bool _requireSEH;
-
- // True if /SAFESEH:no option is specified. Valid only for x86. If true, LLD
- // will not produce an image with SEH table even if all input object files are
- // compatible with SEH.
- bool _noSEH;
-
- // /IMPLIB command line option.
- std::string _implib;
-
- // True if /DEBUG is given.
- bool _debug;
-
- // PDB file output path. NB: this is dummy -- LLD just creates the empty file.
- std::string _pdbFilePath;
-
- // /DELAYLOAD option.
- std::set<std::string> _delayLoadDLLs;
-
- // The set to store /nodefaultlib arguments.
- std::set<std::string> _noDefaultLibs;
-
- std::vector<StringRef> _inputSearchPaths;
- std::unique_ptr<Writer> _writer;
-
- // A map for weak aliases.
- std::map<std::string, std::set<std::string>> _alternateNames;
-
- // A map for section renaming. For example, if there is an entry in the map
- // whose value is .rdata -> .text, the section contens of .rdata will be
- // merged to .text in the resulting executable.
- std::map<std::string, std::string> _renamedSections;
-
- // Section attributes specified by /section option.
- std::map<std::string, uint32_t> _sectionSetMask;
- std::map<std::string, uint32_t> _sectionClearMask;
-
- // DLLExport'ed symbols.
- std::vector<ExportDesc> _dllExports;
-
- // List of files that will be removed on destruction.
- std::vector<std::unique_ptr<llvm::FileRemover> > _tempFiles;
-
- // DOS Stub. DOS stub is data located at the beginning of PE/COFF file.
- // Windows loader do not really care about DOS stub contents, but it's usually
- // a small DOS program that prints out a message "This program requires
- // Microsoft Windows." This feature was somewhat useful before Windows 95.
- ArrayRef<uint8_t> _dosStub;
-
- // Name of the temporary file for lib.exe subcommand. For debugging
- // only.
- std::string _moduleDefinitionFile;
-
- std::set<std::string> _definedSyms;
- std::set<Node *> _seen;
-
- ParseDirectives _parseDirectives;
-};
-
-} // end namespace lld
-
-#endif
diff --git a/include/lld/ReaderWriter/RelocationHelperFunctions.h b/include/lld/ReaderWriter/RelocationHelperFunctions.h
deleted file mode 100644
index 8738e91ebabc..000000000000
--- a/include/lld/ReaderWriter/RelocationHelperFunctions.h
+++ /dev/null
@@ -1,57 +0,0 @@
-//===- lld/ReaderWriter/RelocationHelperFunctions.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_RELOCATION_HELPER_FUNCTIONS_H
-#define LLD_READER_WRITER_RELOCATION_HELPER_FUNCTIONS_H
-
-namespace lld {
-
-/// Gather val's bits as specified by the mask. Example:
-///
-/// Val: 0bABCDEFGHIJKLMN
-/// Mask: 0b10111100001011
-/// Output: 0b000000ACDEFKMN
-template <typename T> T gatherBits(T val, T mask) {
- T result = 0;
- size_t off = 0;
-
- for (size_t bit = 0; bit < sizeof(T) * 8; ++bit) {
- bool maskBit = (mask >> bit) & 1;
- if (maskBit) {
- bool valBit = (val >> bit) & 1;
- result |= static_cast<T>(valBit) << off;
- ++off;
- }
- }
- return result;
-}
-
-/// Scatter val's bits as specified by the mask. Example:
-///
-/// Val: 0bABCDEFG
-/// Mask: 0b10111100001011
-/// Output: 0b00ABCD0000E0FG
-template <typename T> T scatterBits(T val, T mask) {
- T result = 0;
- size_t off = 0;
-
- for (size_t bit = 0; bit < sizeof(T) * 8; ++bit) {
- bool maskBit = (mask >> bit) & 1;
- if (maskBit) {
- bool valBit = (val >> off) & 1;
- result |= static_cast<T>(valBit) << bit;
- ++off;
- }
- }
- return result;
-}
-
-} // namespace lld
-
-#endif // LLD_READER_WRITER_RELOCATION_HELPER_FUNCTIONS_H
diff --git a/include/lld/ReaderWriter/YamlContext.h b/include/lld/ReaderWriter/YamlContext.h
index a15a398ec636..b26161a15431 100644
--- a/include/lld/ReaderWriter/YamlContext.h
+++ b/include/lld/ReaderWriter/YamlContext.h
@@ -30,14 +30,10 @@ using lld::mach_o::normalized::NormalizedFile;
/// object. We need to support hetergenous yaml documents which each require
/// different context info. This struct supports all clients.
struct YamlContext {
- YamlContext()
- : _linkingContext(nullptr), _registry(nullptr), _file(nullptr),
- _normalizeMachOFile(nullptr) {}
-
- const LinkingContext *_linkingContext;
- const Registry *_registry;
- File *_file;
- NormalizedFile *_normalizeMachOFile;
+ const LinkingContext *_ctx = nullptr;
+ const Registry *_registry = nullptr;
+ File *_file = nullptr;
+ NormalizedFile *_normalizeMachOFile = nullptr;
StringRef _path;
};
diff --git a/lib/Config/Makefile b/lib/Config/Makefile
deleted file mode 100644
index b3c57f81418f..000000000000
--- a/lib/Config/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-##===- lib/Config/Makefile ---------------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL := ../..
-LIBRARYNAME := lldConfig
-
-include $(LLD_LEVEL)/Makefile
diff --git a/lib/Core/DefinedAtom.cpp b/lib/Core/DefinedAtom.cpp
index b3f81ca65a91..f1d308088ed4 100644
--- a/lib/Core/DefinedAtom.cpp
+++ b/lib/Core/DefinedAtom.cpp
@@ -76,6 +76,7 @@ DefinedAtom::ContentPermissions DefinedAtom::permissions(ContentType type) {
case typeGnuLinkOnce:
case typeUnknown:
case typeTempLTO:
+ case typeSectCreate:
return permUnknown;
}
llvm_unreachable("unknown content type");
diff --git a/lib/Core/Error.cpp b/lib/Core/Error.cpp
index 24809c3869e5..3b7733746dcd 100644
--- a/lib/Core/Error.cpp
+++ b/lib/Core/Error.cpp
@@ -16,39 +16,6 @@
using namespace lld;
-class _NativeReaderErrorCategory : public std::error_category {
-public:
- const char* name() const LLVM_NOEXCEPT override {
- return "lld.native.reader";
- }
-
- std::string message(int ev) const override {
- switch (static_cast<NativeReaderError>(ev)) {
- case NativeReaderError::success:
- return "Success";
- case NativeReaderError::unknown_file_format:
- return "Unknown file format";
- case NativeReaderError::file_too_short:
- return "file truncated";
- case NativeReaderError::file_malformed:
- return "file malformed";
- case NativeReaderError::memory_error:
- return "out of memory";
- case NativeReaderError::unknown_chunk_type:
- return "unknown chunk type";
- case NativeReaderError::conflicting_target_machine:
- return "conflicting target machine";
- }
- llvm_unreachable("An enumerator of NativeReaderError does not have a "
- "message defined.");
- }
-};
-
-const std::error_category &lld::native_reader_category() {
- static _NativeReaderErrorCategory o;
- return o;
-}
-
class _YamlReaderErrorCategory : public std::error_category {
public:
const char* name() const LLVM_NOEXCEPT override {
@@ -57,8 +24,6 @@ public:
std::string message(int ev) const override {
switch (static_cast<YamlReaderError>(ev)) {
- case YamlReaderError::success:
- return "Success";
case YamlReaderError::unknown_keyword:
return "Unknown keyword found in yaml file";
case YamlReaderError::illegal_value:
@@ -91,6 +56,14 @@ public:
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.");
@@ -102,7 +75,6 @@ const std::error_category &lld::LinkerScriptReaderCategory() {
return o;
}
-
namespace lld {
/// Temporary class to enable make_dynamic_error_code() until
@@ -110,7 +82,7 @@ namespace lld {
/// other than error_code.
class dynamic_error_category : public std::error_category {
public:
- ~dynamic_error_category() LLVM_NOEXCEPT {}
+ ~dynamic_error_category() override = default;
const char *name() const LLVM_NOEXCEPT override {
return "lld.dynamic_error";
@@ -140,6 +112,10 @@ 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);
}
@@ -148,4 +124,4 @@ std::error_code make_dynamic_error_code(const Twine &msg) {
return std::error_code(categorySingleton.add(msg.str()), categorySingleton);
}
-}
+} // namespace lld
diff --git a/lib/Core/File.cpp b/lib/Core/File.cpp
index dbac86b368aa..ac95f1016797 100644
--- a/lib/Core/File.cpp
+++ b/lib/Core/File.cpp
@@ -15,10 +15,10 @@ namespace lld {
File::~File() {}
-File::atom_collection_empty<DefinedAtom> File::_noDefinedAtoms;
-File::atom_collection_empty<UndefinedAtom> File::_noUndefinedAtoms;
-File::atom_collection_empty<SharedLibraryAtom> File::_noSharedLibraryAtoms;
-File::atom_collection_empty<AbsoluteAtom> File::_noAbsoluteAtoms;
+File::AtomVector<DefinedAtom> File::_noDefinedAtoms;
+File::AtomVector<UndefinedAtom> File::_noUndefinedAtoms;
+File::AtomVector<SharedLibraryAtom> File::_noSharedLibraryAtoms;
+File::AtomVector<AbsoluteAtom> File::_noAbsoluteAtoms;
std::error_code File::parse() {
std::lock_guard<std::mutex> lock(_parseMutex);
diff --git a/lib/Core/LinkingContext.cpp b/lib/Core/LinkingContext.cpp
index c6656b935916..cbcf25c17df2 100644
--- a/lib/Core/LinkingContext.cpp
+++ b/lib/Core/LinkingContext.cpp
@@ -24,7 +24,7 @@ LinkingContext::LinkingContext()
_warnIfCoalesableAtomsHaveDifferentCanBeNull(false),
_warnIfCoalesableAtomsHaveDifferentLoadName(false),
_printRemainingUndefines(true), _allowRemainingUndefines(false),
- _logInputFiles(false), _allowShlibUndefines(false),
+ _logInputFiles(false), _allowShlibUndefines(true),
_outputFileType(OutputFileType::Default), _nextOrdinal(0) {}
LinkingContext::~LinkingContext() {}
@@ -37,9 +37,9 @@ std::error_code LinkingContext::writeFile(const File &linkedFile) const {
return this->writer().writeFile(linkedFile, _outputPath);
}
-bool LinkingContext::createImplicitFiles(
- std::vector<std::unique_ptr<File> > &result) {
- return this->writer().createImplicitFiles(result);
+void LinkingContext::createImplicitFiles(
+ std::vector<std::unique_ptr<File>> &result) {
+ this->writer().createImplicitFiles(result);
}
std::unique_ptr<File> LinkingContext::createEntrySymbolFile() const {
diff --git a/lib/Core/Makefile b/lib/Core/Makefile
deleted file mode 100644
index 042d01a1e1b3..000000000000
--- a/lib/Core/Makefile
+++ /dev/null
@@ -1,13 +0,0 @@
-##===- lld/lib/Core/Makefile ---------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL := ../..
-LIBRARYNAME := lldCore
-
-include $(LLD_LEVEL)/Makefile
diff --git a/lib/Core/Reader.cpp b/lib/Core/Reader.cpp
index 6f8b8cbd1bf8..6069093d211e 100644
--- a/lib/Core/Reader.cpp
+++ b/lib/Core/Reader.cpp
@@ -13,7 +13,6 @@
#include "llvm/Support/Errc.h"
#include "llvm/Support/FileUtilities.h"
#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
#include <memory>
#include <system_error>
@@ -29,22 +28,17 @@ void Registry::add(std::unique_ptr<YamlIOTaggedDocumentHandler> handler) {
_yamlHandlers.push_back(std::move(handler));
}
-std::error_code
-Registry::loadFile(std::unique_ptr<MemoryBuffer> mb,
- std::vector<std::unique_ptr<File>> &result) const {
- // Get file type.
+ErrorOr<std::unique_ptr<File>>
+Registry::loadFile(std::unique_ptr<MemoryBuffer> mb) const {
+ // Get file magic.
StringRef content(mb->getBufferStart(), mb->getBufferSize());
llvm::sys::fs::file_magic fileType = llvm::sys::fs::identify_magic(content);
- // Get file extension.
- StringRef extension = llvm::sys::path::extension(mb->getBufferIdentifier());
// Ask each registered reader if it can handle this file type or extension.
for (const std::unique_ptr<Reader> &reader : _readers) {
- if (!reader->canParse(fileType, extension, *mb))
+ if (!reader->canParse(fileType, mb->getMemBufferRef()))
continue;
- if (std::error_code ec = reader->loadFile(std::move(mb), *this, result))
- return ec;
- return std::error_code();
+ return reader->loadFile(std::move(mb), *this);
}
// No Reader could parse this file.
diff --git a/lib/Core/Resolver.cpp b/lib/Core/Resolver.cpp
index 393a7ef2bfc8..8f89856c4a47 100644
--- a/lib/Core/Resolver.cpp
+++ b/lib/Core/Resolver.cpp
@@ -153,7 +153,6 @@ void Resolver::maybeAddSectionGroupOrGnuLinkOnce(const DefinedAtom &atom) {
llvm::errs() << "SymbolTable: error while merging " << atom.name()
<< "\n";
llvm::report_fatal_error("duplicate symbol error");
- return;
}
for (const Reference *r : atom) {
@@ -180,6 +179,8 @@ void Resolver::doDefinedAtom(const DefinedAtom &atom) {
<< atom.ordinal()
<< ", name="
<< atom.name()
+ << ", type="
+ << atom.contentType()
<< "\n");
// add to list of known atoms
@@ -295,11 +296,15 @@ void Resolver::updatePreloadArchiveMap() {
// Keep adding atoms until _ctx.getNextFile() returns an error. This
// function is where undefined atoms are resolved.
bool Resolver::resolveUndefines() {
+ DEBUG_WITH_TYPE("resolver",
+ llvm::dbgs() << "******** Resolving undefines:\n");
ScopedTask task(getDefaultDomain(), "resolveUndefines");
int index = 0;
std::set<File *> seen;
for (;;) {
bool undefAdded = false;
+ DEBUG_WITH_TYPE("resolver",
+ llvm::dbgs() << "Loading file #" << index << "\n");
File *file = getFile(index);
if (!file)
return true;
@@ -308,6 +313,8 @@ bool Resolver::resolveUndefines() {
<< ": " << ec.message() << "\n";
return false;
}
+ DEBUG_WITH_TYPE("resolver",
+ llvm::dbgs() << "Loaded file: " << file->path() << "\n");
file->beforeLink();
updatePreloadArchiveMap();
switch (file->kind()) {
@@ -340,6 +347,8 @@ bool Resolver::resolveUndefines() {
// switch all references to undefined or coalesced away atoms
// to the new defined atom
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)) {
@@ -388,6 +397,8 @@ static bool isBackref(const Reference *ref) {
// remove all atoms not actually used
void Resolver::deadStripOptimize() {
+ DEBUG_WITH_TYPE("resolver",
+ llvm::dbgs() << "******** Dead stripping unused atoms:\n");
ScopedTask task(getDefaultDomain(), "deadStripOptimize");
// only do this optimization with -dead_strip
if (!_ctx.deadStrip())
@@ -433,6 +444,9 @@ void Resolver::deadStripOptimize() {
// error out if some undefines remain
bool Resolver::checkUndefines() {
+ DEBUG_WITH_TYPE("resolver",
+ llvm::dbgs() << "******** Checking for undefines:\n");
+
// build vector of remaining undefined symbols
std::vector<const UndefinedAtom *> undefinedAtoms = _symbolTable.undefines();
if (_ctx.deadStrip()) {
@@ -479,6 +493,8 @@ bool Resolver::checkUndefines() {
// remove from _atoms all coaleseced away atoms
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);
@@ -487,28 +503,53 @@ void Resolver::removeCoalescedAwayAtoms() {
}
bool Resolver::resolve() {
+ DEBUG_WITH_TYPE("resolver",
+ llvm::dbgs() << "******** Resolving atom references:\n");
updatePreloadArchiveMap();
if (!resolveUndefines())
return false;
updateReferences();
deadStripOptimize();
- if (checkUndefines())
- if (!_ctx.allowRemainingUndefines())
+ if (checkUndefines()) {
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Found undefines... ");
+ if (!_ctx.allowRemainingUndefines()) {
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "which we don't allow\n");
return false;
+ }
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "which we are ok with\n");
+ }
removeCoalescedAwayAtoms();
_result->addAtoms(_atoms);
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "******** Finished resolver\n");
return true;
}
void Resolver::MergedFile::addAtoms(std::vector<const Atom *> &all) {
ScopedTask task(getDefaultDomain(), "addAtoms");
DEBUG_WITH_TYPE("resolver", llvm::dbgs() << "Resolver final atom list:\n");
+
for (const Atom *atom : all) {
- DEBUG_WITH_TYPE("resolver", llvm::dbgs()
- << llvm::format(" 0x%09lX", atom)
- << ", name="
- << atom->name()
- << "\n");
+#ifndef NDEBUG
+ if (auto *definedAtom = dyn_cast<DefinedAtom>(atom)) {
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs()
+ << llvm::format(" 0x%09lX", atom)
+ << ", file=#"
+ << definedAtom->file().ordinal()
+ << ", atom=#"
+ << definedAtom->ordinal()
+ << ", name="
+ << definedAtom->name()
+ << ", type="
+ << definedAtom->contentType()
+ << "\n");
+ } else {
+ DEBUG_WITH_TYPE("resolver", llvm::dbgs()
+ << llvm::format(" 0x%09lX", atom)
+ << ", name="
+ << atom->name()
+ << "\n");
+ }
+#endif
addAtom(*atom);
}
}
diff --git a/lib/Core/SymbolTable.cpp b/lib/Core/SymbolTable.cpp
index f3f2da9262e0..b85a83ffbfe6 100644
--- a/lib/Core/SymbolTable.cpp
+++ b/lib/Core/SymbolTable.cpp
@@ -28,7 +28,7 @@
#include <vector>
namespace lld {
-SymbolTable::SymbolTable(LinkingContext &context) : _context(context) {}
+SymbolTable::SymbolTable(LinkingContext &context) : _ctx(context) {}
bool SymbolTable::add(const UndefinedAtom &atom) { return addByName(atom); }
@@ -185,7 +185,7 @@ bool SymbolTable::addByName(const Atom &newAtom) {
// fallthrough
}
case MCR_Error:
- if (!_context.getAllowDuplicates()) {
+ if (!_ctx.getAllowDuplicates()) {
llvm::errs() << "Duplicate symbols: "
<< existing->name()
<< ":"
@@ -207,8 +207,7 @@ bool SymbolTable::addByName(const Atom &newAtom) {
const UndefinedAtom* newUndef = cast<UndefinedAtom>(&newAtom);
bool sameCanBeNull = (existingUndef->canBeNull() == newUndef->canBeNull());
- if (!sameCanBeNull &&
- _context.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
+ if (!sameCanBeNull && _ctx.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
llvm::errs() << "lld warning: undefined symbol "
<< existingUndef->name()
<< " has different weakness in "
@@ -244,14 +243,14 @@ bool SymbolTable::addByName(const Atom &newAtom) {
(curShLib->canBeNullAtRuntime() == newShLib->canBeNullAtRuntime());
bool sameName = curShLib->loadName().equals(newShLib->loadName());
if (sameName && !sameNullness &&
- _context.warnIfCoalesableAtomsHaveDifferentCanBeNull()) {
+ _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 && _context.warnIfCoalesableAtomsHaveDifferentLoadName()) {
+ 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 "
@@ -268,7 +267,7 @@ bool SymbolTable::addByName(const Atom &newAtom) {
}
// Give context a chance to change which is kept.
- _context.notifySymbolTableCoalesce(existing, &newAtom, useNew);
+ _ctx.notifySymbolTableCoalesce(existing, &newAtom, useNew);
if (useNew) {
// Update name table to use new atom.
diff --git a/lib/Core/TODO.txt b/lib/Core/TODO.txt
deleted file mode 100644
index 196a3e02c2fc..000000000000
--- a/lib/Core/TODO.txt
+++ /dev/null
@@ -1,18 +0,0 @@
-lib/Core
-~~~~~~~~
-
-* Add endianness support to the native reader and writer.
-
-* The NativeReader has lots of similar code for converting arrays of ivar
- data in mapped memory into arrays of objects. The commonality can be
- factored out, maybe templatized.
-
-* The NativeFileFormat.h is old school C structs and constants. We scope
- things better by defining constants used with a struct inside the struct
- declaration.
-
-* The native reader and writer currently just blast in memory enumeration
- values (e.g. DefinedAtom::Scope) into a byte in the disk format. To support
- future changes to the enumerations, there should be a translation layer
- to map disk values to in-memory values.
-
diff --git a/lib/Core/Writer.cpp b/lib/Core/Writer.cpp
index 39bcc9e68523..93e6438a28f5 100644
--- a/lib/Core/Writer.cpp
+++ b/lib/Core/Writer.cpp
@@ -16,8 +16,4 @@ Writer::Writer() {
Writer::~Writer() {
}
-
-bool Writer::createImplicitFiles(std::vector<std::unique_ptr<File> > &) {
- return true;
-}
} // end namespace lld
diff --git a/lib/Driver/CMakeLists.txt b/lib/Driver/CMakeLists.txt
index 5a410e7eed7e..64498ccf78ba 100644
--- a/lib/Driver/CMakeLists.txt
+++ b/lib/Driver/CMakeLists.txt
@@ -6,8 +6,6 @@ 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)
-set(LLVM_TARGET_DEFINITIONS WinLinkOptions.td)
-tablegen(LLVM WinLinkOptions.inc -gen-opt-parser-defs)
add_public_tablegen_target(DriverOptionsTableGen)
add_llvm_library(lldDriver
@@ -16,14 +14,14 @@ add_llvm_library(lldDriver
Driver.cpp
GnuLdDriver.cpp
UniversalDriver.cpp
- WinLinkDriver.cpp
- WinLinkModuleDef.cpp
LINK_LIBS
lldConfig
lldMachO
- lldPECOFF
+ lldCOFF
lldELF
+ lldELF2
lldAArch64ELFTarget
+ lldAMDGPUELFTarget
lldARMELFTarget
lldHexagonELFTarget
lldMipsELFTarget
@@ -31,7 +29,6 @@ add_llvm_library(lldDriver
lldExampleSubTarget
lldX86_64ELFTarget
lldCore
- lldNative
lldReaderWriter
lldYAML
LLVMObject
diff --git a/lib/Driver/CoreDriver.cpp b/lib/Driver/CoreDriver.cpp
index b8adee55746f..ce8648595109 100644
--- a/lib/Driver/CoreDriver.cpp
+++ b/lib/Driver/CoreDriver.cpp
@@ -56,7 +56,7 @@ static const llvm::opt::OptTable::Info infoTable[] = {
// Create OptTable class for parsing actual command line arguments
class CoreOptTable : public llvm::opt::OptTable {
public:
- CoreOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable)){}
+ CoreOptTable() : OptTable(infoTable) {}
};
} // namespace anonymous
@@ -73,32 +73,31 @@ static const Registry::KindStrings coreKindStrings[] = {
LLD_KIND_STRING_END
};
-bool CoreDriver::link(int argc, const char *argv[], raw_ostream &diagnostics) {
+bool CoreDriver::link(llvm::ArrayRef<const char *> args,
+ raw_ostream &diagnostics) {
CoreLinkingContext ctx;
// Register possible input file parsers.
- ctx.registry().addSupportNativeObjects();
ctx.registry().addSupportYamlFiles();
ctx.registry().addKindTable(Reference::KindNamespace::testing,
Reference::KindArch::all, coreKindStrings);
- if (!parse(argc, argv, ctx))
+ if (!parse(args, ctx))
return false;
return Driver::link(ctx);
}
-bool CoreDriver::parse(int argc, const char *argv[], CoreLinkingContext &ctx,
- raw_ostream &diagnostics) {
+bool CoreDriver::parse(llvm::ArrayRef<const char *> args,
+ CoreLinkingContext &ctx, raw_ostream &diagnostics) {
// Parse command line options using CoreOptions.td
- std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
CoreOptTable table;
unsigned missingIndex;
unsigned missingCount;
- parsedArgs.reset(
- table.ParseArgs(&argv[1], &argv[argc], missingIndex, missingCount));
+ llvm::opt::InputArgList parsedArgs =
+ table.ParseArgs(args.slice(1), missingIndex, missingCount);
if (missingCount) {
diagnostics << "error: missing arg value for '"
- << parsedArgs->getArgString(missingIndex) << "' expected "
+ << parsedArgs.getArgString(missingIndex) << "' expected "
<< missingCount << " argument(s).\n";
return false;
}
@@ -112,7 +111,7 @@ bool CoreDriver::parse(int argc, const char *argv[], CoreLinkingContext &ctx,
ctx.setSearchArchivesToOverrideTentativeDefinitions(false);
// Process all the arguments and create input files.
- for (auto inputArg : *parsedArgs) {
+ for (auto inputArg : parsedArgs) {
switch (inputArg->getOption().getID()) {
case OPT_mllvm:
ctx.appendLLVMOption(inputArg->getValue());
@@ -160,6 +159,8 @@ bool CoreDriver::parse(int argc, const char *argv[], CoreLinkingContext &ctx,
}
}
+ parseLLVMOptions(ctx);
+
if (ctx.getNodes().empty()) {
diagnostics << "No input files\n";
return false;
diff --git a/lib/Driver/DarwinLdDriver.cpp b/lib/Driver/DarwinLdDriver.cpp
index 2c64aeee38a5..40fad74c9529 100644
--- a/lib/Driver/DarwinLdDriver.cpp
+++ b/lib/Driver/DarwinLdDriver.cpp
@@ -20,6 +20,7 @@
#include "lld/ReaderWriter/MachOLinkingContext.h"
#include "llvm/ADT/ArrayRef.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"
@@ -68,7 +69,7 @@ static const llvm::opt::OptTable::Info infoTable[] = {
// Create OptTable class for parsing actual command line arguments
class DarwinLdOptTable : public llvm::opt::OptTable {
public:
- DarwinLdOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable)){}
+ DarwinLdOptTable() : OptTable(infoTable) {}
};
std::vector<std::unique_ptr<File>>
@@ -80,20 +81,23 @@ loadFile(MachOLinkingContext &ctx, StringRef path,
ErrorOr<std::unique_ptr<MemoryBuffer>> mbOrErr = ctx.getMemoryBuffer(path);
if (std::error_code ec = mbOrErr.getError())
return makeErrorFile(path, ec);
- std::vector<std::unique_ptr<File>> files;
- if (std::error_code ec = ctx.registry().loadFile(std::move(mbOrErr.get()), files))
+ ErrorOr<std::unique_ptr<File>> fileOrErr =
+ ctx.registry().loadFile(std::move(mbOrErr.get()));
+ if (std::error_code ec = fileOrErr.getError())
return makeErrorFile(path, ec);
- for (std::unique_ptr<File> &pf : files) {
- // If file is a dylib, inform LinkingContext about it.
- if (SharedLibraryFile *shl = dyn_cast<SharedLibraryFile>(pf.get())) {
- if (std::error_code ec = shl->parse())
- return makeErrorFile(path, ec);
- ctx.registerDylib(reinterpret_cast<mach_o::MachODylibFile*>(shl),
- upwardDylib);
- }
+ std::unique_ptr<File> &file = fileOrErr.get();
+
+ // If file is a dylib, inform LinkingContext about it.
+ if (SharedLibraryFile *shl = dyn_cast<SharedLibraryFile>(file.get())) {
+ if (std::error_code ec = shl->parse())
+ return makeErrorFile(path, ec);
+ ctx.registerDylib(reinterpret_cast<mach_o::MachODylibFile *>(shl),
+ upwardDylib);
}
if (wholeArchive)
- return parseMemberFiles(files);
+ return parseMemberFiles(std::move(file));
+ std::vector<std::unique_ptr<File>> files;
+ files.push_back(std::move(file));
return files;
}
@@ -263,42 +267,40 @@ static bool parseNumberBase16(StringRef numStr, uint64_t &baseAddress) {
namespace lld {
-bool DarwinLdDriver::linkMachO(int argc, const char *argv[],
+bool DarwinLdDriver::linkMachO(llvm::ArrayRef<const char *> args,
raw_ostream &diagnostics) {
MachOLinkingContext ctx;
- if (!parse(argc, argv, ctx, diagnostics))
+ if (!parse(args, ctx, diagnostics))
return false;
if (ctx.doNothing())
return true;
return link(ctx, diagnostics);
}
-bool DarwinLdDriver::parse(int argc, const char *argv[],
+bool DarwinLdDriver::parse(llvm::ArrayRef<const char *> args,
MachOLinkingContext &ctx, raw_ostream &diagnostics) {
// Parse command line options using DarwinLdOptions.td
- std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
DarwinLdOptTable table;
unsigned missingIndex;
unsigned missingCount;
- bool globalWholeArchive = false;
- parsedArgs.reset(
- table.ParseArgs(&argv[1], &argv[argc], missingIndex, missingCount));
+ llvm::opt::InputArgList parsedArgs =
+ table.ParseArgs(args.slice(1), missingIndex, missingCount);
if (missingCount) {
diagnostics << "error: missing arg value for '"
- << parsedArgs->getArgString(missingIndex) << "' expected "
+ << parsedArgs.getArgString(missingIndex) << "' expected "
<< missingCount << " argument(s).\n";
return false;
}
- for (auto unknownArg : parsedArgs->filtered(OPT_UNKNOWN)) {
- diagnostics << "warning: ignoring unknown argument: "
- << unknownArg->getAsString(*parsedArgs) << "\n";
+ for (auto unknownArg : parsedArgs.filtered(OPT_UNKNOWN)) {
+ diagnostics << "warning: ignoring unknown argument: "
+ << unknownArg->getAsString(parsedArgs) << "\n";
}
// Figure out output kind ( -dylib, -r, -bundle, -preload, or -static )
llvm::MachO::HeaderFileType fileType = llvm::MachO::MH_EXECUTE;
- if ( llvm::opt::Arg *kind = parsedArgs->getLastArg(OPT_dylib, OPT_relocatable,
- OPT_bundle, OPT_static, OPT_preload)) {
+ if (llvm::opt::Arg *kind = parsedArgs.getLastArg(
+ OPT_dylib, OPT_relocatable, OPT_bundle, OPT_static, OPT_preload)) {
switch (kind->getOption().getID()) {
case OPT_dylib:
fileType = llvm::MachO::MH_DYLIB;
@@ -320,7 +322,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
// Handle -arch xxx
MachOLinkingContext::Arch arch = MachOLinkingContext::arch_unknown;
- if (llvm::opt::Arg *archStr = parsedArgs->getLastArg(OPT_arch)) {
+ if (llvm::opt::Arg *archStr = parsedArgs.getLastArg(OPT_arch)) {
arch = MachOLinkingContext::archFromName(archStr->getValue());
if (arch == MachOLinkingContext::arch_unknown) {
diagnostics << "error: unknown arch named '" << archStr->getValue()
@@ -330,17 +332,17 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
}
// If no -arch specified, scan input files to find first non-fat .o file.
if (arch == MachOLinkingContext::arch_unknown) {
- for (auto &inFile: parsedArgs->filtered(OPT_INPUT)) {
+ for (auto &inFile : parsedArgs.filtered(OPT_INPUT)) {
// This is expensive because it opens and maps the file. But that is
// ok because no -arch is rare.
if (MachOLinkingContext::isThinObjectFile(inFile->getValue(), arch))
break;
}
- if (arch == MachOLinkingContext::arch_unknown
- && !parsedArgs->getLastArg(OPT_test_file_usage)) {
+ if (arch == MachOLinkingContext::arch_unknown &&
+ !parsedArgs.getLastArg(OPT_test_file_usage)) {
// If no -arch and no options at all, print usage message.
- if (parsedArgs->size() == 0)
- table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false);
+ if (parsedArgs.size() == 0)
+ table.PrintHelp(llvm::outs(), args[0], "LLVM Linker", false);
else
diagnostics << "error: -arch not specified and could not be inferred\n";
return false;
@@ -351,8 +353,8 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
MachOLinkingContext::OS os = MachOLinkingContext::OS::macOSX;
uint32_t minOSVersion = 0;
if (llvm::opt::Arg *minOS =
- parsedArgs->getLastArg(OPT_macosx_version_min, OPT_ios_version_min,
- OPT_ios_simulator_version_min)) {
+ parsedArgs.getLastArg(OPT_macosx_version_min, OPT_ios_version_min,
+ OPT_ios_simulator_version_min)) {
switch (minOS->getOption().getID()) {
case OPT_macosx_version_min:
os = MachOLinkingContext::OS::macOSX;
@@ -388,17 +390,17 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
ctx.configure(fileType, arch, os, minOSVersion);
// Handle -e xxx
- if (llvm::opt::Arg *entry = parsedArgs->getLastArg(OPT_entry))
+ if (llvm::opt::Arg *entry = parsedArgs.getLastArg(OPT_entry))
ctx.setEntrySymbolName(entry->getValue());
// Handle -o xxx
- if (llvm::opt::Arg *outpath = parsedArgs->getLastArg(OPT_output))
+ if (llvm::opt::Arg *outpath = parsedArgs.getLastArg(OPT_output))
ctx.setOutputPath(outpath->getValue());
else
ctx.setOutputPath("a.out");
// Handle -image_base XXX and -seg1addr XXXX
- if (llvm::opt::Arg *imageBase = parsedArgs->getLastArg(OPT_image_base)) {
+ if (llvm::opt::Arg *imageBase = parsedArgs.getLastArg(OPT_image_base)) {
uint64_t baseAddress;
if (parseNumberBase16(imageBase->getValue(), baseAddress)) {
diagnostics << "error: image_base expects a hex number\n";
@@ -408,7 +410,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
return false;
} else if (baseAddress % ctx.pageSize()) {
diagnostics << "error: image_base must be a multiple of page size ("
- << llvm::format("0x%" PRIx64, ctx.pageSize()) << ")\n";
+ << "0x" << llvm::utohexstr(ctx.pageSize()) << ")\n";
return false;
}
@@ -416,26 +418,26 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
}
// Handle -dead_strip
- if (parsedArgs->getLastArg(OPT_dead_strip))
+ if (parsedArgs.getLastArg(OPT_dead_strip))
ctx.setDeadStripping(true);
+ bool globalWholeArchive = false;
// Handle -all_load
- if (parsedArgs->getLastArg(OPT_all_load))
+ if (parsedArgs.getLastArg(OPT_all_load))
globalWholeArchive = true;
// Handle -install_name
- if (llvm::opt::Arg *installName = parsedArgs->getLastArg(OPT_install_name))
+ if (llvm::opt::Arg *installName = parsedArgs.getLastArg(OPT_install_name))
ctx.setInstallName(installName->getValue());
else
ctx.setInstallName(ctx.outputPath());
// Handle -mark_dead_strippable_dylib
- if (parsedArgs->getLastArg(OPT_mark_dead_strippable_dylib))
+ if (parsedArgs.getLastArg(OPT_mark_dead_strippable_dylib))
ctx.setDeadStrippableDylib(true);
// Handle -compatibility_version and -current_version
- if (llvm::opt::Arg *vers =
- parsedArgs->getLastArg(OPT_compatibility_version)) {
+ if (llvm::opt::Arg *vers = parsedArgs.getLastArg(OPT_compatibility_version)) {
if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB) {
diagnostics
<< "error: -compatibility_version can only be used with -dylib\n";
@@ -449,7 +451,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
ctx.setCompatibilityVersion(parsedVers);
}
- if (llvm::opt::Arg *vers = parsedArgs->getLastArg(OPT_current_version)) {
+ if (llvm::opt::Arg *vers = parsedArgs.getLastArg(OPT_current_version)) {
if (ctx.outputMachOType() != llvm::MachO::MH_DYLIB) {
diagnostics << "-current_version can only be used with -dylib\n";
return false;
@@ -463,11 +465,11 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
}
// Handle -bundle_loader
- if (llvm::opt::Arg *loader = parsedArgs->getLastArg(OPT_bundle_loader))
+ if (llvm::opt::Arg *loader = parsedArgs.getLastArg(OPT_bundle_loader))
ctx.setBundleLoader(loader->getValue());
// Handle -sectalign segname sectname align
- for (auto &alignArg : parsedArgs->filtered(OPT_sectalign)) {
+ for (auto &alignArg : parsedArgs.filtered(OPT_sectalign)) {
const char* segName = alignArg->getValue(0);
const char* sectName = alignArg->getValue(1);
const char* alignStr = alignArg->getValue(2);
@@ -479,43 +481,43 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
<< alignStr << "' not a valid number\n";
return false;
}
- uint8_t align2 = llvm::countTrailingZeros(alignValue);
- if ( (unsigned long)(1 << align2) != alignValue ) {
+ uint16_t align = 1 << llvm::countTrailingZeros(alignValue);
+ if (!llvm::isPowerOf2_64(alignValue)) {
diagnostics << "warning: alignment for '-sectalign "
<< segName << " " << sectName
<< llvm::format(" 0x%llX", alignValue)
<< "' is not a power of two, using "
- << llvm::format("0x%08X", (1 << align2)) << "\n";
+ << llvm::format("0x%08X", align) << "\n";
}
- ctx.addSectionAlignment(segName, sectName, align2);
+ ctx.addSectionAlignment(segName, sectName, align);
}
// Handle -mllvm
- for (auto &llvmArg : parsedArgs->filtered(OPT_mllvm)) {
+ for (auto &llvmArg : parsedArgs.filtered(OPT_mllvm)) {
ctx.appendLLVMOption(llvmArg->getValue());
}
// Handle -print_atoms
- if (parsedArgs->getLastArg(OPT_print_atoms))
+ if (parsedArgs.getLastArg(OPT_print_atoms))
ctx.setPrintAtoms();
// Handle -t (trace) option.
- if (parsedArgs->getLastArg(OPT_t))
+ if (parsedArgs.getLastArg(OPT_t))
ctx.setLogInputFiles(true);
// Handle -demangle option.
- if (parsedArgs->getLastArg(OPT_demangle))
+ if (parsedArgs.getLastArg(OPT_demangle))
ctx.setDemangleSymbols(true);
// Handle -keep_private_externs
- if (parsedArgs->getLastArg(OPT_keep_private_externs)) {
+ if (parsedArgs.getLastArg(OPT_keep_private_externs)) {
ctx.setKeepPrivateExterns(true);
if (ctx.outputMachOType() != llvm::MachO::MH_OBJECT)
diagnostics << "warning: -keep_private_externs only used in -r mode\n";
}
// Handle -dependency_info <path> used by Xcode.
- if (llvm::opt::Arg *depInfo = parsedArgs->getLastArg(OPT_dependency_info)) {
+ if (llvm::opt::Arg *depInfo = parsedArgs.getLastArg(OPT_dependency_info)) {
if (std::error_code ec = ctx.createDependencyFile(depInfo->getValue())) {
diagnostics << "warning: " << ec.message()
<< ", processing '-dependency_info "
@@ -528,14 +530,14 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
// exist. We'll also be expected to print out information about how we located
// libraries and so on that the user specified, but not to actually do any
// linking.
- if (parsedArgs->getLastArg(OPT_test_file_usage)) {
+ if (parsedArgs.getLastArg(OPT_test_file_usage)) {
ctx.setTestingFileUsage();
// With paths existing by fiat, linking is not going to end well.
ctx.setDoNothing(true);
// Only bother looking for an existence override if we're going to use it.
- for (auto existingPath : parsedArgs->filtered(OPT_path_exists)) {
+ for (auto existingPath : parsedArgs.filtered(OPT_path_exists)) {
ctx.addExistingPathForDebug(existingPath->getValue());
}
}
@@ -544,7 +546,6 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
if (!ctx.doNothing()) {
ctx.registry().addSupportMachOObjects(ctx);
ctx.registry().addSupportArchives(ctx.logInputFiles());
- ctx.registry().addSupportNativeObjects();
ctx.registry().addSupportYamlFiles();
}
@@ -559,7 +560,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
// 3. If the last -syslibroot is "/", all of them are ignored entirely.
// 4. If { syslibroots } x path == {}, the original path is kept.
std::vector<StringRef> sysLibRoots;
- for (auto syslibRoot : parsedArgs->filtered(OPT_syslibroot)) {
+ for (auto syslibRoot : parsedArgs.filtered(OPT_syslibroot)) {
sysLibRoots.push_back(syslibRoot->getValue());
}
if (!sysLibRoots.empty()) {
@@ -570,17 +571,17 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
// Paths specified with -L come first, and are not considered system paths for
// the case where there is precisely 1 -syslibroot.
- for (auto libPath : parsedArgs->filtered(OPT_L)) {
+ for (auto libPath : parsedArgs.filtered(OPT_L)) {
ctx.addModifiedSearchDir(libPath->getValue());
}
// Process -F directories (where to look for frameworks).
- for (auto fwPath : parsedArgs->filtered(OPT_F)) {
+ for (auto fwPath : parsedArgs.filtered(OPT_F)) {
ctx.addFrameworkSearchDir(fwPath->getValue());
}
// -Z suppresses the standard search paths.
- if (!parsedArgs->hasArg(OPT_Z)) {
+ if (!parsedArgs.hasArg(OPT_Z)) {
ctx.addModifiedSearchDir("/usr/lib", true);
ctx.addModifiedSearchDir("/usr/local/lib", true);
ctx.addFrameworkSearchDir("/Library/Frameworks", true);
@@ -589,7 +590,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
// Now that we've constructed the final set of search paths, print out those
// search paths in verbose mode.
- if (parsedArgs->getLastArg(OPT_v)) {
+ if (parsedArgs.getLastArg(OPT_v)) {
diagnostics << "Library search paths:\n";
for (auto path : ctx.searchDirs()) {
diagnostics << " " << path << '\n';
@@ -601,7 +602,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
}
// Handle -exported_symbols_list <file>
- for (auto expFile : parsedArgs->filtered(OPT_exported_symbols_list)) {
+ for (auto expFile : parsedArgs.filtered(OPT_exported_symbols_list)) {
if (ctx.exportMode() == MachOLinkingContext::ExportMode::blackList) {
diagnostics << "error: -exported_symbols_list cannot be combined "
<< "with -unexported_symbol[s_list]\n";
@@ -619,7 +620,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
}
// Handle -exported_symbol <symbol>
- for (auto symbol : parsedArgs->filtered(OPT_exported_symbol)) {
+ for (auto symbol : parsedArgs.filtered(OPT_exported_symbol)) {
if (ctx.exportMode() == MachOLinkingContext::ExportMode::blackList) {
diagnostics << "error: -exported_symbol cannot be combined "
<< "with -unexported_symbol[s_list]\n";
@@ -630,7 +631,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
}
// Handle -unexported_symbols_list <file>
- for (auto expFile : parsedArgs->filtered(OPT_unexported_symbols_list)) {
+ for (auto expFile : parsedArgs.filtered(OPT_unexported_symbols_list)) {
if (ctx.exportMode() == MachOLinkingContext::ExportMode::whiteList) {
diagnostics << "error: -unexported_symbols_list cannot be combined "
<< "with -exported_symbol[s_list]\n";
@@ -648,7 +649,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
}
// Handle -unexported_symbol <symbol>
- for (auto symbol : parsedArgs->filtered(OPT_unexported_symbol)) {
+ for (auto symbol : parsedArgs.filtered(OPT_unexported_symbol)) {
if (ctx.exportMode() == MachOLinkingContext::ExportMode::whiteList) {
diagnostics << "error: -unexported_symbol cannot be combined "
<< "with -exported_symbol[s_list]\n";
@@ -659,8 +660,8 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
}
// Handle obosolete -multi_module and -single_module
- if (llvm::opt::Arg *mod = parsedArgs->getLastArg(OPT_multi_module,
- OPT_single_module)) {
+ if (llvm::opt::Arg *mod =
+ parsedArgs.getLastArg(OPT_multi_module, OPT_single_module)) {
if (mod->getOption().getID() == OPT_multi_module) {
diagnostics << "warning: -multi_module is obsolete and being ignored\n";
}
@@ -673,7 +674,7 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
}
// Handle -pie or -no_pie
- if (llvm::opt::Arg *pie = parsedArgs->getLastArg(OPT_pie, OPT_no_pie)) {
+ if (llvm::opt::Arg *pie = parsedArgs.getLastArg(OPT_pie, OPT_no_pie)) {
switch (ctx.outputMachOType()) {
case llvm::MachO::MH_EXECUTE:
switch (ctx.os()) {
@@ -718,12 +719,28 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
}
}
+ // Handle stack_size
+ if (llvm::opt::Arg *stackSize = parsedArgs.getLastArg(OPT_stack_size)) {
+ uint64_t stackSizeVal;
+ if (parseNumberBase16(stackSize->getValue(), stackSizeVal)) {
+ diagnostics << "error: stack_size expects a hex number\n";
+ return false;
+ }
+ if ((stackSizeVal % ctx.pageSize()) != 0) {
+ diagnostics << "error: stack_size must be a multiple of page size ("
+ << "0x" << llvm::utohexstr(ctx.pageSize()) << ")\n";
+ return false;
+ }
+
+ ctx.setStackSize(stackSizeVal);
+ }
+
// Handle debug info handling options: -S
- if (parsedArgs->hasArg(OPT_S))
+ if (parsedArgs.hasArg(OPT_S))
ctx.setDebugInfoMode(MachOLinkingContext::DebugInfoMode::noDebugMap);
// Handle -order_file <file>
- for (auto orderFile : parsedArgs->filtered(OPT_order_file)) {
+ for (auto orderFile : parsedArgs.filtered(OPT_order_file)) {
if (std::error_code ec = parseOrderFile(orderFile->getValue(), ctx,
diagnostics)) {
diagnostics << "error: " << ec.message()
@@ -734,8 +751,51 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
}
}
+ // Handle -flat_namespace.
+ if (llvm::opt::Arg *ns =
+ parsedArgs.getLastArg(OPT_flat_namespace, OPT_twolevel_namespace)) {
+ if (ns->getOption().getID() == OPT_flat_namespace)
+ ctx.setUseFlatNamespace(true);
+ }
+
+ // Handle -undefined
+ if (llvm::opt::Arg *undef = parsedArgs.getLastArg(OPT_undefined)) {
+ MachOLinkingContext::UndefinedMode UndefMode;
+ if (StringRef(undef->getValue()).equals("error"))
+ UndefMode = MachOLinkingContext::UndefinedMode::error;
+ else if (StringRef(undef->getValue()).equals("warning"))
+ UndefMode = MachOLinkingContext::UndefinedMode::warning;
+ else if (StringRef(undef->getValue()).equals("suppress"))
+ UndefMode = MachOLinkingContext::UndefinedMode::suppress;
+ else if (StringRef(undef->getValue()).equals("dynamic_lookup"))
+ UndefMode = MachOLinkingContext::UndefinedMode::dynamicLookup;
+ else {
+ diagnostics << "error: invalid option to -undefined "
+ "[ warning | error | suppress | dynamic_lookup ]\n";
+ return false;
+ }
+
+ if (ctx.useFlatNamespace()) {
+ // If we're using -flat_namespace then 'warning', 'suppress' and
+ // 'dynamic_lookup' are all equivalent, so map them to 'suppress'.
+ if (UndefMode != MachOLinkingContext::UndefinedMode::error)
+ UndefMode = MachOLinkingContext::UndefinedMode::suppress;
+ } else {
+ // If we're using -twolevel_namespace then 'warning' and 'suppress' are
+ // illegal. Emit a diagnostic if they've been (mis)used.
+ if (UndefMode == MachOLinkingContext::UndefinedMode::warning ||
+ UndefMode == MachOLinkingContext::UndefinedMode::suppress) {
+ diagnostics << "error: can't use -undefined warning or suppress with "
+ "-twolevel_namespace\n";
+ return false;
+ }
+ }
+
+ ctx.setUndefinedMode(UndefMode);
+ }
+
// Handle -rpath <path>
- if (parsedArgs->hasArg(OPT_rpath)) {
+ if (parsedArgs.hasArg(OPT_rpath)) {
switch (ctx.outputMachOType()) {
case llvm::MachO::MH_EXECUTE:
case llvm::MachO::MH_DYLIB:
@@ -757,13 +817,17 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
return false;
}
- for (auto rPath : parsedArgs->filtered(OPT_rpath)) {
+ for (auto rPath : parsedArgs.filtered(OPT_rpath)) {
ctx.addRpath(rPath->getValue());
}
}
- // Handle input files
- for (auto &arg : *parsedArgs) {
+ // Parse the LLVM options before we process files in case the file handling
+ // makes use of things like DEBUG().
+ parseLLVMOptions(ctx);
+
+ // Handle input files and sectcreate.
+ for (auto &arg : parsedArgs) {
bool upward;
ErrorOr<StringRef> resolvedPath = StringRef();
switch (arg->getOption().getID()) {
@@ -816,6 +880,22 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
return false;
}
break;
+ case OPT_sectcreate: {
+ const char* seg = arg->getValue(0);
+ const char* sect = arg->getValue(1);
+ const char* fileName = arg->getValue(2);
+
+ ErrorOr<std::unique_ptr<MemoryBuffer>> contentOrErr =
+ MemoryBuffer::getFile(fileName);
+
+ if (!contentOrErr) {
+ diagnostics << "error: can't open -sectcreate file " << fileName << "\n";
+ return false;
+ }
+
+ ctx.addSectCreateSection(seg, sect, std::move(*contentOrErr));
+ }
+ break;
}
}
diff --git a/lib/Driver/DarwinLdOptions.td b/lib/Driver/DarwinLdOptions.td
index 81dcc0a1d925..cbf6ac1d4a4b 100644
--- a/lib/Driver/DarwinLdOptions.td
+++ b/lib/Driver/DarwinLdOptions.td
@@ -55,6 +55,19 @@ def order_file : Separate<["-"], "order_file">,
MetaVarName<"<file-path>">,
HelpText<"re-order and move specified symbols to start of their section">,
Group<grp_opts>;
+def flat_namespace : Flag<["-"], "flat_namespace">,
+ HelpText<"Resolves symbols in any (transitively) linked dynamic libraries. "
+ "Source libraries are not recorded: dyld will re-search all "
+ "images at runtime and use the first definition found.">,
+ Group<grp_opts>;
+def twolevel_namespace : Flag<["-"], "twolevel_namespace">,
+ HelpText<"Resolves symbols in listed libraries only. Source libraries are "
+ "recorded in the symbol table.">,
+ Group<grp_opts>;
+def undefined : Separate<["-"], "undefined">,
+ MetaVarName<"<undefined>">,
+ HelpText<"Determines how undefined symbols are handled.">,
+ Group<grp_opts>;
// main executable options
def grp_main : OptionGroup<"opts">, HelpText<"MAIN EXECUTABLE OPTIONS">;
@@ -67,6 +80,10 @@ def pie : Flag<["-"], "pie">,
def no_pie : Flag<["-"], "no_pie">,
HelpText<"Do not create Position Independent Executable">,
Group<grp_main>;
+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>;
// dylib executable options
def grp_dylib : OptionGroup<"opts">, HelpText<"DYLIB EXECUTABLE OPTIONS">;
@@ -160,7 +177,10 @@ def arch : Separate<["-"], "arch">,
HelpText<"Architecture to link">;
def sectalign : MultiArg<["-"], "sectalign", 3>,
MetaVarName<"<segname> <sectname> <alignment>">,
- HelpText<"alignment for segment/section">;
+ HelpText<"Alignment for segment/section">;
+def sectcreate : MultiArg<["-"], "sectcreate", 3>,
+ MetaVarName<"<segname> <sectname> <file>">,
+ HelpText<"Create section <segname>/<sectname> from contents of <file>">;
def image_base : Separate<["-"], "image_base">;
def seg1addr : Separate<["-"], "seg1addr">, Alias<image_base>;
def demangle : Flag<["-"], "demangle">,
diff --git a/lib/Driver/Driver.cpp b/lib/Driver/Driver.cpp
index d32bfa6e47be..6a7a26b3b0f6 100644
--- a/lib/Driver/Driver.cpp
+++ b/lib/Driver/Driver.cpp
@@ -1,4 +1,4 @@
-//===- lib/Driver/Driver.cpp - Linker Driver Emulator ---------------------===//
+//===- lib/Driver/Driver.cpp - Linker Driver Emulator -----------*- C++ -*-===//
//
// The LLVM Linker
//
@@ -36,15 +36,13 @@ FileVector makeErrorFile(StringRef path, std::error_code ec) {
return result;
}
-FileVector parseMemberFiles(FileVector &files) {
+FileVector parseMemberFiles(std::unique_ptr<File> file) {
std::vector<std::unique_ptr<File>> members;
- for (std::unique_ptr<File> &file : files) {
- 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));
- }
+ 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;
}
@@ -54,72 +52,86 @@ FileVector loadFile(LinkingContext &ctx, StringRef path, bool wholeArchive) {
= MemoryBuffer::getFileOrSTDIN(path);
if (std::error_code ec = mb.getError())
return makeErrorFile(path, ec);
- std::vector<std::unique_ptr<File>> files;
- if (std::error_code ec = ctx.registry().loadFile(std::move(mb.get()), files))
+ 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(files);
+ return parseMemberFiles(std::move(file));
+ std::vector<std::unique_ptr<File>> files;
+ files.push_back(std::move(file));
return files;
}
-/// This is where the link is actually performed.
-bool Driver::link(LinkingContext &context, raw_ostream &diagnostics) {
+void Driver::parseLLVMOptions(const LinkingContext &ctx) {
// Honor -mllvm
- if (!context.llvmOptions().empty()) {
- unsigned numArgs = context.llvmOptions().size();
- const char **args = new const char *[numArgs + 2];
+ 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] = context.llvmOptions()[i];
- args[numArgs + 1] = 0;
+ args[i + 1] = ctx.llvmOptions()[i];
+ args[numArgs + 1] = nullptr;
llvm::cl::ParseCommandLineOptions(numArgs + 1, args);
}
- if (context.getNodes().empty())
+}
+
+/// 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 : context.getNodes())
+ for (std::unique_ptr<Node> &ie : ctx.getNodes())
if (FileNode *node = dyn_cast<FileNode>(ie.get()))
- context.getTaskGroup().spawn([node] { node->getFile()->parse(); });
+ ctx.getTaskGroup().spawn([node] { node->getFile()->parse(); });
std::vector<std::unique_ptr<File>> internalFiles;
- context.createInternalFiles(internalFiles);
+ ctx.createInternalFiles(internalFiles);
for (auto i = internalFiles.rbegin(), e = internalFiles.rend(); i != e; ++i) {
- auto &members = context.getNodes();
+ 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;
- context.createImplicitFiles(implicitFiles);
+ ctx.createImplicitFiles(implicitFiles);
for (auto i = implicitFiles.rbegin(), e = implicitFiles.rend(); i != e; ++i) {
- auto &members = context.getNodes();
+ 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.
- context.finalizeInputFiles();
+ ctx.finalizeInputFiles();
// Do core linking.
ScopedTask resolveTask(getDefaultDomain(), "Resolve");
- Resolver resolver(context);
- if (!resolver.resolve())
+ Resolver resolver(ctx);
+ if (!resolver.resolve()) {
+ ctx.getTaskGroup().sync();
return false;
- std::unique_ptr<MutableFile> merged = resolver.resultFile();
+ }
+ std::unique_ptr<SimpleFile> merged = resolver.resultFile();
resolveTask.end();
// Run passes on linked atoms.
ScopedTask passTask(getDefaultDomain(), "Passes");
PassManager pm;
- context.addPasses(pm);
- pm.runOnFile(merged);
+ 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 = context.writeFile(*merged)) {
- diagnostics << "Failed to write file '" << context.outputPath()
+ if (std::error_code ec = ctx.writeFile(*merged)) {
+ diagnostics << "Failed to write file '" << ctx.outputPath()
<< "': " << ec.message() << "\n";
return false;
}
@@ -127,4 +139,4 @@ bool Driver::link(LinkingContext &context, raw_ostream &diagnostics) {
return true;
}
-} // namespace
+} // namespace lld
diff --git a/lib/Driver/GnuLdDriver.cpp b/lib/Driver/GnuLdDriver.cpp
index b9af04d4b615..8c75126d6d41 100644
--- a/lib/Driver/GnuLdDriver.cpp
+++ b/lib/Driver/GnuLdDriver.cpp
@@ -15,7 +15,6 @@
#include "lld/Driver/Driver.h"
#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "lld/ReaderWriter/ELFTargets.h"
#include "lld/ReaderWriter/LinkerScript.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/Optional.h"
@@ -32,6 +31,7 @@
#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>
@@ -72,21 +72,7 @@ static const llvm::opt::OptTable::Info infoTable[] = {
// Create OptTable class for parsing actual command line arguments
class GnuLdOptTable : public llvm::opt::OptTable {
public:
- GnuLdOptTable() : OptTable(infoTable, llvm::array_lengthof(infoTable)){}
-};
-
-class DriverStringSaver : public llvm::cl::StringSaver {
-public:
- DriverStringSaver(BumpPtrAllocator &alloc) : _alloc(alloc) {}
-
- const char *SaveString(const char *s) override {
- char *p = _alloc.Allocate<char>(strlen(s) + 1);
- strcpy(p, s);
- return p;
- }
-
-private:
- BumpPtrAllocator &_alloc;
+ GnuLdOptTable() : OptTable(infoTable){}
};
} // anonymous namespace
@@ -96,37 +82,21 @@ private:
// 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 std::tuple<int, const char **>
-maybeExpandResponseFiles(int argc, const char **argv, BumpPtrAllocator &alloc) {
+static llvm::ArrayRef<const char *>
+maybeExpandResponseFiles(llvm::ArrayRef<const char *> args,
+ BumpPtrAllocator &alloc) {
// Expand response files.
SmallVector<const char *, 256> smallvec;
- for (int i = 0; i < argc; ++i)
- smallvec.push_back(argv[i]);
- DriverStringSaver saver(alloc);
+ 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.
- argc = smallvec.size();
- const char **copy = alloc.Allocate<const char *>(argc + 1);
+ const char **copy = alloc.Allocate<const char *>(smallvec.size() + 1);
std::copy(smallvec.begin(), smallvec.end(), copy);
- copy[argc] = nullptr;
- return std::make_tuple(argc, copy);
-}
-
-static std::error_code
-getFileMagic(StringRef path, llvm::sys::fs::file_magic &magic) {
- std::error_code ec = llvm::sys::fs::identify_magic(path, magic);
- if (ec)
- return ec;
- switch (magic) {
- case llvm::sys::fs::file_magic::archive:
- case llvm::sys::fs::file_magic::elf_relocatable:
- case llvm::sys::fs::file_magic::elf_shared_object:
- case llvm::sys::fs::file_magic::unknown:
- return std::error_code();
- default:
- return make_dynamic_error_code(StringRef("unknown type of object file"));
- }
+ copy[smallvec.size()] = nullptr;
+ return llvm::makeArrayRef(copy, smallvec.size() + 1);
}
// Parses an argument of --defsym=<sym>=<number>
@@ -164,11 +134,12 @@ static bool parseMaxPageSize(StringRef opt, uint64_t &val) {
return true;
}
-bool GnuLdDriver::linkELF(int argc, const char *argv[], raw_ostream &diag) {
+bool GnuLdDriver::linkELF(llvm::ArrayRef<const char *> args,
+ raw_ostream &diag) {
BumpPtrAllocator alloc;
- std::tie(argc, argv) = maybeExpandResponseFiles(argc, argv, alloc);
+ args = maybeExpandResponseFiles(args, alloc);
std::unique_ptr<ELFLinkingContext> options;
- if (!parse(argc, argv, options, diag))
+ if (!parse(args, options, diag))
return false;
if (!options)
return true;
@@ -193,13 +164,16 @@ getArchType(const llvm::Triple &triple, StringRef value) {
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:
- if (value == "elf32ltsmip")
- return llvm::Triple::mipsel;
- if (value == "elf64ltsmip")
- return llvm::Triple::mips64el;
- return llvm::None;
+ 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;
@@ -215,9 +189,9 @@ getArchType(const llvm::Triple &triple, StringRef value) {
static bool isLinkerScript(StringRef path, raw_ostream &diag) {
llvm::sys::fs::file_magic magic = llvm::sys::fs::file_magic::unknown;
- std::error_code ec = getFileMagic(path, magic);
- if (ec) {
- diag << "unknown input file format for file " << path << "\n";
+ 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;
@@ -350,17 +324,14 @@ void GnuLdDriver::addPlatformSearchDirs(ELFLinkingContext &ctx,
std::unique_ptr<ELFLinkingContext>
GnuLdDriver::createELFLinkingContext(llvm::Triple triple) {
std::unique_ptr<ELFLinkingContext> p;
- // FIXME: #include "llvm/Config/Targets.def"
-#define LLVM_TARGET(targetName) \
- if ((p = elf::targetName##LinkingContext::create(triple))) return p;
- LLVM_TARGET(AArch64)
- LLVM_TARGET(ARM)
- LLVM_TARGET(Hexagon)
- LLVM_TARGET(Mips)
- LLVM_TARGET(X86)
- LLVM_TARGET(Example)
- LLVM_TARGET(X86_64)
-#undef LLVM_TARGET
+ if ((p = elf::createAArch64LinkingContext(triple))) return p;
+ if ((p = elf::createAMDGPULinkingContext(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;
}
@@ -372,40 +343,39 @@ getBool(const llvm::opt::InputArgList &parsedArgs,
return llvm::None;
}
-bool GnuLdDriver::parse(int argc, const char *argv[],
+bool GnuLdDriver::parse(llvm::ArrayRef<const char *> args,
std::unique_ptr<ELFLinkingContext> &context,
raw_ostream &diag) {
// Parse command line options using GnuLdOptions.td
- std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
GnuLdOptTable table;
unsigned missingIndex;
unsigned missingCount;
- parsedArgs.reset(
- table.ParseArgs(&argv[1], &argv[argc], missingIndex, missingCount));
+ llvm::opt::InputArgList parsedArgs =
+ table.ParseArgs(args.slice(1), missingIndex, missingCount);
if (missingCount) {
diag << "error: missing arg value for '"
- << parsedArgs->getArgString(missingIndex) << "' expected "
+ << parsedArgs.getArgString(missingIndex) << "' expected "
<< missingCount << " argument(s).\n";
return false;
}
// Handle --help
- if (parsedArgs->hasArg(OPT_help)) {
- table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false);
+ 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)) {
+ if (auto *arg = parsedArgs.getLastArg(OPT_target)) {
baseTriple = llvm::Triple(arg->getValue());
} else {
- baseTriple = getDefaultTarget(argv[0]);
+ baseTriple = getDefaultTarget(args[0]);
}
llvm::Triple triple(baseTriple);
- if (!applyEmulation(triple, *parsedArgs, diag))
+ if (!applyEmulation(triple, parsedArgs, diag))
return false;
std::unique_ptr<ELFLinkingContext> ctx(createELFLinkingContext(triple));
@@ -416,39 +386,39 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
}
// Copy mllvm
- for (auto *arg : parsedArgs->filtered(OPT_mllvm))
+ for (auto *arg : parsedArgs.filtered(OPT_mllvm))
ctx->appendLLVMOption(arg->getValue());
// Ignore unknown arguments.
- for (auto unknownArg : parsedArgs->filtered(OPT_UNKNOWN))
+ 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))
+ if (auto *arg = parsedArgs.getLastArg(OPT_sysroot))
ctx->setSysroot(arg->getValue());
// Handle --demangle option(For compatibility)
- if (parsedArgs->hasArg(OPT_demangle))
+ if (parsedArgs.hasArg(OPT_demangle))
ctx->setDemangleSymbols(true);
// Handle --no-demangle option.
- if (parsedArgs->hasArg(OPT_no_demangle))
+ if (parsedArgs.hasArg(OPT_no_demangle))
ctx->setDemangleSymbols(false);
// Figure out output kind (-r, -static, -shared)
- if (parsedArgs->hasArg(OPT_relocatable)) {
+ if (parsedArgs.hasArg(OPT_relocatable)) {
ctx->setOutputELFType(llvm::ELF::ET_REL);
ctx->setPrintRemainingUndefines(false);
ctx->setAllowRemainingUndefines(true);
}
- if (parsedArgs->hasArg(OPT_static)) {
+ if (parsedArgs.hasArg(OPT_static)) {
ctx->setOutputELFType(llvm::ELF::ET_EXEC);
ctx->setIsStaticExecutable(true);
}
- if (parsedArgs->hasArg(OPT_shared)) {
+ if (parsedArgs.hasArg(OPT_shared)) {
ctx->setOutputELFType(llvm::ELF::ET_DYN);
ctx->setAllowShlibUndefines(true);
ctx->setUseShlibUndefines(false);
@@ -457,13 +427,13 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
}
// Handle --stats.
- if (parsedArgs->hasArg(OPT_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)) {
+ if (auto *arg =
+ parsedArgs.getLastArg(OPT_nmagic, OPT_omagic, OPT_no_omagic)) {
switch (arg->getOption().getID()) {
case OPT_nmagic:
ctx->setOutputMagic(ELFLinkingContext::OutputMagic::NMAGIC);
@@ -480,19 +450,25 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
}
}
- if (parsedArgs->hasArg(OPT_strip_all))
+ 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))
+ if (auto *arg = parsedArgs.getLastArg(OPT_soname))
ctx->setSharedObjectName(arg->getValue());
- if (parsedArgs->hasArg(OPT_rosegment))
+ if (parsedArgs.hasArg(OPT_rosegment))
ctx->setCreateSeparateROSegment();
- if (parsedArgs->hasArg(OPT_no_align_segments))
+ if (parsedArgs.hasArg(OPT_no_align_segments))
ctx->setAlignSegments(false);
- if (auto *arg = parsedArgs->getLastArg(OPT_image_base)) {
+ if (auto *arg = parsedArgs.getLastArg(OPT_image_base)) {
uint64_t baseAddress = 0;
StringRef inputValue = arg->getValue();
if (inputValue.getAsInteger(0, baseAddress) || !baseAddress) {
@@ -502,58 +478,94 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
ctx->setBaseAddress(baseAddress);
}
- if (parsedArgs->hasArg(OPT_merge_strings))
+ if (parsedArgs.hasArg(OPT_merge_strings))
ctx->setMergeCommonStrings(true);
- if (parsedArgs->hasArg(OPT_t))
+ if (parsedArgs.hasArg(OPT_t))
ctx->setLogInputFiles(true);
- if (parsedArgs->hasArg(OPT_use_shlib_undefs))
+ if (parsedArgs.hasArg(OPT_use_shlib_undefs))
ctx->setUseShlibUndefines(true);
- if (auto val = getBool(*parsedArgs, OPT_allow_shlib_undefs,
+ if (auto val = getBool(parsedArgs, OPT_allow_shlib_undefs,
OPT_no_allow_shlib_undefs))
ctx->setAllowShlibUndefines(*val);
- if (auto *arg = parsedArgs->getLastArg(OPT_e))
+ if (auto *arg = parsedArgs.getLastArg(OPT_e))
ctx->setEntrySymbolName(arg->getValue());
- if (auto *arg = parsedArgs->getLastArg(OPT_output))
+ if (auto *arg = parsedArgs.getLastArg(OPT_output))
ctx->setOutputPath(arg->getValue());
- if (parsedArgs->hasArg(OPT_noinhibit_exec))
+ if (parsedArgs.hasArg(OPT_noinhibit_exec))
ctx->setAllowRemainingUndefines(true);
- if (auto val = getBool(*parsedArgs, OPT_export_dynamic,
- OPT_no_export_dynamic))
+ if (auto val = getBool(parsedArgs, OPT_export_dynamic, OPT_no_export_dynamic))
ctx->setExportDynamic(*val);
- if (parsedArgs->hasArg(OPT_allow_multiple_definition))
+ if (parsedArgs.hasArg(OPT_allow_multiple_definition))
ctx->setAllowDuplicates(true);
- if (auto *arg = parsedArgs->getLastArg(OPT_dynamic_linker))
+ if (auto *arg = parsedArgs.getLastArg(OPT_dynamic_linker))
ctx->setInterpreter(arg->getValue());
- if (auto *arg = parsedArgs->getLastArg(OPT_init))
+ if (auto *arg = parsedArgs.getLastArg(OPT_init))
ctx->setInitFunction(arg->getValue());
- if (auto *arg = parsedArgs->getLastArg(OPT_fini))
+ if (auto *arg = parsedArgs.getLastArg(OPT_fini))
ctx->setFiniFunction(arg->getValue());
- if (auto *arg = parsedArgs->getLastArg(OPT_output_filetype))
+ if (auto *arg = parsedArgs.getLastArg(OPT_output_filetype))
ctx->setOutputFileType(arg->getValue());
- for (auto *arg : parsedArgs->filtered(OPT_L))
+ // 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))
+ if (!parsedArgs.hasArg(OPT_nostdlib))
addPlatformSearchDirs(*ctx, triple, baseTriple);
- for (auto *arg : parsedArgs->filtered(OPT_u))
+ for (auto *arg : parsedArgs.filtered(OPT_u))
ctx->addInitialUndefinedSymbol(arg->getValue());
- for (auto *arg : parsedArgs->filtered(OPT_defsym)) {
+ for (auto *arg : parsedArgs.filtered(OPT_defsym)) {
StringRef sym, target;
uint64_t addr;
if (parseDefsymAsAbsolute(arg->getValue(), sym, addr)) {
@@ -566,11 +578,15 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
}
}
- for (auto *arg : parsedArgs->filtered(OPT_z)) {
+ for (auto *arg : parsedArgs.filtered(OPT_z)) {
StringRef opt = arg->getValue();
- if (opt == "muldefs") {
+ if (opt == "muldefs")
ctx->setAllowDuplicates(true);
- } else if (opt.startswith("max-page-size")) {
+ 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
@@ -592,39 +608,46 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
}
}
- for (auto *arg : parsedArgs->filtered(OPT_rpath)) {
+ 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)) {
+ 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))
+ 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();
- ctx->registry().addSupportNativeObjects();
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) {
+ for (auto arg : parsedArgs) {
switch (arg->getOption().getID()) {
case OPT_no_whole_archive:
wholeArchive = false;
@@ -685,7 +708,7 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
diag << "Cannot open " << path << ": " << ec.message() << "\n";
return false;
}
- bool nostdlib = parsedArgs->hasArg(OPT_nostdlib);
+ bool nostdlib = parsedArgs.hasArg(OPT_nostdlib);
std::error_code ec =
evalLinkerScript(*ctx, std::move(mb.get()), diag, nostdlib);
if (ec) {
@@ -721,9 +744,6 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
case LinkingContext::OutputFileType::YAML:
ctx->setOutputPath("-");
break;
- case LinkingContext::OutputFileType::Native:
- ctx->setOutputPath("a.native");
- break;
default:
ctx->setOutputPath("a.out");
break;
@@ -735,7 +755,10 @@ bool GnuLdDriver::parse(int argc, const char *argv[],
return false;
// Perform linker script semantic actions
- ctx->linkerScriptSema().perform();
+ if (auto ec = ctx->linkerScriptSema().perform()) {
+ diag << "Error in the linker script's semantics: " << ec.message() << "\n";
+ return false;
+ }
context.swap(ctx);
return true;
diff --git a/lib/Driver/GnuLdOptions.td b/lib/Driver/GnuLdOptions.td
index 9d06f2935439..7d850d4d002e 100644
--- a/lib/Driver/GnuLdOptions.td
+++ b/lib/Driver/GnuLdOptions.td
@@ -25,6 +25,15 @@ multiclass dashEq<string opt1, string opt2, string help> {
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
//===----------------------------------------------------------------------===//
@@ -62,7 +71,7 @@ def grp_general : OptionGroup<"opts">,
def output : Separate<["-"], "o">, MetaVarName<"<path>">,
HelpText<"Path to file to write output">,
Group<grp_general>;
-def m : Separate<["-"], "m">, MetaVarName<"<emulation>">,
+def m : JoinedOrSeparate<["-"], "m">, MetaVarName<"<emulation>">,
HelpText<"Select target emulation">,
Group<grp_general>;
def build_id : Flag<["--"], "build-id">,
@@ -142,7 +151,7 @@ def grp_dynlibexec : OptionGroup<"opts">,
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">,
+def dynamic_linker_alias : Separate<["-", "--"], "dynamic-linker">,
Alias<dynamic_linker>;
defm rpath : dashEq<"rpath", "rpath",
"Add a directory to the runtime library search path">,
@@ -211,15 +220,23 @@ def use_shlib_undefs: Flag<["--"], "use-shlib-undefines">,
def allow_multiple_definition: Flag<["--"], "allow-multiple-definition">,
HelpText<"Allow multiple definitions">,
Group<grp_resolveropt>;
-def defsym : Joined<["--"], "defsym=">,
- HelpText<"Create a defined symbol">,
- 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>;
@@ -238,6 +255,16 @@ def grp_symbolopts : OptionGroup<"opts">,
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>;
@@ -296,12 +323,37 @@ def stats : Flag<["--"], "stats">,
def grp_extns : OptionGroup<"opts">,
HelpText<"Extensions">;
def output_filetype: Separate<["--"], "output-filetype">,
- HelpText<"Specify what type of output file that lld creates, YAML/Native">,
+ 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">,
@@ -315,6 +367,9 @@ def Qy : Flag<["-"], "Qy">,
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
diff --git a/lib/Driver/Makefile b/lib/Driver/Makefile
deleted file mode 100644
index 19024cfab0f1..000000000000
--- a/lib/Driver/Makefile
+++ /dev/null
@@ -1,38 +0,0 @@
-##===- lld/lib/Driver/Makefile ---------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL := ../..
-LIBRARYNAME := lldDriver
-
-BUILT_SOURCES = CoreOptions.inc UniversalDriverOptions.inc DarwinLdOptions.inc \
- GnuLdOptions.inc WinLinkOptions.inc
-
-TABLEGEN_INC_FILES_COMMON = 1
-
-include $(LLD_LEVEL)/Makefile
-
-$(ObjDir)/CoreOptions.inc.tmp : CoreOptions.td $(LLVM_TBLGEN) $(ObjDir)/.dir
- $(Echo) "Building LLD CoreOptions Option tables with tblgen"
- $(Verb) $(LLVMTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<
-
-$(ObjDir)/UniversalDriverOptions.inc.tmp : UniversalDriverOptions.td $(LLVM_TBLGEN) $(ObjDir)/.dir
- $(Echo) "Building LLD Universal Driver Options tables with tblgen"
- $(Verb) $(LLVMTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<
-
-$(ObjDir)/DarwinLdOptions.inc.tmp : DarwinLdOptions.td $(LLVM_TBLGEN) $(ObjDir)/.dir
- $(Echo) "Building LLD Darwin ld Option tables with tblgen"
- $(Verb) $(LLVMTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<
-
-$(ObjDir)/GnuLdOptions.inc.tmp : GnuLdOptions.td $(LLVM_TBLGEN) $(ObjDir)/.dir
- $(Echo) "Building LLD Gnu ld Option tables with tblgen"
- $(Verb) $(LLVMTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<
-
-$(ObjDir)/WinLinkOptions.inc.tmp : WinLinkOptions.td $(LLVM_TBLGEN) $(ObjDir)/.dir
- $(Echo) "Building LLD WinLinkOptions Option tables with tblgen"
- $(Verb) $(LLVMTableGen) -gen-opt-parser-defs -o $(call SYSPATH, $@) $<
diff --git a/lib/Driver/TODO.rst b/lib/Driver/TODO.rst
index e03d829c232d..868eaf02290c 100644
--- a/lib/Driver/TODO.rst
+++ b/lib/Driver/TODO.rst
@@ -35,8 +35,6 @@ Missing Options
* -Ur
* --unique
* -v,--version,-V
-* -x,--discard-all
-* -X,--discard-locals
* -y,--trace-symbol
* -z (keywords need to be implemented)
* --accept-unknown-input-arch,--no-accept-unknown-input-arch
diff --git a/lib/Driver/UniversalDriver.cpp b/lib/Driver/UniversalDriver.cpp
index 7d42ad7b4bfc..3dea7ebfae89 100644
--- a/lib/Driver/UniversalDriver.cpp
+++ b/lib/Driver/UniversalDriver.cpp
@@ -63,15 +63,16 @@ static const llvm::opt::OptTable::Info infoTable[] = {
class UniversalDriverOptTable : public llvm::opt::OptTable {
public:
UniversalDriverOptTable()
- : OptTable(infoTable, llvm::array_lengthof(infoTable)) {}
+ : OptTable(infoTable) {}
};
enum class Flavor {
invalid,
- gnu_ld, // -flavor gnu
- win_link, // -flavor link
- darwin_ld, // -flavor darwin
- core // -flavor core OR -core
+ 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 {
@@ -83,7 +84,9 @@ struct ProgramNameParts {
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)
@@ -124,27 +127,27 @@ static ProgramNameParts parseProgramName(StringRef programName) {
// Removes the argument from argv along with its value, if exists, and updates
// argc.
-static void removeArg(llvm::opt::Arg *arg, int &argc, const char **&argv) {
+static void removeArg(llvm::opt::Arg *arg,
+ llvm::MutableArrayRef<const char *> &args) {
unsigned int numToRemove = arg->getNumValues() + 1;
- unsigned int argIndex = arg->getIndex() + 1;
-
- std::rotate(&argv[argIndex], &argv[argIndex + numToRemove], argv + argc);
- argc -= numToRemove;
+ auto sub = args.slice(arg->getIndex() + 1);
+ std::rotate(sub.begin(), sub.begin() + numToRemove, sub.end());
+ args = args.drop_back(numToRemove);
}
-static Flavor getFlavor(int &argc, const char **&argv,
- std::unique_ptr<llvm::opt::InputArgList> &parsedArgs) {
- if (llvm::opt::Arg *argCore = parsedArgs->getLastArg(OPT_core)) {
- removeArg(argCore, argc, argv);
+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, argc, argv);
+ 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(argv[0]).equals("ld")) {
+ 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;
@@ -154,59 +157,63 @@ static Flavor getFlavor(int &argc, const char **&argv,
}
#endif
- StringRef name = llvm::sys::path::stem(argv[0]);
+ 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(int argc, const char *argv[],
+bool UniversalDriver::link(llvm::MutableArrayRef<const char *> args,
raw_ostream &diagnostics) {
// Parse command line options using GnuLdOptions.td
- std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
UniversalDriverOptTable table;
unsigned missingIndex;
unsigned missingCount;
// Program name
- StringRef programName = llvm::sys::path::stem(argv[0]);
+ StringRef programName = llvm::sys::path::stem(args[0]);
- parsedArgs.reset(
- table.ParseArgs(&argv[1], &argv[argc], missingIndex, missingCount));
+ llvm::opt::InputArgList parsedArgs =
+ table.ParseArgs(args.slice(1), missingIndex, missingCount);
if (missingCount) {
diagnostics << "error: missing arg value for '"
- << parsedArgs->getArgString(missingIndex) << "' expected "
+ << parsedArgs.getArgString(missingIndex) << "' expected "
<< missingCount << " argument(s).\n";
return false;
}
// Handle -help
- if (parsedArgs->getLastArg(OPT_help)) {
+ if (parsedArgs.getLastArg(OPT_help)) {
table.PrintHelp(llvm::outs(), programName.data(), "LLVM Linker", false);
return true;
}
// Handle -version
- if (parsedArgs->getLastArg(OPT_version)) {
+ if (parsedArgs.getLastArg(OPT_version)) {
diagnostics << "LLVM Linker Version: " << getLLDVersion()
<< getLLDRepositoryVersion() << "\n";
return true;
}
- Flavor flavor = getFlavor(argc, argv, parsedArgs);
- std::vector<const char *> args(argv, argv + argc);
+ 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:
- return GnuLdDriver::linkELF(args.size(), args.data(), diagnostics);
+ elf2::link(args);
+ return true;
case Flavor::darwin_ld:
- return DarwinLdDriver::linkMachO(args.size(), args.data(), diagnostics);
+ return DarwinLdDriver::linkMachO(args, diagnostics);
case Flavor::win_link:
- return WinLinkDriver::linkPECOFF(args.size(), args.data(), diagnostics);
+ coff::link(args);
+ return true;
case Flavor::core:
- return CoreDriver::link(args.size(), args.data(), diagnostics);
+ return CoreDriver::link(args, diagnostics);
case Flavor::invalid:
diagnostics << "Select the appropriate flavor\n";
table.PrintHelp(llvm::outs(), programName.data(), "LLVM Linker", false);
diff --git a/lib/Driver/WinLinkDriver.cpp b/lib/Driver/WinLinkDriver.cpp
deleted file mode 100644
index 6ee7a5a004b5..000000000000
--- a/lib/Driver/WinLinkDriver.cpp
+++ /dev/null
@@ -1,1371 +0,0 @@
-//===- lib/Driver/WinLinkDriver.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 Windows link.exe.
-///
-//===----------------------------------------------------------------------===//
-
-#include "lld/Driver/Driver.h"
-#include "lld/Driver/WinLinkModuleDef.h"
-#include "lld/ReaderWriter/PECOFFLinkingContext.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Object/COFF.h"
-#include "llvm/Option/Arg.h"
-#include "llvm/Option/Option.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Process.h"
-#include "llvm/Support/Program.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <cctype>
-#include <map>
-#include <memory>
-#include <sstream>
-#include <tuple>
-
-namespace lld {
-
-//
-// Option definitions
-//
-
-// Create enum with OPT_xxx values for each option in WinLinkOptions.td
-enum {
- OPT_INVALID = 0,
-#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
- HELP, META) \
- OPT_##ID,
-#include "WinLinkOptions.inc"
-#undef OPTION
-};
-
-// Create prefix string literals used in WinLinkOptions.td
-#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
-#include "WinLinkOptions.inc"
-#undef PREFIX
-
-// Create table mapping all options defined in WinLinkOptions.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 "WinLinkOptions.inc"
-#undef OPTION
-};
-
-namespace {
-
-// Create OptTable class for parsing actual command line arguments
-class WinLinkOptTable : public llvm::opt::OptTable {
-public:
- // link.exe's command line options are case insensitive, unlike
- // other driver's options for Unix.
- WinLinkOptTable()
- : OptTable(infoTable, llvm::array_lengthof(infoTable),
- /* ignoreCase */ true) {}
-};
-
-} // anonymous namespace
-
-//
-// Functions to parse each command line option
-//
-
-// Split the given string with spaces.
-static std::vector<std::string> splitArgList(const std::string &str) {
- std::stringstream stream(str);
- std::istream_iterator<std::string> begin(stream);
- std::istream_iterator<std::string> end;
- return std::vector<std::string>(begin, end);
-}
-
-// Split the given string with the path separator.
-static std::vector<StringRef> splitPathList(StringRef str) {
- std::vector<StringRef> ret;
- while (!str.empty()) {
- StringRef path;
- std::tie(path, str) = str.split(';');
- ret.push_back(path);
- }
- return ret;
-}
-
-// Parse an argument for /alternatename. The expected string is
-// "<string>=<string>".
-static bool parseAlternateName(StringRef arg, StringRef &weak, StringRef &def,
- raw_ostream &diag) {
- std::tie(weak, def) = arg.split('=');
- if (weak.empty() || def.empty()) {
- diag << "Error: malformed /alternatename option: " << arg << "\n";
- return false;
- }
- return true;
-}
-
-// Parse an argument for /base, /stack or /heap. The expected string
-// is "<integer>[,<integer>]".
-static bool parseMemoryOption(StringRef arg, uint64_t &reserve,
- uint64_t &commit) {
- StringRef reserveStr, commitStr;
- std::tie(reserveStr, commitStr) = arg.split(',');
- if (reserveStr.getAsInteger(0, reserve))
- return false;
- if (!commitStr.empty() && commitStr.getAsInteger(0, commit))
- return false;
- return true;
-}
-
-// Parse an argument for /version or /subsystem. The expected string is
-// "<integer>[.<integer>]".
-static bool parseVersion(StringRef arg, uint32_t &major, uint32_t &minor) {
- StringRef majorVersion, minorVersion;
- std::tie(majorVersion, minorVersion) = arg.split('.');
- if (minorVersion.empty())
- minorVersion = "0";
- if (majorVersion.getAsInteger(0, major))
- return false;
- if (minorVersion.getAsInteger(0, minor))
- return false;
- return true;
-}
-
-// Returns subsystem type for the given string.
-static llvm::COFF::WindowsSubsystem stringToWinSubsystem(StringRef str) {
- return llvm::StringSwitch<llvm::COFF::WindowsSubsystem>(str.lower())
- .Case("windows", llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI)
- .Case("console", llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI)
- .Case("boot_application",
- llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION)
- .Case("efi_application", llvm::COFF::IMAGE_SUBSYSTEM_EFI_APPLICATION)
- .Case("efi_boot_service_driver",
- llvm::COFF::IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
- .Case("efi_rom", llvm::COFF::IMAGE_SUBSYSTEM_EFI_ROM)
- .Case("efi_runtime_driver",
- llvm::COFF::IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER)
- .Case("native", llvm::COFF::IMAGE_SUBSYSTEM_NATIVE)
- .Case("posix", llvm::COFF::IMAGE_SUBSYSTEM_POSIX_CUI)
- .Default(llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN);
-}
-
-// Parse /subsystem command line option. The form of /subsystem is
-// "subsystem_name[,majorOSVersion[.minorOSVersion]]".
-static bool parseSubsystem(StringRef arg,
- llvm::COFF::WindowsSubsystem &subsystem,
- llvm::Optional<uint32_t> &major,
- llvm::Optional<uint32_t> &minor, raw_ostream &diag) {
- StringRef subsystemStr, osVersion;
- std::tie(subsystemStr, osVersion) = arg.split(',');
- if (!osVersion.empty()) {
- uint32_t v1, v2;
- if (!parseVersion(osVersion, v1, v2))
- return false;
- major = v1;
- minor = v2;
- }
- subsystem = stringToWinSubsystem(subsystemStr);
- if (subsystem == llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN) {
- diag << "error: unknown subsystem name: " << subsystemStr << "\n";
- return false;
- }
- return true;
-}
-
-static llvm::COFF::MachineTypes stringToMachineType(StringRef str) {
- // FIXME: we have no way to differentiate between ARM and ARMNT currently.
- // However, given that LLVM only supports ARM NT, default to that for now.
- return llvm::StringSwitch<llvm::COFF::MachineTypes>(str.lower())
- .Case("arm", llvm::COFF::IMAGE_FILE_MACHINE_ARMNT)
- .Case("x64", llvm::COFF::IMAGE_FILE_MACHINE_AMD64)
- .Case("x86", llvm::COFF::IMAGE_FILE_MACHINE_I386)
- .Default(llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN);
-}
-
-// Parse /section:name,[[!]{DEKPRSW}]
-//
-// /section option is to set non-default bits in the Characteristics fields of
-// the section header. D, E, K, P, R, S, and W represent discardable,
-// execute, not_cachable, not_pageable, read, shared, and write bits,
-// respectively. You can specify multiple flags in one /section option.
-//
-// If the flag starts with "!", the flags represent a mask that should be turned
-// off regardless of the default value. You can even create a section which is
-// not readable, writable nor executable with this -- although it's probably
-// useless.
-static bool parseSection(StringRef option, std::string &section,
- llvm::Optional<uint32_t> &flags,
- llvm::Optional<uint32_t> &mask) {
- StringRef flagString;
- std::tie(section, flagString) = option.split(",");
-
- bool negative = false;
- if (flagString.startswith("!")) {
- negative = true;
- flagString = flagString.substr(1);
- }
- if (flagString.empty())
- return false;
-
- uint32_t attribs = 0;
- for (size_t i = 0, e = flagString.size(); i < e; ++i) {
- switch (tolower(flagString[i])) {
-#define CASE(c, flag) \
- case c: \
- attribs |= flag; \
- break
- CASE('d', llvm::COFF::IMAGE_SCN_MEM_DISCARDABLE);
- CASE('e', llvm::COFF::IMAGE_SCN_MEM_EXECUTE);
- CASE('k', llvm::COFF::IMAGE_SCN_MEM_NOT_CACHED);
- CASE('p', llvm::COFF::IMAGE_SCN_MEM_NOT_PAGED);
- CASE('r', llvm::COFF::IMAGE_SCN_MEM_READ);
- CASE('s', llvm::COFF::IMAGE_SCN_MEM_SHARED);
- CASE('w', llvm::COFF::IMAGE_SCN_MEM_WRITE);
-#undef CASE
- default:
- return false;
- }
- }
-
- if (negative) {
- mask = attribs;
- } else {
- flags = attribs;
- }
- return true;
-}
-
-static bool readFile(PECOFFLinkingContext &ctx, StringRef path,
- ArrayRef<uint8_t> &result) {
- ErrorOr<std::unique_ptr<MemoryBuffer>> buf = MemoryBuffer::getFile(path);
- if (!buf)
- return false;
- StringRef Data = buf.get()->getBuffer();
- result = ctx.allocate(ArrayRef<uint8_t>(
- reinterpret_cast<const uint8_t *>(Data.begin()), Data.size()));
- return true;
-}
-
-// Parse /manifest:EMBED[,ID=#]|NO.
-static bool parseManifest(StringRef option, bool &enable, bool &embed,
- int &id) {
- if (option.equals_lower("no")) {
- enable = false;
- return true;
- }
- if (!option.startswith_lower("embed"))
- return false;
-
- embed = true;
- option = option.substr(strlen("embed"));
- if (option.empty())
- return true;
- if (!option.startswith_lower(",id="))
- return false;
- option = option.substr(strlen(",id="));
- if (option.getAsInteger(0, id))
- return false;
- return true;
-}
-
-static bool isLibraryFile(StringRef path) {
- return path.endswith_lower(".lib") || path.endswith_lower(".imp");
-}
-
-static StringRef getObjectPath(PECOFFLinkingContext &ctx, StringRef path) {
- std::string result;
- if (isLibraryFile(path)) {
- result = ctx.searchLibraryFile(path);
- } else if (llvm::sys::path::extension(path).empty()) {
- result = path.str() + ".obj";
- } else {
- result = path;
- }
- return ctx.allocate(result);
-}
-
-static StringRef getLibraryPath(PECOFFLinkingContext &ctx, StringRef path) {
- std::string result = isLibraryFile(path)
- ? ctx.searchLibraryFile(path)
- : ctx.searchLibraryFile(path.str() + ".lib");
- return ctx.allocate(result);
-}
-
-// Returns true if the given file is a Windows resource file.
-static bool isResoruceFile(StringRef path) {
- llvm::sys::fs::file_magic fileType;
- if (llvm::sys::fs::identify_magic(path, fileType)) {
- // If we cannot read the file, assume it's not a resource file.
- // The further stage will raise an error on this unreadable file.
- return false;
- }
- return fileType == llvm::sys::fs::file_magic::windows_resource;
-}
-
-// Merge Windows resource files and convert them to a single COFF file.
-// The temporary file path is set to result.
-static bool convertResourceFiles(PECOFFLinkingContext &ctx,
- std::vector<std::string> inFiles,
- std::string &result) {
- // Create an output file path.
- SmallString<128> outFile;
- if (llvm::sys::fs::createTemporaryFile("resource", "obj", outFile))
- return false;
- std::string outFileArg = ("/out:" + outFile).str();
-
- // Construct CVTRES.EXE command line and execute it.
- std::string program = "cvtres.exe";
- ErrorOr<std::string> programPathOrErr = llvm::sys::findProgramByName(program);
- if (!programPathOrErr) {
- llvm::errs() << "Unable to find " << program << " in PATH\n";
- return false;
- }
- const std::string &programPath = *programPathOrErr;
-
- std::vector<const char *> args;
- args.push_back(programPath.c_str());
- args.push_back(ctx.is64Bit() ? "/machine:x64" : "/machine:x86");
- args.push_back("/readonly");
- args.push_back("/nologo");
- args.push_back(outFileArg.c_str());
- for (const std::string &path : inFiles)
- args.push_back(path.c_str());
- args.push_back(nullptr);
-
- if (llvm::sys::ExecuteAndWait(programPath.c_str(), &args[0]) != 0) {
- llvm::errs() << program << " failed\n";
- return false;
- }
- result = outFile.str();
- return true;
-}
-
-// Parse /manifestuac:(level=<string>|uiAccess=<string>).
-//
-// The arguments will be embedded to the manifest XML file with no error check,
-// so the values given via the command line must be valid as XML attributes.
-// This may sound a bit odd, but that's how link.exe works, so we will follow.
-static bool parseManifestUAC(StringRef option,
- llvm::Optional<std::string> &level,
- llvm::Optional<std::string> &uiAccess) {
- for (;;) {
- option = option.ltrim();
- if (option.empty())
- return true;
- if (option.startswith_lower("level=")) {
- option = option.substr(strlen("level="));
- StringRef value;
- std::tie(value, option) = option.split(" ");
- level = value.str();
- continue;
- }
- if (option.startswith_lower("uiaccess=")) {
- option = option.substr(strlen("uiaccess="));
- StringRef value;
- std::tie(value, option) = option.split(" ");
- uiAccess = value.str();
- continue;
- }
- return false;
- }
-}
-
-// Returns the machine type (e.g. x86) of the given input file.
-// If the file is not COFF, returns false.
-static bool getMachineType(StringRef path, llvm::COFF::MachineTypes &result) {
- llvm::sys::fs::file_magic fileType;
- if (llvm::sys::fs::identify_magic(path, fileType))
- return false;
- if (fileType != llvm::sys::fs::file_magic::coff_object)
- return false;
- ErrorOr<std::unique_ptr<MemoryBuffer>> buf = MemoryBuffer::getFile(path);
- if (!buf)
- return false;
- std::error_code ec;
- llvm::object::COFFObjectFile obj(buf.get()->getMemBufferRef(), ec);
- if (ec)
- return false;
- result = static_cast<llvm::COFF::MachineTypes>(obj.getMachine());
- return true;
-}
-
-// Parse /export:entryname[=internalname][,@ordinal[,NONAME]][,DATA][,PRIVATE].
-//
-// MSDN doesn't say anything about /export:foo=bar style option or PRIVATE
-// attribtute, but link.exe actually accepts them.
-static bool parseExport(StringRef option,
- PECOFFLinkingContext::ExportDesc &ret) {
- StringRef name;
- StringRef rest;
- std::tie(name, rest) = option.split(",");
- if (name.empty())
- return false;
- if (name.find('=') == StringRef::npos) {
- ret.name = name;
- } else {
- std::tie(ret.externalName, ret.name) = name.split("=");
- if (ret.name.empty())
- return false;
- }
-
- for (;;) {
- if (rest.empty())
- return true;
- StringRef arg;
- std::tie(arg, rest) = rest.split(",");
- if (arg.equals_lower("noname")) {
- if (ret.ordinal < 0)
- return false;
- ret.noname = true;
- continue;
- }
- if (arg.equals_lower("data")) {
- ret.isData = true;
- continue;
- }
- if (arg.equals_lower("private")) {
- ret.isPrivate = true;
- continue;
- }
- if (arg.startswith("@")) {
- int ordinal;
- if (arg.substr(1).getAsInteger(0, ordinal))
- return false;
- if (ordinal <= 0 || 65535 < ordinal)
- return false;
- ret.ordinal = ordinal;
- continue;
- }
- return false;
- }
-}
-
-// Read module-definition file.
-static bool parseDef(StringRef option, llvm::BumpPtrAllocator &alloc,
- std::vector<moduledef::Directive *> &result) {
- ErrorOr<std::unique_ptr<MemoryBuffer>> buf = MemoryBuffer::getFile(option);
- if (!buf)
- return false;
- moduledef::Lexer lexer(std::move(buf.get()));
- moduledef::Parser parser(lexer, alloc);
- return parser.parse(result);
-}
-
-static StringRef replaceExtension(PECOFFLinkingContext &ctx, StringRef path,
- StringRef extension) {
- SmallString<128> val = path;
- llvm::sys::path::replace_extension(val, extension);
- return ctx.allocate(val.str());
-}
-
-// Create a manifest file contents.
-static std::string createManifestXml(PECOFFLinkingContext &ctx) {
- std::string ret;
- llvm::raw_string_ostream out(ret);
- // Emit the XML. Note that we do *not* verify that the XML attributes are
- // syntactically correct. This is intentional for link.exe compatibility.
- out << "<?xml version=\"1.0\" standalone=\"yes\"?>\n"
- "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\"\n"
- " manifestVersion=\"1.0\">\n";
- if (ctx.getManifestUAC()) {
- out << " <trustInfo>\n"
- " <security>\n"
- " <requestedPrivileges>\n"
- " <requestedExecutionLevel level=" << ctx.getManifestLevel()
- << " uiAccess=" << ctx.getManifestUiAccess()
- << "/>\n"
- " </requestedPrivileges>\n"
- " </security>\n"
- " </trustInfo>\n";
- const std::string &dependency = ctx.getManifestDependency();
- if (!dependency.empty()) {
- out << " <dependency>\n"
- " <dependentAssembly>\n"
- " <assemblyIdentity " << dependency
- << " />\n"
- " </dependentAssembly>\n"
- " </dependency>\n";
- }
- }
- out << "</assembly>\n";
- out.flush();
- return ret;
-}
-
-// Convert one doublequote to two doublequotes, so that we can embed the string
-// into a resource script file.
-static void quoteAndPrintXml(raw_ostream &out, StringRef str) {
- for (;;) {
- if (str.empty())
- return;
- StringRef line;
- std::tie(line, str) = str.split("\n");
- if (line.empty())
- continue;
- out << '\"';
- const char *p = line.data();
- for (int i = 0, size = line.size(); i < size; ++i) {
- switch (p[i]) {
- case '\"':
- out << '\"';
- // fallthrough
- default:
- out << p[i];
- }
- }
- out << "\"\n";
- }
-}
-
-// Create a resource file (.res file) containing the manifest XML. This is done
-// in two steps:
-//
-// 1. Create a resource script file containing the XML as a literal string.
-// 2. Run RC.EXE command to compile the script file to a resource file.
-//
-// The temporary file created in step 1 will be deleted on exit from this
-// function. The file created in step 2 will have the same lifetime as the
-// PECOFFLinkingContext.
-static bool createManifestResourceFile(PECOFFLinkingContext &ctx,
- raw_ostream &diag,
- std::string &resFile) {
- // Create a temporary file for the resource script file.
- SmallString<128> rcFileSmallString;
- if (llvm::sys::fs::createTemporaryFile("tmp", "rc", rcFileSmallString)) {
- diag << "Cannot create a temporary file\n";
- return false;
- }
- StringRef rcFile(rcFileSmallString.str());
- llvm::FileRemover rcFileRemover((Twine(rcFile)));
-
- // Open the temporary file for writing.
- std::error_code ec;
- llvm::raw_fd_ostream out(rcFileSmallString, ec, llvm::sys::fs::F_Text);
- if (ec) {
- diag << "Failed to open " << ctx.getManifestOutputPath() << ": "
- << ec.message() << "\n";
- return false;
- }
-
- // Write resource script to the RC file.
- out << "#define LANG_ENGLISH 9\n"
- << "#define SUBLANG_DEFAULT 1\n"
- << "#define APP_MANIFEST " << ctx.getManifestId() << "\n"
- << "#define RT_MANIFEST 24\n"
- << "LANGUAGE LANG_ENGLISH, SUBLANG_DEFAULT\n"
- << "APP_MANIFEST RT_MANIFEST {\n";
- quoteAndPrintXml(out, createManifestXml(ctx));
- out << "}\n";
- out.close();
-
- // Create output resource file.
- SmallString<128> resFileSmallString;
- if (llvm::sys::fs::createTemporaryFile("tmp", "res", resFileSmallString)) {
- diag << "Cannot create a temporary file";
- return false;
- }
- resFile = resFileSmallString.str();
-
- // Register the resource file path so that the file will be deleted when the
- // context's destructor is called.
- ctx.registerTemporaryFile(resFile);
-
- // Run RC.EXE /fo tmp.res tmp.rc
- std::string program = "rc.exe";
- ErrorOr<std::string> programPathOrErr = llvm::sys::findProgramByName(program);
- if (!programPathOrErr) {
- diag << "Unable to find " << program << " in PATH\n";
- return false;
- }
- const std::string &programPath = *programPathOrErr;
- std::vector<const char *> args;
- args.push_back(programPath.c_str());
- args.push_back("/fo");
- args.push_back(resFile.c_str());
- args.push_back("/nologo");
- args.push_back(rcFileSmallString.c_str());
- args.push_back(nullptr);
-
- if (llvm::sys::ExecuteAndWait(programPath.c_str(), &args[0]) != 0) {
- diag << program << " failed\n";
- return false;
- }
- return true;
-}
-
-
-// Create the a side-by-side manifest file.
-//
-// The manifest file will convey some information to the linker, such as whether
-// the binary needs to run as Administrator or not. Instead of being placed in
-// the PE/COFF header, it's in XML format for some reason -- I guess it's
-// probably because it's invented in the early dot-com era.
-//
-// The side-by-side manifest file is a separate XML file having ".manifest"
-// extension. It will be created in the same directory as the resulting
-// executable.
-static bool createSideBySideManifestFile(PECOFFLinkingContext &ctx,
- raw_ostream &diag) {
- std::string path = ctx.getManifestOutputPath();
- if (path.empty()) {
- // Default name of the manifest file is "foo.exe.manifest" where "foo.exe" is
- // the output path.
- path = ctx.outputPath();
- path.append(".manifest");
- }
-
- std::error_code ec;
- llvm::raw_fd_ostream out(path, ec, llvm::sys::fs::F_Text);
- if (ec) {
- diag << ec.message() << "\n";
- return false;
- }
- out << createManifestXml(ctx);
- return true;
-}
-
-// Handle /failifmismatch option.
-static bool
-handleFailIfMismatchOption(StringRef option,
- std::map<StringRef, StringRef> &mustMatch,
- raw_ostream &diag) {
- StringRef key, value;
- std::tie(key, value) = option.split('=');
- if (key.empty() || value.empty()) {
- diag << "error: malformed /failifmismatch option: " << option << "\n";
- return true;
- }
- auto it = mustMatch.find(key);
- if (it != mustMatch.end() && it->second != value) {
- diag << "error: mismatch detected: '" << it->second << "' and '" << value
- << "' for key '" << key << "'\n";
- return true;
- }
- mustMatch[key] = value;
- return false;
-}
-
-//
-// Environment variable
-//
-
-// Process "LINK" environment variable. If defined, the value of the variable
-// should be processed as command line arguments.
-static std::vector<const char *> processLinkEnv(PECOFFLinkingContext &ctx,
- int argc, const char **argv) {
- std::vector<const char *> ret;
- // The first argument is the name of the command. This should stay at the head
- // of the argument list.
- assert(argc > 0);
- ret.push_back(argv[0]);
-
- // Add arguments specified by the LINK environment variable.
- llvm::Optional<std::string> env = llvm::sys::Process::GetEnv("LINK");
- if (env.hasValue())
- for (std::string &arg : splitArgList(*env))
- ret.push_back(ctx.allocate(arg).data());
-
- // Add the rest of arguments passed via the command line.
- for (int i = 1; i < argc; ++i)
- ret.push_back(argv[i]);
- ret.push_back(nullptr);
- return ret;
-}
-
-// Process "LIB" environment variable. The variable contains a list of search
-// paths separated by semicolons.
-static void processLibEnv(PECOFFLinkingContext &ctx) {
- llvm::Optional<std::string> env = llvm::sys::Process::GetEnv("LIB");
- if (env.hasValue())
- for (StringRef path : splitPathList(*env))
- ctx.appendInputSearchPath(ctx.allocate(path));
-}
-
-namespace {
-class DriverStringSaver : public llvm::cl::StringSaver {
-public:
- DriverStringSaver(PECOFFLinkingContext &ctx) : _ctx(ctx) {}
-
- const char *SaveString(const char *s) override {
- return _ctx.allocate(StringRef(s)).data();
- }
-
-private:
- PECOFFLinkingContext &_ctx;
-};
-}
-
-// Tokenize command line options in a given file and add them to result.
-static bool readResponseFile(StringRef path, PECOFFLinkingContext &ctx,
- std::vector<const char *> &result) {
- ArrayRef<uint8_t> contents;
- if (!readFile(ctx, path, contents))
- return false;
- StringRef contentsStr(reinterpret_cast<const char *>(contents.data()),
- contents.size());
- DriverStringSaver saver(ctx);
- SmallVector<const char *, 0> args;
- llvm::cl::TokenizeWindowsCommandLine(contentsStr, saver, args);
- for (const char *s : args)
- result.push_back(s);
- return true;
-}
-
-// Expand arguments starting with "@". It's an error if a specified file does
-// not exist. Returns true on success.
-static bool expandResponseFiles(int &argc, const char **&argv,
- PECOFFLinkingContext &ctx, raw_ostream &diag,
- bool &expanded) {
- std::vector<const char *> newArgv;
- for (int i = 0; i < argc; ++i) {
- if (argv[i][0] != '@') {
- newArgv.push_back(argv[i]);
- continue;
- }
- StringRef filename = StringRef(argv[i] + 1);
- if (!readResponseFile(filename, ctx, newArgv)) {
- diag << "error: cannot read response file: " << filename << "\n";
- return false;
- }
- expanded = true;
- }
- if (!expanded)
- return true;
- argc = newArgv.size();
- newArgv.push_back(nullptr);
- argv = &ctx.allocateCopy(newArgv)[0];
- return true;
-}
-
-// Parses the given command line options and returns the result. Returns NULL if
-// there's an error in the options.
-static std::unique_ptr<llvm::opt::InputArgList>
-parseArgs(int argc, const char **argv, PECOFFLinkingContext &ctx,
- raw_ostream &diag, bool isReadingDirectiveSection) {
- // Expand arguments starting with "@".
- bool expanded = false;
- if (!expandResponseFiles(argc, argv, ctx, diag, expanded))
- return nullptr;
-
- // Parse command line options using WinLinkOptions.td
- std::unique_ptr<llvm::opt::InputArgList> parsedArgs;
- WinLinkOptTable table;
- unsigned missingIndex;
- unsigned missingCount;
- parsedArgs.reset(table.ParseArgs(&argv[1], &argv[argc],
- missingIndex, missingCount));
- if (missingCount) {
- diag << "error: missing arg value for '"
- << parsedArgs->getArgString(missingIndex) << "' expected "
- << missingCount << " argument(s).\n";
- return nullptr;
- }
-
- // Show warning for unknown arguments. In .drectve section, unknown options
- // starting with "-?" are silently ignored. This is a COFF's feature to embed a
- // new linker option to an object file while keeping backward compatibility.
- for (auto unknownArg : parsedArgs->filtered(OPT_UNKNOWN)) {
- StringRef arg = unknownArg->getSpelling();
- if (isReadingDirectiveSection && arg.startswith("-?"))
- continue;
- diag << "warning: ignoring unknown argument: " << arg << "\n";
- }
-
- // Copy mllvm
- for (auto arg : parsedArgs->filtered(OPT_mllvm))
- ctx.appendLLVMOption(arg->getValue());
-
- // If we have expaneded response files and /verbose is given, print out the
- // final command line.
- if (!isReadingDirectiveSection && expanded &&
- parsedArgs->getLastArg(OPT_verbose)) {
- diag << "Command line:";
- for (int i = 0; i < argc; ++i)
- diag << " " << argv[i];
- diag << "\n\n";
- }
-
- return parsedArgs;
-}
-
-// Returns true if the given file node has already been added to the input
-// graph.
-static bool hasLibrary(PECOFFLinkingContext &ctx, File *file) {
- StringRef path = file->path();
- for (std::unique_ptr<Node> &p : ctx.getNodes())
- if (auto *f = dyn_cast<FileNode>(p.get()))
- if (f->getFile()->path() == path)
- return true;
- return false;
-}
-
-// If the first command line argument is "/lib", link.exe acts as if it's
-// "lib.exe" command. This is for backward compatibility.
-// http://msdn.microsoft.com/en-us/library/h34w59b3.aspx
-static bool maybeRunLibCommand(int argc, const char **argv, raw_ostream &diag) {
- if (argc <= 1)
- return false;
- if (!StringRef(argv[1]).equals_lower("/lib"))
- return false;
- ErrorOr<std::string> pathOrErr = llvm::sys::findProgramByName("lib.exe");
- if (!pathOrErr) {
- diag << "Unable to find lib.exe in PATH\n";
- return true;
- }
- const std::string &path = *pathOrErr;
-
- // Run lib.exe
- std::vector<const char *> vec;
- vec.push_back(path.c_str());
- for (int i = 2; i < argc; ++i)
- vec.push_back(argv[i]);
- vec.push_back(nullptr);
-
- if (llvm::sys::ExecuteAndWait(path.c_str(), &vec[0]) != 0)
- diag << "lib.exe failed\n";
- return true;
-}
-
-/// \brief Parse the input file to lld::File.
-void addFiles(PECOFFLinkingContext &ctx, StringRef path, raw_ostream &diag,
- std::vector<std::unique_ptr<File>> &files) {
- for (std::unique_ptr<File> &file : loadFile(ctx, path, false)) {
- if (ctx.logInputFiles())
- diag << file->path() << "\n";
- files.push_back(std::move(file));
- }
-}
-
-//
-// Main driver
-//
-
-bool WinLinkDriver::linkPECOFF(int argc, const char **argv, raw_ostream &diag) {
- if (maybeRunLibCommand(argc, argv, diag))
- return true;
-
- PECOFFLinkingContext ctx;
- ctx.setParseDirectives(parseDirectives);
- ctx.registry().addSupportCOFFObjects(ctx);
- ctx.registry().addSupportCOFFImportLibraries(ctx);
- ctx.registry().addSupportArchives(ctx.logInputFiles());
- ctx.registry().addSupportNativeObjects();
- ctx.registry().addSupportYamlFiles();
-
- std::vector<const char *> newargv = processLinkEnv(ctx, argc, argv);
- processLibEnv(ctx);
- if (!parse(newargv.size() - 1, &newargv[0], ctx, diag))
- return false;
-
- // Create the file if needed.
- if (ctx.getCreateManifest() && !ctx.getEmbedManifest())
- if (!createSideBySideManifestFile(ctx, diag))
- return false;
-
- return link(ctx, diag);
-}
-
-bool WinLinkDriver::parse(int argc, const char *argv[],
- PECOFFLinkingContext &ctx, raw_ostream &diag,
- bool isReadingDirectiveSection) {
- // Parse may be called from multiple threads simultaneously to parse .drectve
- // sections. This function is not thread-safe because it mutates the context
- // object. So acquire the lock.
- std::lock_guard<std::recursive_mutex> lock(ctx.getMutex());
-
- std::map<StringRef, StringRef> failIfMismatchMap;
- // Parse the options.
- std::unique_ptr<llvm::opt::InputArgList> parsedArgs =
- parseArgs(argc, argv, ctx, diag, isReadingDirectiveSection);
- if (!parsedArgs)
- return false;
-
- // The list of input files.
- std::vector<std::unique_ptr<File>> files;
- std::vector<std::unique_ptr<File>> libraries;
-
- // Handle /help
- if (parsedArgs->hasArg(OPT_help)) {
- WinLinkOptTable table;
- table.PrintHelp(llvm::outs(), argv[0], "LLVM Linker", false);
- return false;
- }
-
- // Handle /machine before parsing all the other options, as the target machine
- // type affects how to handle other options. For example, x86 needs the
- // leading underscore to mangle symbols, while x64 doesn't need it.
- if (llvm::opt::Arg *inputArg = parsedArgs->getLastArg(OPT_machine)) {
- StringRef arg = inputArg->getValue();
- llvm::COFF::MachineTypes type = stringToMachineType(arg);
- if (type == llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN) {
- diag << "error: unknown machine type: " << arg << "\n";
- return false;
- }
- ctx.setMachineType(type);
- } else {
- // If /machine option is missing, we need to take a look at
- // the magic byte of the first object file to infer machine type.
- std::vector<StringRef> filePaths;
- for (auto arg : *parsedArgs)
- if (arg->getOption().getID() == OPT_INPUT)
- filePaths.push_back(arg->getValue());
- if (llvm::opt::Arg *arg = parsedArgs->getLastArg(OPT_DASH_DASH))
- filePaths.insert(filePaths.end(), arg->getValues().begin(),
- arg->getValues().end());
- for (StringRef path : filePaths) {
- llvm::COFF::MachineTypes type;
- if (!getMachineType(path, type))
- continue;
- if (type == llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN)
- continue;
- ctx.setMachineType(type);
- break;
- }
- }
-
- // Handle /nodefaultlib:<lib>. The same option without argument is handled in
- // the following for loop.
- for (auto *arg : parsedArgs->filtered(OPT_nodefaultlib))
- ctx.addNoDefaultLib(arg->getValue());
-
- // Handle /defaultlib. Argument of the option is added to the input file list
- // unless it's blacklisted by /nodefaultlib.
- std::vector<StringRef> defaultLibs;
- for (auto *arg : parsedArgs->filtered(OPT_defaultlib))
- defaultLibs.push_back(arg->getValue());
-
- // -alternatename:<alias>=<symbol>
- for (auto *arg : parsedArgs->filtered(OPT_alternatename)) {
- StringRef weak, def;
- if (!parseAlternateName(arg->getValue(), weak, def, diag))
- return false;
- ctx.addAlternateName(weak, def);
- }
-
- // Parse /base command line option. The argument for the parameter is in
- // the form of "<address>[:<size>]".
- if (auto *arg = parsedArgs->getLastArg(OPT_base)) {
- uint64_t addr, size;
- // Size should be set to SizeOfImage field in the COFF header, and if
- // it's smaller than the actual size, the linker should warn about that.
- // Currently we just ignore the value of size parameter.
- if (!parseMemoryOption(arg->getValue(), addr, size))
- return false;
- ctx.setBaseAddress(addr);
- }
-
- // Parse /dll command line option
- if (parsedArgs->hasArg(OPT_dll)) {
- ctx.setIsDll(true);
- // Default base address of a DLL is 0x10000000.
- if (!parsedArgs->hasArg(OPT_base))
- ctx.setBaseAddress(0x10000000);
- }
-
- // Parse /stack command line option
- if (auto *arg = parsedArgs->getLastArg(OPT_stack)) {
- uint64_t reserve;
- uint64_t commit = ctx.getStackCommit();
- if (!parseMemoryOption(arg->getValue(), reserve, commit))
- return false;
- ctx.setStackReserve(reserve);
- ctx.setStackCommit(commit);
- }
-
- // Parse /heap command line option
- if (auto *arg = parsedArgs->getLastArg(OPT_heap)) {
- uint64_t reserve;
- uint64_t commit = ctx.getHeapCommit();
- if (!parseMemoryOption(arg->getValue(), reserve, commit))
- return false;
- ctx.setHeapReserve(reserve);
- ctx.setHeapCommit(commit);
- }
-
- if (auto *arg = parsedArgs->getLastArg(OPT_align)) {
- uint32_t align;
- StringRef val = arg->getValue();
- if (val.getAsInteger(10, align)) {
- diag << "error: invalid value for /align: " << val << "\n";
- return false;
- }
- ctx.setSectionDefaultAlignment(align);
- }
-
- if (auto *arg = parsedArgs->getLastArg(OPT_version)) {
- uint32_t major, minor;
- if (!parseVersion(arg->getValue(), major, minor))
- return false;
- ctx.setImageVersion(PECOFFLinkingContext::Version(major, minor));
- }
-
- // Parse /merge:<from>=<to>.
- for (auto *arg : parsedArgs->filtered(OPT_merge)) {
- StringRef from, to;
- std::tie(from, to) = StringRef(arg->getValue()).split('=');
- if (from.empty() || to.empty()) {
- diag << "error: malformed /merge option: " << arg->getValue() << "\n";
- return false;
- }
- if (!ctx.addSectionRenaming(diag, from, to))
- return false;
- }
-
- // Parse /subsystem:<subsystem>[,<majorOSVersion>[.<minorOSVersion>]].
- if (auto *arg = parsedArgs->getLastArg(OPT_subsystem)) {
- llvm::COFF::WindowsSubsystem subsystem;
- llvm::Optional<uint32_t> major, minor;
- if (!parseSubsystem(arg->getValue(), subsystem, major, minor, diag))
- return false;
- ctx.setSubsystem(subsystem);
- if (major.hasValue())
- ctx.setMinOSVersion(PECOFFLinkingContext::Version(*major, *minor));
- }
-
- // Parse /section:name,[[!]{DEKPRSW}]
- for (auto *arg : parsedArgs->filtered(OPT_section)) {
- std::string section;
- llvm::Optional<uint32_t> flags, mask;
- if (!parseSection(arg->getValue(), section, flags, mask)) {
- diag << "Unknown argument for /section: " << arg->getValue() << "\n";
- return false;
- }
- if (flags.hasValue())
- ctx.setSectionSetMask(section, *flags);
- if (mask.hasValue())
- ctx.setSectionClearMask(section, *mask);
- }
-
- // Parse /manifest:EMBED[,ID=#]|NO.
- if (auto *arg = parsedArgs->getLastArg(OPT_manifest_colon)) {
- bool enable = true;
- bool embed = false;
- int id = 1;
- if (!parseManifest(arg->getValue(), enable, embed, id)) {
- diag << "Unknown argument for /manifest: " << arg->getValue() << "\n";
- return false;
- }
- ctx.setCreateManifest(enable);
- ctx.setEmbedManifest(embed);
- ctx.setManifestId(id);
- }
-
- // Parse /manifestuac.
- if (auto *arg = parsedArgs->getLastArg(OPT_manifestuac)) {
- if (StringRef(arg->getValue()).equals_lower("no")) {
- ctx.setManifestUAC(false);
- } else {
- llvm::Optional<std::string> privilegeLevel;
- llvm::Optional<std::string> uiAccess;
- if (!parseManifestUAC(arg->getValue(), privilegeLevel, uiAccess)) {
- diag << "Unknown argument for /manifestuac: " << arg->getValue()
- << "\n";
- return false;
- }
- if (privilegeLevel.hasValue())
- ctx.setManifestLevel(privilegeLevel.getValue());
- if (uiAccess.hasValue())
- ctx.setManifestUiAccess(uiAccess.getValue());
- }
- }
-
- if (auto *arg = parsedArgs->getLastArg(OPT_manifestfile))
- ctx.setManifestOutputPath(ctx.allocate(arg->getValue()));
-
- // /manifestdependency:<string> option. Note that the argument will be
- // embedded to the manifest XML file with no error check, for link.exe
- // compatibility. We do not gurantete that the resulting XML file is
- // valid.
- if (auto *arg = parsedArgs->getLastArg(OPT_manifestdependency))
- ctx.setManifestDependency(ctx.allocate(arg->getValue()));
-
- for (auto *arg : parsedArgs->filtered(OPT_failifmismatch))
- if (handleFailIfMismatchOption(arg->getValue(), failIfMismatchMap, diag))
- return false;
-
- if (auto *arg = parsedArgs->getLastArg(OPT_entry))
- ctx.setEntrySymbolName(ctx.allocate(arg->getValue()));
-
- for (auto *arg : parsedArgs->filtered(OPT_export)) {
- PECOFFLinkingContext::ExportDesc desc;
- if (!parseExport(arg->getValue(), desc)) {
- diag << "Error: malformed /export option: " << arg->getValue() << "\n";
- return false;
- }
-
- // Mangle the symbol name only if it is reading user-supplied command line
- // arguments. Because the symbol name in the .drectve section is already
- // mangled by the compiler, we shouldn't add a leading underscore in that
- // case. It's odd that the command line option has different semantics in
- // the .drectve section, but this behavior is needed for compatibility
- // with MSVC's link.exe.
- if (!isReadingDirectiveSection)
- desc.name = ctx.decorateSymbol(desc.name);
- ctx.addDllExport(desc);
- }
-
- for (auto *arg : parsedArgs->filtered(OPT_deffile)) {
- llvm::BumpPtrAllocator alloc;
- std::vector<moduledef::Directive *> dirs;
- if (!parseDef(arg->getValue(), alloc, dirs)) {
- diag << "Error: invalid module-definition file\n";
- return false;
- }
- for (moduledef::Directive *dir : dirs) {
- if (auto *exp = dyn_cast<moduledef::Exports>(dir)) {
- for (PECOFFLinkingContext::ExportDesc desc : exp->getExports()) {
- desc.name = ctx.decorateSymbol(desc.name);
- ctx.addDllExport(desc);
- }
- } else if (auto *hs = dyn_cast<moduledef::Heapsize>(dir)) {
- ctx.setHeapReserve(hs->getReserve());
- ctx.setHeapCommit(hs->getCommit());
- } else if (auto *lib = dyn_cast<moduledef::Library>(dir)) {
- ctx.setIsDll(true);
- ctx.setOutputPath(ctx.allocate(lib->getName()));
- if (lib->getBaseAddress() && !ctx.getBaseAddress())
- ctx.setBaseAddress(lib->getBaseAddress());
- } else if (auto *name = dyn_cast<moduledef::Name>(dir)) {
- if (!name->getOutputPath().empty() && ctx.outputPath().empty())
- ctx.setOutputPath(ctx.allocate(name->getOutputPath()));
- if (name->getBaseAddress() && ctx.getBaseAddress())
- ctx.setBaseAddress(name->getBaseAddress());
- } else if (auto *ver = dyn_cast<moduledef::Version>(dir)) {
- ctx.setImageVersion(PECOFFLinkingContext::Version(
- ver->getMajorVersion(), ver->getMinorVersion()));
- } else {
- llvm::dbgs() << static_cast<int>(dir->getKind()) << "\n";
- llvm_unreachable("Unknown module-definition directive.\n");
- }
- }
- }
-
- for (auto *arg : parsedArgs->filtered(OPT_libpath))
- ctx.appendInputSearchPath(ctx.allocate(arg->getValue()));
-
- for (auto *arg : parsedArgs->filtered(OPT_opt)) {
- std::string val = StringRef(arg->getValue()).lower();
- if (val == "noref") {
- ctx.setDeadStripping(false);
- } else if (val != "ref" && val != "icf" && val != "noicf" &&
- val != "lbr" && val != "nolbr" &&
- !StringRef(val).startswith("icf=")) {
- diag << "unknown option for /opt: " << val << "\n";
- return false;
- }
- }
-
- // LLD is not yet capable of creating a PDB file, so /debug does not have
- // any effect.
- // TODO: This should disable dead stripping. Currently we can't do that
- // because removal of associative sections depends on dead stripping.
- if (parsedArgs->hasArg(OPT_debug))
- ctx.setDebug(true);
-
- if (parsedArgs->hasArg(OPT_verbose))
- ctx.setLogInputFiles(true);
-
- // /force and /force:unresolved mean the same thing. We do not currently
- // support /force:multiple.
- if (parsedArgs->hasArg(OPT_force) ||
- parsedArgs->hasArg(OPT_force_unresolved)) {
- ctx.setAllowRemainingUndefines(true);
- }
-
- if (parsedArgs->hasArg(OPT_fixed)) {
- // /fixed is not compatible with /dynamicbase. Check for it.
- if (parsedArgs->hasArg(OPT_dynamicbase)) {
- diag << "/dynamicbase must not be specified with /fixed\n";
- return false;
- }
- ctx.setBaseRelocationEnabled(false);
- ctx.setDynamicBaseEnabled(false);
- }
-
- // /swaprun:{cd,net} options set IMAGE_FILE_{REMOVABLE,NET}_RUN_FROM_SWAP
- // bits in the COFF header, respectively. If one of the bits is on, the
- // Windows loader will copy the entire file to swap area then execute it,
- // so that the user can eject a CD or disconnect from the network.
- if (parsedArgs->hasArg(OPT_swaprun_cd))
- ctx.setSwapRunFromCD(true);
-
- if (parsedArgs->hasArg(OPT_swaprun_net))
- ctx.setSwapRunFromNet(true);
-
- if (parsedArgs->hasArg(OPT_profile)) {
- // /profile implies /opt:ref, /opt:noicf, /incremental:no and /fixed:no.
- ctx.setDeadStripping(true);
- ctx.setBaseRelocationEnabled(true);
- ctx.setDynamicBaseEnabled(true);
- }
-
- for (auto *arg : parsedArgs->filtered(OPT_implib))
- ctx.setOutputImportLibraryPath(arg->getValue());
-
- for (auto *arg : parsedArgs->filtered(OPT_delayload)) {
- ctx.addInitialUndefinedSymbol(ctx.getDelayLoadHelperName());
- ctx.addDelayLoadDLL(arg->getValue());
- }
-
- if (auto *arg = parsedArgs->getLastArg(OPT_stub)) {
- ArrayRef<uint8_t> contents;
- if (!readFile(ctx, arg->getValue(), contents)) {
- diag << "Failed to read DOS stub file " << arg->getValue() << "\n";
- return false;
- }
- ctx.setDosStub(contents);
- }
-
- for (auto *arg : parsedArgs->filtered(OPT_incl))
- ctx.addInitialUndefinedSymbol(ctx.allocate(arg->getValue()));
-
- if (parsedArgs->hasArg(OPT_noentry))
- ctx.setHasEntry(false);
-
- if (parsedArgs->hasArg(OPT_nodefaultlib_all))
- ctx.setNoDefaultLibAll(true);
-
- if (auto *arg = parsedArgs->getLastArg(OPT_out))
- ctx.setOutputPath(ctx.allocate(arg->getValue()));
-
- if (auto *arg = parsedArgs->getLastArg(OPT_pdb))
- ctx.setPDBFilePath(arg->getValue());
-
- if (auto *arg = parsedArgs->getLastArg(OPT_lldmoduledeffile))
- ctx.setModuleDefinitionFile(arg->getValue());
-
- std::vector<StringRef> inputFiles;
- for (auto *arg : parsedArgs->filtered(OPT_INPUT))
- inputFiles.push_back(ctx.allocate(arg->getValue()));
-
-#define BOOLEAN_FLAG(name, setter) \
- if (auto *arg = parsedArgs->getLastArg(OPT_##name, OPT_##name##_no)) \
- ctx.setter(arg->getOption().matches(OPT_##name));
-
- BOOLEAN_FLAG(nxcompat, setNxCompat);
- BOOLEAN_FLAG(largeaddressaware, setLargeAddressAware);
- BOOLEAN_FLAG(allowbind, setAllowBind);
- BOOLEAN_FLAG(allowisolation, setAllowIsolation);
- BOOLEAN_FLAG(dynamicbase, setDynamicBaseEnabled);
- BOOLEAN_FLAG(tsaware, setTerminalServerAware);
- BOOLEAN_FLAG(highentropyva, setHighEntropyVA);
- BOOLEAN_FLAG(safeseh, setSafeSEH);
-#undef BOOLEAN_FLAG
-
- // Arguments after "--" are interpreted as filenames even if they
- // start with a hypen or a slash. This is not compatible with link.exe
- // but useful for us to test lld on Unix.
- if (llvm::opt::Arg *dashdash = parsedArgs->getLastArg(OPT_DASH_DASH))
- for (const StringRef value : dashdash->getValues())
- inputFiles.push_back(value);
-
- // Compile Windows resource files to compiled resource file.
- if (ctx.getCreateManifest() && ctx.getEmbedManifest() &&
- !isReadingDirectiveSection) {
- std::string resFile;
- if (!createManifestResourceFile(ctx, diag, resFile))
- return false;
- inputFiles.push_back(ctx.allocate(resFile));
- }
-
- // A Windows Resource file is not an object file. It contains data,
- // such as an icon image, and is not in COFF file format. If resource
- // files are given, the linker merge them into one COFF file using
- // CVTRES.EXE and then link the resulting file.
- {
- auto it = std::partition(inputFiles.begin(), inputFiles.end(),
- isResoruceFile);
- if (it != inputFiles.begin()) {
- std::vector<std::string> resFiles(inputFiles.begin(), it);
- std::string resObj;
- if (!convertResourceFiles(ctx, resFiles, resObj)) {
- diag << "Failed to convert resource files\n";
- return false;
- }
- inputFiles = std::vector<StringRef>(it, inputFiles.end());
- inputFiles.push_back(ctx.allocate(resObj));
- ctx.registerTemporaryFile(resObj);
- }
- }
-
- // Prepare objects to add them to the list of input files.
- for (StringRef path : inputFiles) {
- path = ctx.allocate(path);
- if (isLibraryFile(path)) {
- addFiles(ctx, getLibraryPath(ctx, path), diag, libraries);
- } else {
- addFiles(ctx, getObjectPath(ctx, path), diag, files);
- }
- }
-
- // If dead-stripping is enabled, we need to add the entry symbol and
- // symbols given by /include to the dead strip root set, so that it
- // won't be removed from the output.
- if (ctx.deadStrip())
- for (const StringRef symbolName : ctx.initialUndefinedSymbols())
- ctx.addDeadStripRoot(symbolName);
-
- // Add the libraries specified by /defaultlib unless they are already added
- // nor blacklisted by /nodefaultlib.
- if (!ctx.getNoDefaultLibAll())
- for (const StringRef path : defaultLibs)
- if (!ctx.hasNoDefaultLib(path))
- addFiles(ctx, getLibraryPath(ctx, path.lower()), diag, libraries);
-
- if (files.empty() && !isReadingDirectiveSection) {
- diag << "No input files\n";
- return false;
- }
-
- // If /out option was not specified, the default output file name is
- // constructed by replacing an extension of the first input file
- // with ".exe".
- if (ctx.outputPath().empty()) {
- StringRef path = files[0]->path();
- ctx.setOutputPath(replaceExtension(ctx, path, ".exe"));
- }
-
- // Add the input files to the linking context.
- for (std::unique_ptr<File> &file : files) {
- if (isReadingDirectiveSection) {
- File *f = file.get();
- ctx.getTaskGroup().spawn([f] { f->parse(); });
- }
- ctx.getNodes().push_back(llvm::make_unique<FileNode>(std::move(file)));
- }
-
- // Add the library group to the linking context.
- if (!isReadingDirectiveSection) {
- // Add a group-end marker.
- ctx.getNodes().push_back(llvm::make_unique<GroupEnd>(0));
- }
-
- // Add the library files to the library group.
- for (std::unique_ptr<File> &file : libraries) {
- if (!hasLibrary(ctx, file.get())) {
- if (isReadingDirectiveSection) {
- File *f = file.get();
- ctx.getTaskGroup().spawn([f] { f->parse(); });
- }
- ctx.addLibraryFile(llvm::make_unique<FileNode>(std::move(file)));
- }
- }
-
- // Validate the combination of options used.
- return ctx.validate(diag);
-}
-
-} // namespace lld
diff --git a/lib/Driver/WinLinkModuleDef.cpp b/lib/Driver/WinLinkModuleDef.cpp
deleted file mode 100644
index e55a0bc5fe64..000000000000
--- a/lib/Driver/WinLinkModuleDef.cpp
+++ /dev/null
@@ -1,295 +0,0 @@
-//===- lib/Driver/WinLinkModuleDef.cpp ------------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Windows module definition file parser.
-///
-//===----------------------------------------------------------------------===//
-
-#include "lld/Driver/WinLinkModuleDef.h"
-#include "llvm/ADT/StringSwitch.h"
-
-namespace lld {
-namespace moduledef {
-
-Token Lexer::lex() {
- for (;;) {
- _buffer = _buffer.trim();
- if (_buffer.empty() || _buffer[0] == '\0')
- return Token(Kind::eof, _buffer);
-
- switch (_buffer[0]) {
- case ';': {
- size_t end = _buffer.find('\n');
- _buffer = (end == _buffer.npos) ? "" : _buffer.drop_front(end);
- continue;
- }
- case '=':
- _buffer = _buffer.drop_front();
- return Token(Kind::equal, "=");
- case ',':
- _buffer = _buffer.drop_front();
- return Token(Kind::comma, ",");
- case '"': {
- size_t end = _buffer.find('"', 1);
- Token ret;
- if (end == _buffer.npos) {
- ret = Token(Kind::identifier, _buffer.substr(1, end));
- _buffer = "";
- } else {
- ret = Token(Kind::identifier, _buffer.substr(1, end - 1));
- _buffer = _buffer.drop_front(end + 1);
- }
- return ret;
- }
- default: {
- size_t end = _buffer.find_first_not_of(
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "0123456789_.*~+!@#$%^&*()/");
- StringRef word = _buffer.substr(0, end);
- Kind kind = llvm::StringSwitch<Kind>(word)
- .Case("BASE", Kind::kw_base)
- .Case("DATA", Kind::kw_data)
- .Case("EXPORTS", Kind::kw_exports)
- .Case("HEAPSIZE", Kind::kw_heapsize)
- .Case("LIBRARY", Kind::kw_library)
- .Case("NAME", Kind::kw_name)
- .Case("NONAME", Kind::kw_noname)
- .Case("PRIVATE", Kind::kw_private)
- .Case("STACKSIZE", Kind::kw_stacksize)
- .Case("VERSION", Kind::kw_version)
- .Default(Kind::identifier);
- _buffer = (end == _buffer.npos) ? "" : _buffer.drop_front(end);
- return Token(kind, word);
- }
- }
- }
-}
-
-void Parser::consumeToken() {
- if (_tokBuf.empty()) {
- _tok = _lex.lex();
- return;
- }
- _tok = _tokBuf.back();
- _tokBuf.pop_back();
-}
-
-bool Parser::consumeTokenAsInt(uint64_t &result) {
- consumeToken();
- if (_tok._kind != Kind::identifier) {
- ungetToken();
- error(_tok, "Integer expected");
- return false;
- }
- if (_tok._range.getAsInteger(10, result)) {
- error(_tok, "Integer expected");
- return false;
- }
- return true;
-}
-
-bool Parser::expectAndConsume(Kind kind, Twine msg) {
- consumeToken();
- if (_tok._kind != kind) {
- error(_tok, msg);
- return false;
- }
- return true;
-}
-
-void Parser::ungetToken() { _tokBuf.push_back(_tok); }
-
-void Parser::error(const Token &tok, Twine msg) {
- _lex.getSourceMgr().PrintMessage(
- llvm::SMLoc::getFromPointer(tok._range.data()), llvm::SourceMgr::DK_Error,
- msg);
-}
-
-bool Parser::parse(std::vector<Directive *> &ret) {
- for (;;) {
- Directive *dir = nullptr;
- if (!parseOne(dir))
- return false;
- if (!dir)
- return true;
- ret.push_back(dir);
- }
-}
-
-bool Parser::parseOne(Directive *&ret) {
- consumeToken();
- switch (_tok._kind) {
- case Kind::eof:
- return true;
- case Kind::kw_exports: {
- // EXPORTS
- std::vector<PECOFFLinkingContext::ExportDesc> exports;
- for (;;) {
- PECOFFLinkingContext::ExportDesc desc;
- if (!parseExport(desc))
- break;
- exports.push_back(desc);
- }
- ret = new (_alloc) Exports(exports);
- return true;
- }
- case Kind::kw_heapsize: {
- // HEAPSIZE
- uint64_t reserve, commit;
- if (!parseMemorySize(reserve, commit))
- return false;
- ret = new (_alloc) Heapsize(reserve, commit);
- return true;
- }
- case Kind::kw_library: {
- // LIBRARY
- std::string name;
- uint64_t baseaddr;
- if (!parseName(name, baseaddr))
- return false;
- if (!StringRef(name).endswith_lower(".dll"))
- name.append(".dll");
- ret = new (_alloc) Library(name, baseaddr);
- return true;
- }
- case Kind::kw_stacksize: {
- // STACKSIZE
- uint64_t reserve, commit;
- if (!parseMemorySize(reserve, commit))
- return false;
- ret = new (_alloc) Stacksize(reserve, commit);
- return true;
- }
- case Kind::kw_name: {
- // NAME
- std::string outputPath;
- uint64_t baseaddr;
- if (!parseName(outputPath, baseaddr))
- return false;
- ret = new (_alloc) Name(outputPath, baseaddr);
- return true;
- }
- case Kind::kw_version: {
- // VERSION
- int major, minor;
- if (!parseVersion(major, minor))
- return false;
- ret = new (_alloc) Version(major, minor);
- return true;
- }
- default:
- error(_tok, Twine("Unknown directive: ") + _tok._range);
- return false;
- }
-}
-
-bool Parser::parseExport(PECOFFLinkingContext::ExportDesc &result) {
- consumeToken();
- if (_tok._kind != Kind::identifier) {
- ungetToken();
- return false;
- }
- result.name = _tok._range;
-
- consumeToken();
- if (_tok._kind == Kind::equal) {
- consumeToken();
- if (_tok._kind != Kind::identifier)
- return false;
- result.externalName = result.name;
- result.name = _tok._range;
- } else {
- ungetToken();
- }
-
- for (;;) {
- consumeToken();
- if (_tok._kind == Kind::identifier && _tok._range[0] == '@') {
- _tok._range.drop_front().getAsInteger(10, result.ordinal);
- consumeToken();
- if (_tok._kind == Kind::kw_noname) {
- result.noname = true;
- } else {
- ungetToken();
- }
- continue;
- }
- if (_tok._kind == Kind::kw_data) {
- result.isData = true;
- continue;
- }
- if (_tok._kind == Kind::kw_private) {
- result.isPrivate = true;
- continue;
- }
- ungetToken();
- return true;
- }
-}
-
-// HEAPSIZE/STACKSIZE reserve[,commit]
-bool Parser::parseMemorySize(uint64_t &reserve, uint64_t &commit) {
- if (!consumeTokenAsInt(reserve))
- return false;
-
- consumeToken();
- if (_tok._kind != Kind::comma) {
- ungetToken();
- commit = 0;
- return true;
- }
-
- if (!consumeTokenAsInt(commit))
- return false;
- return true;
-}
-
-// NAME [outputPath] [BASE=address]
-bool Parser::parseName(std::string &outputPath, uint64_t &baseaddr) {
- consumeToken();
- if (_tok._kind == Kind::identifier) {
- outputPath = _tok._range;
- } else {
- outputPath = "";
- ungetToken();
- return true;
- }
- consumeToken();
- if (_tok._kind == Kind::kw_base) {
- if (!expectAndConsume(Kind::equal, "'=' expected"))
- return false;
- if (!consumeTokenAsInt(baseaddr))
- return false;
- } else {
- ungetToken();
- baseaddr = 0;
- }
- return true;
-}
-
-// VERSION major[.minor]
-bool Parser::parseVersion(int &major, int &minor) {
- consumeToken();
- if (_tok._kind != Kind::identifier)
- return false;
- StringRef v1, v2;
- std::tie(v1, v2) = _tok._range.split('.');
- if (v1.getAsInteger(10, major))
- return false;
- if (v2.empty()) {
- minor = 0;
- } else if (v2.getAsInteger(10, minor)) {
- return false;
- }
- return true;
-}
-
-} // moddef
-} // namespace lld
diff --git a/lib/Driver/WinLinkOptions.td b/lib/Driver/WinLinkOptions.td
deleted file mode 100644
index a545639b5bb2..000000000000
--- a/lib/Driver/WinLinkOptions.td
+++ /dev/null
@@ -1,120 +0,0 @@
-include "llvm/Option/OptParser.td"
-
-// link.exe accepts options starting with either a dash or a slash.
-
-// Flag that takes no arguments.
-class F<string name> : Flag<["/", "-", "-?"], name>;
-
-// Flag that takes one argument after ":".
-class P<string name, string help> :
- Joined<["/", "-", "-?"], name#":">, HelpText<help>;
-
-// Boolean flag suffixed by ":no".
-multiclass B<string name, string help> {
- def "" : F<name>;
- def _no : F<name#":no">, HelpText<help>;
-}
-
-def alternatename : P<"alternatename", "Define weak alias">;
-def base : P<"base", "Base address of the program">;
-def defaultlib : P<"defaultlib", "Add the library to the list of input files">;
-def nodefaultlib : P<"nodefaultlib", "Remove a default library">;
-def disallowlib : Joined<["/", "-", "-?"], "disallowlib:">, Alias<nodefaultlib>;
-def entry : P<"entry", "Name of entry point symbol">;
-// No help text because /failifmismatch is not intended to be used by the user.
-def export : P<"export", "Export a function">;
-def failifmismatch : P<"failifmismatch", "">;
-def heap : P<"heap", "Size of the heap">;
-def align : P<"align", "Section alignment">;
-def libpath : P<"libpath", "Additional library search path">;
-def mllvm : P<"mllvm", "Options to pass to LLVM">;
-def out : P<"out", "Path to file to write output">;
-def stack : P<"stack", "Size of the stack">;
-def machine : P<"machine", "Specify target platform">;
-def version : P<"version", "Specify a version number in the PE header">;
-def merge : P<"merge", "Combine sections">;
-def section : P<"section", "Specify section attributes">;
-def subsystem : P<"subsystem", "Specify subsystem">;
-def stub : P<"stub", "Specify DOS stub file">;
-def opt : P<"opt", "Control optimizations">;
-def implib : P<"implib", "Import library name">;
-def delayload : P<"delayload", "Delay loaded DLL name">;
-def pdb : P<"pdb", "PDB file path">;
-
-def manifest : F<"manifest">;
-def manifest_colon : P<"manifest", "Create manifest file">;
-def manifestuac : P<"manifestuac", "User access control">;
-def manifestfile : P<"manifestfile", "Manifest file path">;
-def manifestdependency : P<"manifestdependency",
- "Attributes for <dependency> in 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
-// a reserved keyword in tablegen.
-def incl : Joined<["/", "-"], "include:">,
- HelpText<"Force symbol to be added to symbol table as undefined one">;
-
-// "def" is also a keyword.
-def deffile : Joined<["/", "-"], "def:">,
- HelpText<"Use module-definition file">;
-
-def nodefaultlib_all : F<"nodefaultlib">;
-def noentry : F<"noentry">;
-def dll : F<"dll">;
-def verbose : F<"verbose">;
-def debug : F<"debug">;
-def swaprun_cd : F<"swaprun:cd">;
-def swaprun_net : F<"swaprun:net">;
-def profile : F<"profile">;
-
-def force : F<"force">,
- HelpText<"Allow undefined symbols when creating executables">;
-def force_unresolved : F<"force:unresolved">;
-
-defm nxcompat : B<"nxcompat", "Disable data execution provention">;
-defm largeaddressaware : B<"largeaddressaware", "Disable large addresses">;
-defm allowbind: B<"allowbind", "Disable DLL binding">;
-defm fixed : B<"fixed", "Enable base relocations">;
-defm tsaware : B<"tsaware", "Create non-Terminal Server aware executable">;
-defm allowisolation : B<"allowisolation", "Set NO_ISOLATION bit">;
-defm dynamicbase : B<"dynamicbase",
- "Disable address space layout randomization">;
-defm safeseh : B<"safeseh", "Produce an image with Safe Exception Handler">;
-defm highentropyva : B<"highentropyva", "Set HIGH_ENTROPY_VA bit">;
-
-def help : F<"help">;
-def help_q : Flag<["/?", "-?"], "">, Alias<help>;
-
-def DASH_DASH : Option<["--"], "", KIND_REMAINING_ARGS>;
-
-// Flag for debug
-def lldmoduledeffile : Joined<["/", "-"], "lldmoduledeffile:">;
-
-//==============================================================================
-// The flags below do nothing. They are defined only for link.exe compatibility.
-//==============================================================================
-
-class QF<string name> : Joined<["/", "-", "-?"], name#":">;
-
-multiclass QB<string name> {
- def "" : F<name>;
- def _no : F<name#":no">;
-}
-
-def functionpadmin : F<"functionpadmin">;
-def ignoreidl : F<"ignoreidl">;
-def incremental : F<"incremental">;
-def no_incremental : F<"incremental:no">;
-def nologo : F<"nologo">;
-
-def delay : QF<"delay">;
-def errorreport : QF<"errorreport">;
-def idlout : QF<"idlout">;
-def ignore : QF<"ignore">;
-def maxilksize : QF<"maxilksize">;
-def pdbaltpath : QF<"pdbaltpath">;
-def tlbid : QF<"tlbid">;
-def tlbout : QF<"tlbout">;
-def verbose_all : QF<"verbose">;
-
-defm wx : QB<"wx">;
diff --git a/lib/Makefile b/lib/Makefile
deleted file mode 100644
index 83112eaf972a..000000000000
--- a/lib/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-##===- lib/Makefile ----------------------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-LLD_LEVEL := ..
-
-# ARCMigrate and Rewrite are always needed because of libclang.
-PARALLEL_DIRS = Config Core Driver ReaderWriter
-
-include $(LLD_LEVEL)/../../Makefile.config
-
-include $(LLD_LEVEL)/Makefile
diff --git a/lib/ReaderWriter/CMakeLists.txt b/lib/ReaderWriter/CMakeLists.txt
index 1fd19eb73a75..588f0d85a586 100644
--- a/lib/ReaderWriter/CMakeLists.txt
+++ b/lib/ReaderWriter/CMakeLists.txt
@@ -1,7 +1,5 @@
add_subdirectory(ELF)
add_subdirectory(MachO)
-add_subdirectory(Native)
-add_subdirectory(PECOFF)
add_subdirectory(YAML)
if (MSVC)
diff --git a/lib/ReaderWriter/CoreLinkingContext.cpp b/lib/ReaderWriter/CoreLinkingContext.cpp
index 86fad4f6e77d..02f6263c0c3f 100644
--- a/lib/ReaderWriter/CoreLinkingContext.cpp
+++ b/lib/ReaderWriter/CoreLinkingContext.cpp
@@ -14,139 +14,19 @@
#include "lld/Core/Simple.h"
#include "lld/ReaderWriter/CoreLinkingContext.h"
#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLExtras.h"
using namespace lld;
namespace {
-/// \brief Simple atom created by the stubs pass.
-class TestingStubAtom : public DefinedAtom {
-public:
- TestingStubAtom(const File &F, const Atom &) : _file(F) {
- static uint32_t lastOrdinal = 0;
- _ordinal = lastOrdinal++;
- }
-
- const File &file() const override { return _file; }
-
- StringRef name() const override { return StringRef(); }
-
- uint64_t ordinal() const override { return _ordinal; }
-
- uint64_t size() const override { return 0; }
-
- Scope scope() const override { return DefinedAtom::scopeLinkageUnit; }
-
- Interposable interposable() const override { return DefinedAtom::interposeNo; }
-
- Merge merge() const override { return DefinedAtom::mergeNo; }
-
- ContentType contentType() const override { return DefinedAtom::typeStub; }
-
- Alignment alignment() const override { return Alignment(0, 0); }
-
- SectionChoice sectionChoice() const override {
- return DefinedAtom::sectionBasedOnContent;
- }
-
- StringRef customSectionName() const override { return StringRef(); }
-
- DeadStripKind deadStrip() const override {
- return DefinedAtom::deadStripNormal;
- }
-
- ContentPermissions permissions() const override {
- return DefinedAtom::permR_X;
- }
-
- ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
-
- reference_iterator begin() const override {
- return reference_iterator(*this, nullptr);
- }
-
- reference_iterator end() const override {
- return reference_iterator(*this, nullptr);
- }
-
- const Reference *derefIterator(const void *iter) const override {
- return nullptr;
- }
-
- void incrementIterator(const void *&iter) const override {}
-
-private:
- const File &_file;
- uint32_t _ordinal;
-};
-
-/// \brief Simple atom created by the GOT pass.
-class TestingGOTAtom : public DefinedAtom {
-public:
- TestingGOTAtom(const File &F, const Atom &) : _file(F) {
- static uint32_t lastOrdinal = 0;
- _ordinal = lastOrdinal++;
- }
-
- const File &file() const override { return _file; }
-
- StringRef name() const override { return StringRef(); }
-
- uint64_t ordinal() const override { return _ordinal; }
-
- uint64_t size() const override { return 0; }
-
- Scope scope() const override { return DefinedAtom::scopeLinkageUnit; }
-
- Interposable interposable() const override { return DefinedAtom::interposeNo; }
-
- Merge merge() const override { return DefinedAtom::mergeNo; }
-
- ContentType contentType() const override { return DefinedAtom::typeGOT; }
-
- Alignment alignment() const override { return Alignment(3, 0); }
-
- SectionChoice sectionChoice() const override {
- return DefinedAtom::sectionBasedOnContent;
- }
-
- StringRef customSectionName() const override { return StringRef(); }
-
- DeadStripKind deadStrip() const override {
- return DefinedAtom::deadStripNormal;
- }
-
- ContentPermissions permissions() const override {
- return DefinedAtom::permRW_;
- }
-
- ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
-
- reference_iterator begin() const override {
- return reference_iterator(*this, nullptr);
- }
-
- reference_iterator end() const override {
- return reference_iterator(*this, nullptr);
- }
-
- const Reference *derefIterator(const void *iter) const override {
- return nullptr;
- }
-
- void incrementIterator(const void *&iter) const override {}
-
-private:
- const File &_file;
- uint32_t _ordinal;
-};
-
class OrderPass : public Pass {
public:
/// Sorts atoms by position
- void perform(std::unique_ptr<MutableFile> &file) override {
- MutableFile::DefinedAtomRange defined = file->definedAtoms();
+ std::error_code perform(SimpleFile &file) override {
+ SimpleFile::DefinedAtomRange defined = file.definedAtoms();
std::sort(defined.begin(), defined.end(), DefinedAtom::compareByPosition);
+ return std::error_code();
}
};
@@ -161,10 +41,9 @@ bool CoreLinkingContext::validateImpl(raw_ostream &) {
void CoreLinkingContext::addPasses(PassManager &pm) {
for (StringRef name : _passNames) {
- if (name.equals("order"))
- pm.add(std::unique_ptr<Pass>(new OrderPass()));
- else
- llvm_unreachable("bad pass name");
+ (void)name;
+ assert(name == "order" && "bad pass name");
+ pm.add(llvm::make_unique<OrderPass>());
}
}
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h b/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h
index 12ba52a38f38..73864d2b4c38 100644
--- a/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h
+++ b/lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h
@@ -16,51 +16,27 @@
namespace lld {
namespace elf {
-template <class ELFT>
-class AArch64DynamicLibraryWriter : public DynamicLibraryWriter<ELFT> {
+class AArch64DynamicLibraryWriter : public DynamicLibraryWriter<ELF64LE> {
public:
- AArch64DynamicLibraryWriter(AArch64LinkingContext &context,
- AArch64TargetLayout<ELFT> &layout);
+ AArch64DynamicLibraryWriter(AArch64LinkingContext &ctx,
+ TargetLayout<ELF64LE> &layout);
protected:
// Add any runtime files and their atoms to the output
- virtual bool createImplicitFiles(std::vector<std::unique_ptr<File>> &);
-
- virtual void finalizeDefaultAtomValues() {
- return DynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues();
- }
-
- virtual void addDefaultAtoms() {
- return DynamicLibraryWriter<ELFT>::addDefaultAtoms();
- }
-
-private:
- class GOTFile : public SimpleFile {
- public:
- GOTFile(const ELFLinkingContext &eti) : SimpleFile("GOTFile") {}
- llvm::BumpPtrAllocator _alloc;
- };
-
- std::unique_ptr<GOTFile> _gotFile;
- AArch64LinkingContext &_context;
- AArch64TargetLayout<ELFT> &_AArch64Layout;
+ void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
};
-template <class ELFT>
-AArch64DynamicLibraryWriter<ELFT>::AArch64DynamicLibraryWriter(
- AArch64LinkingContext &context, AArch64TargetLayout<ELFT> &layout)
- : DynamicLibraryWriter<ELFT>(context, layout),
- _gotFile(new GOTFile(context)), _context(context),
- _AArch64Layout(layout) {}
+AArch64DynamicLibraryWriter::AArch64DynamicLibraryWriter(
+ AArch64LinkingContext &ctx, TargetLayout<ELF64LE> &layout)
+ : DynamicLibraryWriter(ctx, layout) {}
-template <class ELFT>
-bool AArch64DynamicLibraryWriter<ELFT>::createImplicitFiles(
+void AArch64DynamicLibraryWriter::createImplicitFiles(
std::vector<std::unique_ptr<File>> &result) {
- DynamicLibraryWriter<ELFT>::createImplicitFiles(result);
- _gotFile->addAtom(*new (_gotFile->_alloc) GLOBAL_OFFSET_TABLEAtom(*_gotFile));
- _gotFile->addAtom(*new (_gotFile->_alloc) DYNAMICAtom(*_gotFile));
- result.push_back(std::move(_gotFile));
- return true;
+ 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
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64ELFFile.h b/lib/ReaderWriter/ELF/AArch64/AArch64ELFFile.h
deleted file mode 100644
index 9d5207c1c4b4..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/AArch64ELFFile.h
+++ /dev/null
@@ -1,41 +0,0 @@
-//===- lib/ReaderWriter/ELF/AArch64/AArch64ELFFile.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_ELF_FILE_H
-#define LLD_READER_WRITER_ELF_AARCH64_AARCH64_ELF_FILE_H
-
-#include "ELFReader.h"
-
-namespace lld {
-namespace elf {
-
-class AArch64LinkingContext;
-
-template <class ELFT> class AArch64ELFFile : public ELFFile<ELFT> {
-public:
- AArch64ELFFile(std::unique_ptr<MemoryBuffer> mb, AArch64LinkingContext &ctx)
- : ELFFile<ELFT>(std::move(mb), ctx) {}
-
- static ErrorOr<std::unique_ptr<AArch64ELFFile>>
- create(std::unique_ptr<MemoryBuffer> mb, AArch64LinkingContext &ctx) {
- return std::unique_ptr<AArch64ELFFile<ELFT>>(
- new AArch64ELFFile<ELFT>(std::move(mb), ctx));
- }
-};
-
-template <class ELFT> class AArch64DynamicFile : public DynamicFile<ELFT> {
-public:
- AArch64DynamicFile(const AArch64LinkingContext &context, StringRef name)
- : DynamicFile<ELFT>(context, name) {}
-};
-
-} // elf
-} // lld
-
-#endif // LLD_READER_WRITER_ELF_AARCH64_AARCH64_ELF_FILE_H
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64ELFReader.h b/lib/ReaderWriter/ELF/AArch64/AArch64ELFReader.h
deleted file mode 100644
index 05f312db3e7b..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/AArch64ELFReader.h
+++ /dev/null
@@ -1,62 +0,0 @@
-//===- lib/ReaderWriter/ELF/AArch64/AArch64ELFReader.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_AARCH64_AARCH64_ELF_READER_H
-#define LLD_READER_WRITER_AARCH64_AARCH64_ELF_READER_H
-
-#include "AArch64ELFFile.h"
-#include "ELFReader.h"
-
-namespace lld {
-namespace elf {
-
-typedef llvm::object::ELFType<llvm::support::little, 2, true> AArch64ELFType;
-
-struct AArch64DynamicFileCreateELFTraits {
- typedef llvm::ErrorOr<std::unique_ptr<lld::SharedLibraryFile>> result_type;
-
- template <class ELFT>
- static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb,
- AArch64LinkingContext &ctx) {
- return lld::elf::AArch64DynamicFile<ELFT>::create(std::move(mb), ctx);
- }
-};
-
-struct AArch64ELFFileCreateELFTraits {
- typedef llvm::ErrorOr<std::unique_ptr<lld::File>> result_type;
-
- template <class ELFT>
- static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb,
- AArch64LinkingContext &ctx) {
- return lld::elf::AArch64ELFFile<ELFT>::create(std::move(mb), ctx);
- }
-};
-
-class AArch64ELFObjectReader
- : public ELFObjectReader<AArch64ELFType, AArch64ELFFileCreateELFTraits,
- AArch64LinkingContext> {
-public:
- AArch64ELFObjectReader(AArch64LinkingContext &ctx)
- : ELFObjectReader<AArch64ELFType, AArch64ELFFileCreateELFTraits,
- AArch64LinkingContext>(ctx, llvm::ELF::EM_AARCH64) {}
-};
-
-class AArch64ELFDSOReader
- : public ELFDSOReader<AArch64ELFType, AArch64DynamicFileCreateELFTraits,
- AArch64LinkingContext> {
-public:
- AArch64ELFDSOReader(AArch64LinkingContext &ctx)
- : ELFDSOReader<AArch64ELFType, AArch64DynamicFileCreateELFTraits,
- AArch64LinkingContext>(ctx, llvm::ELF::EM_AARCH64) {}
-};
-
-} // namespace elf
-} // namespace lld
-
-#endif // LLD_READER_WRITER_AARCH64_AARCH64_ELF_READER_H
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.cpp b/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.cpp
new file mode 100644
index 000000000000..9a9ec6cba12b
--- /dev/null
+++ b/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.cpp
@@ -0,0 +1,52 @@
+//===- 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
index 73963f56ef70..eef825040ffa 100644
--- a/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h
+++ b/lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h
@@ -9,59 +9,29 @@
#ifndef AARCH64_EXECUTABLE_WRITER_H
#define AARCH64_EXECUTABLE_WRITER_H
-#include "AArch64LinkingContext.h"
#include "ExecutableWriter.h"
namespace lld {
namespace elf {
-template <class ELFT>
-class AArch64ExecutableWriter : public ExecutableWriter<ELFT> {
+class AArch64TargetLayout;
+class AArch64LinkingContext;
+
+class AArch64ExecutableWriter : public ExecutableWriter<ELF64LE> {
public:
- AArch64ExecutableWriter(AArch64LinkingContext &context,
- AArch64TargetLayout<ELFT> &layout);
+ AArch64ExecutableWriter(AArch64LinkingContext &ctx,
+ AArch64TargetLayout &layout);
protected:
// Add any runtime files and their atoms to the output
- bool createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-
- void finalizeDefaultAtomValues() override {
- return ExecutableWriter<ELFT>::finalizeDefaultAtomValues();
- }
+ void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
- void addDefaultAtoms() override{
- return ExecutableWriter<ELFT>::addDefaultAtoms();
- }
+ void buildDynamicSymbolTable(const File &file) override;
private:
- class GOTFile : public SimpleFile {
- public:
- GOTFile(const ELFLinkingContext &eti) : SimpleFile("GOTFile") {}
- llvm::BumpPtrAllocator _alloc;
- };
-
- std::unique_ptr<GOTFile> _gotFile;
- AArch64LinkingContext &_context;
- AArch64TargetLayout<ELFT> &_AArch64Layout;
+ AArch64TargetLayout &_targetLayout;
};
-template <class ELFT>
-AArch64ExecutableWriter<ELFT>::AArch64ExecutableWriter(
- AArch64LinkingContext &context, AArch64TargetLayout<ELFT> &layout)
- : ExecutableWriter<ELFT>(context, layout), _gotFile(new GOTFile(context)),
- _context(context), _AArch64Layout(layout) {}
-
-template <class ELFT>
-bool AArch64ExecutableWriter<ELFT>::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &result) {
- ExecutableWriter<ELFT>::createImplicitFiles(result);
- _gotFile->addAtom(*new (_gotFile->_alloc) GLOBAL_OFFSET_TABLEAtom(*_gotFile));
- if (_context.isDynamic())
- _gotFile->addAtom(*new (_gotFile->_alloc) DYNAMICAtom(*_gotFile));
- result.push_back(std::move(_gotFile));
- return true;
-}
-
} // namespace elf
} // namespace lld
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp b/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp
index 9eb98f447709..ba883f7f59db 100644
--- a/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp
+++ b/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp
@@ -12,22 +12,34 @@
#include "AArch64TargetHandler.h"
using namespace lld;
+using namespace lld::elf;
std::unique_ptr<ELFLinkingContext>
-elf::AArch64LinkingContext::create(llvm::Triple triple) {
+elf::createAArch64LinkingContext(llvm::Triple triple) {
if (triple.getArch() == llvm::Triple::aarch64)
- return std::unique_ptr<ELFLinkingContext>(
- new elf::AArch64LinkingContext(triple));
+ return llvm::make_unique<AArch64LinkingContext>(triple);
return nullptr;
}
-elf::AArch64LinkingContext::AArch64LinkingContext(llvm::Triple triple)
- : ELFLinkingContext(triple, std::unique_ptr<TargetHandlerBase>(
- new AArch64TargetHandler(*this))) {}
+AArch64LinkingContext::AArch64LinkingContext(llvm::Triple triple)
+ : ELFLinkingContext(triple, std::unique_ptr<TargetHandler>(
+ new AArch64TargetHandler(*this))) {}
-void elf::AArch64LinkingContext::addPasses(PassManager &pm) {
+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
index ebd91fe0a95b..25a173158318 100644
--- a/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h
+++ b/lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h
@@ -24,10 +24,11 @@ enum {
class AArch64LinkingContext final : public ELFLinkingContext {
public:
- static std::unique_ptr<ELFLinkingContext> create(llvm::Triple);
+ 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)
@@ -88,6 +89,11 @@ public:
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
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp b/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp
index d1ecc7fa884b..ac7c769ec26d 100644
--- a/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp
+++ b/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp
@@ -13,11 +13,14 @@
#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;
-#define PAGE(X) ((X) & ~0x0FFFL)
+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) {
@@ -28,77 +31,130 @@ static bool withinSignedUnsignedRange(int64_t X, int bits) {
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_WITH_TYPE(
- "AArch64", 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");
+ 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 void relocR_AARCH64_PREL32(uint8_t *location, uint64_t P, uint64_t S,
- int64_t A) {
- int32_t result = (int32_t)((S + A) - P);
- write32le(location, result + (int32_t)read32le(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_WITH_TYPE(
- "AArch64", 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");
+ 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_ADR_PREL_PG_HI21 - Page(S+A) - Page(P)
-static void relocR_AARCH64_ADR_PREL_PG_HI21(uint8_t *location, uint64_t P,
+/// \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) {
- uint64_t result = (PAGE(S + A) - PAGE(P));
+ 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_WITH_TYPE(
- "AArch64", 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");
+ 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));
- // TODO: Make sure this is correct!
+ return std::error_code();
}
/// \brief R_AARCH64_ADR_PREL_LO21 - S + A - P
-static void relocR_AARCH64_ADR_PREL_LO21(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- uint64_t result = (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_WITH_TYPE(
- "AArch64", 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");
+ 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));
- // TODO: Make sure this is correct!
+ return std::error_code();
}
/// \brief R_AARCH64_ADD_ABS_LO12_NC
@@ -106,41 +162,46 @@ 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_WITH_TYPE(
- "AArch64", 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");
+ 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 void relocJump26(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
- int32_t result = (int32_t)((S + A) - P);
+/// \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_WITH_TYPE(
- "AArch64", 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");
+ 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 void relocR_AARCH64_CONDBR19(uint8_t *location, uint64_t P, uint64_t S,
- int64_t A) {
- int32_t result = (int32_t)((S + A) - P);
+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_WITH_TYPE(
- "AArch64", 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");
+ 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
@@ -148,12 +209,11 @@ 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_WITH_TYPE(
- "AArch64", 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");
+ 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));
}
@@ -163,12 +223,11 @@ static void relocR_AARCH64_LDST16_ABS_LO12_NC(uint8_t *location, uint64_t P,
int32_t result = (int32_t)(S + A);
result &= 0x0FFC;
result <<= 9;
- DEBUG_WITH_TYPE(
- "AArch64", 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");
+ 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));
}
@@ -178,12 +237,11 @@ static void relocR_AARCH64_LDST32_ABS_LO12_NC(uint8_t *location, uint64_t P,
int32_t result = (int32_t)(S + A);
result &= 0x0FFC;
result <<= 8;
- DEBUG_WITH_TYPE(
- "AArch64", 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");
+ 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));
}
@@ -193,12 +251,11 @@ static void relocR_AARCH64_LDST64_ABS_LO12_NC(uint8_t *location, uint64_t P,
int32_t result = (int32_t)(S + A);
result &= 0x0FF8;
result <<= 7;
- DEBUG_WITH_TYPE(
- "AArch64", 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");
+ 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));
}
@@ -208,83 +265,89 @@ static void relocR_AARCH64_LDST128_ABS_LO12_NC(uint8_t *location, uint64_t P,
int32_t result = (int32_t)(S + A);
result &= 0x0FF8;
result <<= 6;
- DEBUG_WITH_TYPE(
- "AArch64", 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");
+ 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 void 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);
- result >>= 12;
+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_WITH_TYPE(
- "AArch64", 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, result | read32le(location));
+ 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 void relocR_AARCH64_LD64_GOT_LO12_NC(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
+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_WITH_TYPE(
- "AArch64", 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");
+ 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_WITH_TYPE(
- "AArch64", 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");
+ 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 void 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);
+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_WITH_TYPE(
- "AArch64", 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");
+ 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
@@ -294,28 +357,31 @@ static void relocR_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC(uint8_t *location,
int32_t result = S + A;
result &= 0xFF8;
result <<= 7;
- DEBUG_WITH_TYPE(
- "AArch64", 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");
+ 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 void relocR_AARCH64_TLSLE_ADD_TPREL_HI12(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A) {
- int32_t result = S + A;
+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_WITH_TYPE(
- "AArch64", 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");
+ 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
@@ -325,22 +391,76 @@ static void relocR_AARCH64_TLSLE_ADD_TPREL_LO12_NC(uint8_t *location,
int32_t result = S + A;
result &= 0x0FFF;
result <<= 10;
- DEBUG_WITH_TYPE(
- "AArch64", 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");
+ 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 lld::AtomLayout &atom,
+ ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
const Reference &ref) const {
uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
- uint8_t *location = atomContent + ref.offsetInAtom();
- uint64_t targetVAddress = writer.addressOfAtom(ref.target());
- uint64_t relocVAddress = atom._virtualAddr + ref.offsetInAtom();
+ 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();
@@ -349,92 +469,88 @@ std::error_code AArch64TargetRelocationHandler::applyRelocation(
case R_AARCH64_NONE:
break;
case R_AARCH64_ABS64:
- relocR_AARCH64_ABS64(location, relocVAddress, targetVAddress, ref.addend());
- break;
- case R_AARCH64_PREL32:
- relocR_AARCH64_PREL32(location, relocVAddress, targetVAddress,
- ref.addend());
+ relocR_AARCH64_ABS64(loc, reloc, target, addend);
break;
case R_AARCH64_ABS32:
- return relocR_AARCH64_ABS32(location, relocVAddress, targetVAddress,
- ref.addend());
- // Runtime only relocations. Ignore here.
- case R_AARCH64_RELATIVE:
- case R_AARCH64_IRELATIVE:
- case R_AARCH64_JUMP_SLOT:
- case R_AARCH64_GLOB_DAT:
+ 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:
- relocR_AARCH64_ADR_PREL_PG_HI21(location, relocVAddress, targetVAddress,
- ref.addend());
- break;
+ return relocR_AARCH64_ADR_PREL_PG_HI21(loc, reloc, target, addend);
case R_AARCH64_ADR_PREL_LO21:
- relocR_AARCH64_ADR_PREL_LO21(location, relocVAddress, targetVAddress,
- ref.addend());
- break;
+ return relocR_AARCH64_ADR_PREL_LO21(loc, reloc, target, addend);
case R_AARCH64_ADD_ABS_LO12_NC:
- relocR_AARCH64_ADD_ABS_LO12_NC(location, relocVAddress, targetVAddress,
- ref.addend());
+ relocR_AARCH64_ADD_ABS_LO12_NC(loc, reloc, target, addend);
break;
case R_AARCH64_CALL26:
case R_AARCH64_JUMP26:
- relocJump26(location, relocVAddress, targetVAddress, ref.addend());
- break;
+ return relocJump26(loc, reloc, target, addend);
case R_AARCH64_CONDBR19:
- relocR_AARCH64_CONDBR19(location, relocVAddress, targetVAddress,
- ref.addend());
- break;
+ return relocR_AARCH64_CONDBR19(loc, reloc, target, addend);
case R_AARCH64_ADR_GOT_PAGE:
- relocR_AARCH64_ADR_GOT_PAGE(location, relocVAddress, targetVAddress,
- ref.addend());
- break;
+ return relocR_AARCH64_ADR_GOT_PAGE(loc, reloc, target, addend);
case R_AARCH64_LD64_GOT_LO12_NC:
- relocR_AARCH64_LD64_GOT_LO12_NC(location, relocVAddress, targetVAddress,
- ref.addend());
- break;
+ return relocR_AARCH64_LD64_GOT_LO12_NC(loc, reloc, target, addend);
case R_AARCH64_LDST8_ABS_LO12_NC:
- relocR_AARCH64_LDST8_ABS_LO12_NC(location, relocVAddress, targetVAddress,
- ref.addend());
+ relocR_AARCH64_LDST8_ABS_LO12_NC(loc, reloc, target, addend);
break;
case R_AARCH64_LDST16_ABS_LO12_NC:
- relocR_AARCH64_LDST16_ABS_LO12_NC(location, relocVAddress, targetVAddress,
- ref.addend());
+ relocR_AARCH64_LDST16_ABS_LO12_NC(loc, reloc, target, addend);
break;
case R_AARCH64_LDST32_ABS_LO12_NC:
- relocR_AARCH64_LDST32_ABS_LO12_NC(location, relocVAddress, targetVAddress,
- ref.addend());
+ relocR_AARCH64_LDST32_ABS_LO12_NC(loc, reloc, target, addend);
break;
case R_AARCH64_LDST64_ABS_LO12_NC:
- relocR_AARCH64_LDST64_ABS_LO12_NC(location, relocVAddress, targetVAddress,
- ref.addend());
+ relocR_AARCH64_LDST64_ABS_LO12_NC(loc, reloc, target, addend);
break;
case R_AARCH64_LDST128_ABS_LO12_NC:
- relocR_AARCH64_LDST128_ABS_LO12_NC(location, relocVAddress, targetVAddress,
- ref.addend());
+ relocR_AARCH64_LDST128_ABS_LO12_NC(loc, reloc, target, addend);
break;
case ADD_AARCH64_GOTRELINDEX:
- relocADD_AARCH64_GOTRELINDEX(location, relocVAddress, targetVAddress,
- ref.addend());
+ relocADD_AARCH64_GOTRELINDEX(loc, reloc, target, addend);
break;
case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
- relocR_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21(location, relocVAddress,
- targetVAddress, ref.addend());
- break;
+ 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(location, relocVAddress,
- targetVAddress, ref.addend());
+ relocR_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC(loc, reloc, target, addend);
break;
case R_AARCH64_TLSLE_ADD_TPREL_HI12:
- relocR_AARCH64_TLSLE_ADD_TPREL_HI12(location, relocVAddress, targetVAddress,
- ref.addend());
+ 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;
- case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
- relocR_AARCH64_TLSLE_ADD_TPREL_LO12_NC(location, relocVAddress,
- targetVAddress, ref.addend());
+ // 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
index b1d3c09dc936..8cde7a03e51a 100644
--- a/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h
+++ b/lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h
@@ -10,21 +10,24 @@
#ifndef AARCH64_RELOCATION_HANDLER_H
#define AARCH64_RELOCATION_HANDLER_H
-#include "AArch64TargetHandler.h"
+#include "lld/ReaderWriter/ELFLinkingContext.h"
namespace lld {
namespace elf {
-typedef llvm::object::ELFType<llvm::support::little, 2, true> AArch64ELFType;
-template <class ELFT> class AArch64TargetLayout;
+class AArch64TargetLayout;
class AArch64TargetRelocationHandler final : public TargetRelocationHandler {
public:
+ AArch64TargetRelocationHandler(AArch64TargetLayout &layout)
+ : _layout(layout) {}
+
std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
- const lld::AtomLayout &,
+ const AtomLayout &,
const Reference &) const override;
- static const Registry::KindStrings kindStrings[];
+private:
+ AArch64TargetLayout &_layout;
};
} // end namespace elf
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp b/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp
index 0bd12958b27b..4d94a793665c 100644
--- a/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp
+++ b/lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp
@@ -28,52 +28,79 @@ using namespace lld;
using namespace lld::elf;
using namespace llvm::ELF;
-namespace {
// .got values
-const uint8_t AArch64GotAtomContent[8] = {0};
+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)
-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
+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)
-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
+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, StringRef secName) : GOTAtom(f, secName) {}
+ 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) {}
@@ -84,13 +111,22 @@ public:
class AArch64PLTAtom : public PLTAtom {
public:
- AArch64PLTAtom(const File &f, StringRef secName) : PLTAtom(f, secName) {}
+ 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") {
@@ -149,9 +185,16 @@ template <class Derived> class AArch64RelocationPass : public Pass {
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)->handleGOT(ref);
+ 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;
}
}
@@ -164,9 +207,9 @@ protected:
auto plt = _pltMap.find(da);
if (plt != _pltMap.end())
return plt->second;
- auto ga = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
+ auto ga = new (_file._alloc) AArch64GOTPLTAtom(_file);
ga->addReferenceELF_AArch64(R_AARCH64_IRELATIVE, 0, da, 0);
- auto pa = new (_file._alloc) AArch64PLTAtom(_file, ".plt");
+ auto pa = new (_file._alloc) AArch64PLTAtom(_file);
pa->addReferenceELF_AArch64(R_AARCH64_PREL32, 2, ga, -4);
#ifndef NDEBUG
ga->_name = "__got_ifunc_";
@@ -193,11 +236,11 @@ protected:
}
/// \brief Create a GOT entry for the TP offset of a TLS atom.
- const GOTAtom *getGOTTPOFF(const Atom *atom) {
+ const GOTAtom *getGOTTPREL(const Atom *atom) {
auto got = _gotMap.find(atom);
if (got == _gotMap.end()) {
- auto g = new (_file._alloc) AArch64GOTAtom(_file, ".got");
- g->addReferenceELF_AArch64(R_AARCH64_GOTREL64, 0, atom, 0);
+ 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();
@@ -209,17 +252,53 @@ protected:
return got->second;
}
- /// \brief Create a TPOFF64 GOT entry and change the relocation to a PC32 to
- /// the GOT.
- void handleGOTTPOFF(const Reference &ref) {
- const_cast<Reference &>(ref).setTarget(getGOTTPOFF(ref.target()));
- const_cast<Reference &>(ref).setKindValue(R_AARCH64_PREL32);
+ /// \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) AArch64GOTAtom(_file, ".got.plt");
+ _null = new (_file._alloc) AArch64GOTPLTAtom(_file);
#ifndef NDEBUG
_null->_name = "__got_null";
#endif
@@ -230,7 +309,7 @@ protected:
const GOTAtom *getGOT(const DefinedAtom *da) {
auto got = _gotMap.find(da);
if (got == _gotMap.end()) {
- auto g = new (_file._alloc) AArch64GOTAtom(_file, ".got");
+ auto g = new (_file._alloc) AArch64GOTAtom(_file);
g->addReferenceELF_AArch64(R_AARCH64_ABS64, 0, da, 0);
#ifndef NDEBUG
g->_name = "__got_";
@@ -244,9 +323,7 @@ protected:
}
public:
- AArch64RelocationPass(const ELFLinkingContext &ctx)
- : _file(ctx), _ctx(ctx), _null(nullptr), _PLT0(nullptr), _got0(nullptr),
- _got1(nullptr) {}
+ AArch64RelocationPass(const ELFLinkingContext &ctx) : _file(ctx), _ctx(ctx) {}
/// \brief Do the pass.
///
@@ -256,32 +333,32 @@ public:
///
/// After all references are handled, the atoms created during that are all
/// added to mf.
- void perform(std::unique_ptr<MutableFile> &mf) override {
+ 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()) {
+ : mf.undefined()) {
llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
} llvm::dbgs()
<< "Shared Library Atoms"
<< "\n";
for (const auto &atom
- : mf->sharedLibrary()) {
+ : mf.sharedLibrary()) {
llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
} llvm::dbgs()
<< "Absolute Atoms"
<< "\n";
for (const auto &atom
- : mf->absolute()) {
+ : 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 &atom : mf.defined()) {
for (const auto &ref : *atom) {
handleReference(*atom, *ref);
}
@@ -289,32 +366,39 @@ public:
// Add all created atoms to the link.
uint64_t ordinal = 0;
- if (_PLT0) {
- _PLT0->setOrdinal(ordinal++);
- mf->addAtom(*_PLT0);
+ if (_plt0) {
+ _plt0->setOrdinal(ordinal++);
+ mf.addAtom(*_plt0);
}
for (auto &plt : _pltVector) {
plt->setOrdinal(ordinal++);
- mf->addAtom(*plt);
+ mf.addAtom(*plt);
}
if (_null) {
_null->setOrdinal(ordinal++);
- mf->addAtom(*_null);
+ mf.addAtom(*_null);
}
- if (_PLT0) {
+ if (_plt0) {
_got0->setOrdinal(ordinal++);
_got1->setOrdinal(ordinal++);
- mf->addAtom(*_got0);
- mf->addAtom(*_got1);
+ mf.addAtom(*_got0);
+ mf.addAtom(*_got1);
}
for (auto &got : _gotVector) {
got->setOrdinal(ordinal++);
- mf->addAtom(*got);
+ 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);
+ mf.addAtom(*obj);
}
+
+ return std::error_code();
}
protected:
@@ -333,18 +417,19 @@ protected:
/// \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;
+ 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;
- GOTAtom *_got0;
- GOTAtom *_got1;
+ PLT0Atom *_plt0 = nullptr;
+ GOTAtom *_got0 = nullptr;
+ GOTAtom *_got1 = nullptr;
/// @}
};
@@ -394,31 +479,31 @@ public:
: AArch64RelocationPass(ctx) {}
const PLT0Atom *getPLT0() {
- if (_PLT0)
- return _PLT0;
+ if (_plt0)
+ return _plt0;
// Fill in the null entry.
getNullGOT();
- _PLT0 = new (_file._alloc) AArch64PLT0Atom(_file);
- _got0 = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
- _got1 = new (_file._alloc) AArch64GOTAtom(_file, ".got.plt");
- _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);
+ _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";
+ _plt0->_name = "__PLT0";
_got0->_name = "__got0";
_got1->_name = "__got1";
#endif
- return _PLT0;
+ 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) AArch64GOTAtom(_file, ".got.plt");
+ auto ga = new (_file._alloc) AArch64GOTPLTAtom(_file);
ga->addReferenceELF_AArch64(R_AARCH64_JUMP_SLOT, 0, a, 0);
- auto pa = new (_file._alloc) AArch64PLTAtom(_file, ".plt");
+ 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);
@@ -485,7 +570,7 @@ public:
const GOTAtom *getSharedGOT(const SharedLibraryAtom *sla) {
auto got = _gotMap.find(sla);
if (got == _gotMap.end()) {
- auto g = new (_file._alloc) AArch64GOTAtom(_file, ".got");
+ auto g = new (_file._alloc) AArch64GOTAtom(_file);
g->addReferenceELF_AArch64(R_AARCH64_GLOB_DAT, 0, sla, 0);
#ifndef NDEBUG
g->_name = "__got_";
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.cpp b/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.cpp
new file mode 100644
index 000000000000..2734bcdbda5f
--- /dev/null
+++ b/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.cpp
@@ -0,0 +1,39 @@
+//===- 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
new file mode 100644
index 000000000000..2b7594c2db84
--- /dev/null
+++ b/lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.h
@@ -0,0 +1,37 @@
+//===- 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
index 607f767f8b8a..083b492c1607 100644
--- a/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp
+++ b/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp
@@ -12,41 +12,40 @@
#include "AArch64ExecutableWriter.h"
#include "AArch64LinkingContext.h"
#include "AArch64TargetHandler.h"
+#include "AArch64SectionChunks.h"
using namespace lld;
using namespace elf;
-AArch64TargetHandler::AArch64TargetHandler(AArch64LinkingContext &context)
- : _context(context),
- _AArch64TargetLayout(new AArch64TargetLayout<AArch64ELFType>(context)),
- _AArch64RelocationHandler(new AArch64TargetRelocationHandler()) {}
-
-void AArch64TargetHandler::registerRelocationNames(Registry &registry) {
- registry.addKindTable(Reference::KindNamespace::ELF,
- Reference::KindArch::AArch64, kindStrings);
+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->_context.getOutputELFType()) {
+ switch (this->_ctx.getOutputELFType()) {
case llvm::ELF::ET_EXEC:
- return std::unique_ptr<Writer>(new AArch64ExecutableWriter<AArch64ELFType>(
- _context, *_AArch64TargetLayout.get()));
+ return llvm::make_unique<AArch64ExecutableWriter>(_ctx, *_targetLayout);
case llvm::ELF::ET_DYN:
- return std::unique_ptr<Writer>(
- new AArch64DynamicLibraryWriter<AArch64ELFType>(
- _context, *_AArch64TargetLayout.get()));
+ return llvm::make_unique<AArch64DynamicLibraryWriter>(_ctx, *_targetLayout);
case llvm::ELF::ET_REL:
llvm_unreachable("TODO: support -r mode");
default:
llvm_unreachable("unsupported output type");
}
}
-
-#define ELF_RELOC(name, value) LLD_KIND_STRING_ENTRY(name),
-
-const Registry::KindStrings AArch64TargetHandler::kindStrings[] = {
-#include "llvm/Support/ELFRelocs/AArch64.def"
- LLD_KIND_STRING_END
-};
-
-#undef ELF_RELOC
diff --git a/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h b/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h
index 4eb6786cdf1f..c0ecbfa9e44b 100644
--- a/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h
+++ b/lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h
@@ -10,52 +10,78 @@
#ifndef LLD_READER_WRITER_ELF_AARCH64_AARCH64_TARGET_HANDLER_H
#define LLD_READER_WRITER_ELF_AARCH64_AARCH64_TARGET_HANDLER_H
-#include "AArch64ELFFile.h"
-#include "AArch64ELFReader.h"
#include "AArch64RelocationHandler.h"
-#include "DefaultTargetHandler.h"
+#include "ELFReader.h"
#include "TargetLayout.h"
#include "lld/Core/Simple.h"
namespace lld {
namespace elf {
+
class AArch64LinkingContext;
+class AArch64GOTSection;
-template <class ELFT> class AArch64TargetLayout : public TargetLayout<ELFT> {
-public:
- AArch64TargetLayout(AArch64LinkingContext &context)
- : TargetLayout<ELFT>(context) {}
-};
+class AArch64TargetLayout final : public TargetLayout<ELF64LE> {
+ typedef llvm::object::Elf_Shdr_Impl<ELF64LE> Elf_Shdr;
-class AArch64TargetHandler final : public DefaultTargetHandler<AArch64ELFType> {
public:
- AArch64TargetHandler(AArch64LinkingContext &context);
+ 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;
+ }
- AArch64TargetLayout<AArch64ELFType> &getTargetLayout() override {
- return *(_AArch64TargetLayout.get());
+ 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;
}
- void registerRelocationNames(Registry &registry) override;
+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 AArch64TargetRelocationHandler &getRelocationHandler() const override {
- return *(_AArch64RelocationHandler.get());
+ const TargetRelocationHandler &getRelocationHandler() const override {
+ return *_relocationHandler;
}
std::unique_ptr<Reader> getObjReader() override {
- return std::unique_ptr<Reader>(new AArch64ELFObjectReader(_context));
+ return llvm::make_unique<ELFReader<ELFFile<ELF64LE>>>(_ctx);
}
std::unique_ptr<Reader> getDSOReader() override {
- return std::unique_ptr<Reader>(new AArch64ELFDSOReader(_context));
+ return llvm::make_unique<ELFReader<DynamicFile<ELF64LE>>>(_ctx);
}
std::unique_ptr<Writer> getWriter() override;
private:
- static const Registry::KindStrings kindStrings[];
- AArch64LinkingContext &_context;
- std::unique_ptr<AArch64TargetLayout<AArch64ELFType>> _AArch64TargetLayout;
- std::unique_ptr<AArch64TargetRelocationHandler> _AArch64RelocationHandler;
+ AArch64LinkingContext &_ctx;
+ std::unique_ptr<AArch64TargetLayout> _targetLayout;
+ std::unique_ptr<AArch64TargetRelocationHandler> _relocationHandler;
};
} // end namespace elf
diff --git a/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt b/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt
index de94a4df5078..2347dda9adb0 100644
--- a/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt
+++ b/lib/ReaderWriter/ELF/AArch64/CMakeLists.txt
@@ -3,6 +3,8 @@ add_llvm_library(lldAArch64ELFTarget
AArch64TargetHandler.cpp
AArch64RelocationHandler.cpp
AArch64RelocationPass.cpp
+ AArch64ExecutableWriter.cpp
+ AArch64SectionChunks.cpp
LINK_LIBS
lldELF
lldReaderWriter
diff --git a/lib/ReaderWriter/ELF/AArch64/Makefile b/lib/ReaderWriter/ELF/AArch64/Makefile
deleted file mode 100644
index 02cff4747d0d..000000000000
--- a/lib/ReaderWriter/ELF/AArch64/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-##===- lld/lib/ReaderWriter/ELF/AArch64/Makefile ----------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL := ../../../..
-LIBRARYNAME := lldAArch64ELFTarget
-USEDLIBS = lldCore.a
-CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF/AArch64 -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF
-
-include $(LLD_LEVEL)/Makefile
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.cpp b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.cpp
new file mode 100644
index 000000000000..89efeb23d6f8
--- /dev/null
+++ b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.cpp
@@ -0,0 +1,34 @@
+//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.cpp -------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AMDGPUExecutableWriter.h"
+
+using namespace lld;
+using namespace lld::elf;
+
+AMDGPUExecutableWriter::AMDGPUExecutableWriter(AMDGPULinkingContext &ctx,
+ AMDGPUTargetLayout &layout)
+ : ExecutableWriter(ctx, layout), _ctx(ctx) {}
+
+void AMDGPUExecutableWriter::createImplicitFiles(
+ std::vector<std::unique_ptr<File>> &Result) {
+ // ExecutableWriter::createImplicitFiles() adds C runtime symbols that we
+ // don't need, so we use the OutputELFWriter implementation instead.
+ OutputELFWriter<ELF64LE>::createImplicitFiles(Result);
+}
+
+void AMDGPUExecutableWriter::finalizeDefaultAtomValues() {
+
+ // ExecutableWriter::finalizeDefaultAtomValues() assumes the presence of
+ // C runtime symbols. However, since we skip the call to
+ // ExecutableWriter::createImplicitFiles(), these symbols are never added
+ // and ExectuableWriter::finalizeDefaultAtomValues() will crash if we call
+ // it.
+ OutputELFWriter<ELF64LE>::finalizeDefaultAtomValues();
+}
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.h b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.h
new file mode 100644
index 000000000000..accc00b8a054
--- /dev/null
+++ b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.h
@@ -0,0 +1,41 @@
+//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPUExecutableWriter.h ---------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+#ifndef AMDGPU_EXECUTABLE_WRITER_H
+#define AMDGPU_EXECUTABLE_WRITER_H
+
+#include "ExecutableWriter.h"
+#include "AMDGPULinkingContext.h"
+#include "AMDGPUSymbolTable.h"
+#include "AMDGPUTargetHandler.h"
+
+namespace lld {
+namespace elf {
+
+class AMDGPUTargetLayout;
+
+class AMDGPUExecutableWriter : public ExecutableWriter<ELF64LE> {
+public:
+ AMDGPUExecutableWriter(AMDGPULinkingContext &ctx, AMDGPUTargetLayout &layout);
+
+ unique_bump_ptr<SymbolTable<ELF64LE>> createSymbolTable() override {
+ return unique_bump_ptr<SymbolTable<ELF64LE>>(new (this->_alloc)
+ AMDGPUSymbolTable(_ctx));
+ }
+
+ void createImplicitFiles(std::vector<std::unique_ptr<File>> &Result) override;
+ void finalizeDefaultAtomValues() override;
+
+private:
+ AMDGPULinkingContext &_ctx;
+};
+
+} // namespace elf
+} // namespace lld
+
+#endif // AMDGPU_EXECUTABLE_WRITER_H
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.cpp b/lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.cpp
new file mode 100644
index 000000000000..b1e83641fa82
--- /dev/null
+++ b/lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.cpp
@@ -0,0 +1,41 @@
+//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.cpp ---------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===------------------------------------------------------------------------===//
+
+#include "AMDGPULinkingContext.h"
+#include "AMDGPUTargetHandler.h"
+
+namespace lld {
+namespace elf {
+
+std::unique_ptr<ELFLinkingContext>
+createAMDGPULinkingContext(llvm::Triple triple) {
+ if (triple.getArch() == llvm::Triple::amdgcn)
+ return llvm::make_unique<AMDGPULinkingContext>(triple);
+ return nullptr;
+}
+
+AMDGPULinkingContext::AMDGPULinkingContext(llvm::Triple triple)
+ : ELFLinkingContext(triple, llvm::make_unique<AMDGPUTargetHandler>(*this)) {
+}
+
+static const Registry::KindStrings kindStrings[] = {LLD_KIND_STRING_END};
+
+void AMDGPULinkingContext::registerRelocationNames(Registry &registry) {
+ registry.addKindTable(Reference::KindNamespace::ELF,
+ Reference::KindArch::AMDGPU, kindStrings);
+}
+
+void setAMDGPUELFHeader(ELFHeader<ELF64LE> &elfHeader) {
+ elfHeader.e_ident(llvm::ELF::EI_OSABI, ELFOSABI_AMDGPU_HSA);
+}
+
+StringRef AMDGPULinkingContext::entrySymbolName() const { return ""; }
+
+} // namespace elf
+} // namespace lld
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.h b/lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.h
new file mode 100644
index 000000000000..1cc7a3c7694f
--- /dev/null
+++ b/lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.h
@@ -0,0 +1,36 @@
+//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPULinkingContext.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_AMDGPU_AMDGPU_LINKING_CONTEXT_H
+#define LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_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 AMDGPULinkingContext final : public ELFLinkingContext {
+public:
+ AMDGPULinkingContext(llvm::Triple triple);
+ int getMachineType() const override { return llvm::ELF::EM_AMDGPU; }
+
+ void registerRelocationNames(Registry &r) override;
+
+ StringRef entrySymbolName() const override;
+};
+
+void setAMDGPUELFHeader(ELFHeader<ELF64LE> &elfHeader);
+
+} // elf
+} // lld
+
+#endif // LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_LINKING_CONTEXT_H
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.cpp b/lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.cpp
new file mode 100644
index 000000000000..ca5a77db9177
--- /dev/null
+++ b/lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.cpp
@@ -0,0 +1,19 @@
+//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.cpp -----------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AMDGPURelocationHandler.h"
+
+using namespace lld;
+using namespace lld::elf;
+
+std::error_code AMDGPUTargetRelocationHandler::applyRelocation(
+ ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
+ const Reference &ref) const {
+ return std::error_code();
+}
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.h b/lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.h
new file mode 100644
index 000000000000..90d37274aebf
--- /dev/null
+++ b/lib/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.h
@@ -0,0 +1,31 @@
+//===- lld/ReaderWriter/ELF/AMDGPU/AMDGPURelocationHandler.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_AMDGPU_AMDGPU_RELOCATION_HANDLER_H
+#define LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_RELOCATION_HANDLER_H
+
+#include "lld/ReaderWriter/ELFLinkingContext.h"
+#include <system_error>
+
+namespace lld {
+namespace elf {
+class AMDGPUTargetHandler;
+class AMDGPUTargetLayout;
+
+class AMDGPUTargetRelocationHandler final : public TargetRelocationHandler {
+public:
+ AMDGPUTargetRelocationHandler(AMDGPUTargetLayout &layout) { }
+
+ std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
+ const AtomLayout &,
+ const Reference &) const override;
+
+};
+} // elf
+} // lld
+#endif
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.cpp b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.cpp
new file mode 100644
index 000000000000..0824974d4602
--- /dev/null
+++ b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.cpp
@@ -0,0 +1,32 @@
+//===--------- lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.cpp ----------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "AMDGPUSymbolTable.h"
+#include "ELFFile.h"
+#include "Atoms.h"
+#include "SectionChunks.h"
+
+using namespace lld;
+using namespace lld::elf;
+
+AMDGPUSymbolTable::AMDGPUSymbolTable(const ELFLinkingContext &ctx)
+ : SymbolTable(ctx, ".symtab", TargetLayout<ELF64LE>::ORDER_SYMBOL_TABLE) {}
+
+void AMDGPUSymbolTable::addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
+ int64_t addr) {
+ SymbolTable::addDefinedAtom(sym, da, addr);
+
+ // FIXME: Only do this for kernel functions.
+ sym.setType(STT_AMDGPU_HSA_KERNEL);
+
+ // Make st_value section relative.
+ // FIXME: This is hack to give kernel symbols a section relative offset.
+ // Because of this hack only on kernel can be included in a binary file.
+ sym.st_value = 0;
+}
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.h b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.h
new file mode 100644
index 000000000000..41c3be5cb38f
--- /dev/null
+++ b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.h
@@ -0,0 +1,32 @@
+//===--------- lib/ReaderWriter/ELF/AMDGPU/AMDGPUSymbolTable.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_AMDGPU_AMDGPU_SYMBOL_TABLE_H
+#define LLD_READER_WRITER_ELF_AMDGPU_AMDGPU_SYMBOL_TABLE_H
+
+#include "TargetLayout.h"
+
+namespace lld {
+namespace elf {
+
+/// \brief The SymbolTable class represents the symbol table in a ELF file
+class AMDGPUSymbolTable : public SymbolTable<ELF64LE> {
+public:
+ typedef llvm::object::Elf_Sym_Impl<ELF64LE> Elf_Sym;
+
+ AMDGPUSymbolTable(const ELFLinkingContext &ctx);
+
+ void addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
+ int64_t addr) override;
+};
+
+} // elf
+} // lld
+
+#endif
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.cpp b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.cpp
new file mode 100644
index 000000000000..ff4b600158bd
--- /dev/null
+++ b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.cpp
@@ -0,0 +1,65 @@
+//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.cpp -------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "TargetLayout.h"
+#include "AMDGPUExecutableWriter.h"
+#include "AMDGPULinkingContext.h"
+#include "AMDGPUTargetHandler.h"
+#include "llvm/Support/ELF.h"
+
+namespace lld {
+namespace elf {
+
+AMDGPUTargetHandler::AMDGPUTargetHandler(AMDGPULinkingContext &ctx)
+ : _ctx(ctx), _targetLayout(new AMDGPUTargetLayout(ctx)),
+ _relocationHandler(new AMDGPUTargetRelocationHandler(*_targetLayout)) {}
+
+std::unique_ptr<Writer> AMDGPUTargetHandler::getWriter() {
+ switch (_ctx.getOutputELFType()) {
+ case llvm::ELF::ET_EXEC:
+ return llvm::make_unique<AMDGPUExecutableWriter>(_ctx, *_targetLayout);
+ case llvm::ELF::ET_DYN:
+ llvm_unreachable("TODO: support dynamic libraries");
+ case llvm::ELF::ET_REL:
+ llvm_unreachable("TODO: support -r mode");
+ default:
+ llvm_unreachable("unsupported output type");
+ }
+}
+
+HSATextSection::HSATextSection(const ELFLinkingContext &ctx)
+ : AtomSection(ctx, ".hsatext", DefinedAtom::typeCode, 0, 0) {
+ _type = SHT_PROGBITS;
+ _flags = SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR | SHF_AMDGPU_HSA_AGENT |
+ SHF_AMDGPU_HSA_CODE;
+
+ // FIXME: What alignment should we use here?
+ _alignment = 4096;
+}
+
+void AMDGPUTargetLayout::assignSectionsToSegments() {
+
+ TargetLayout::assignSectionsToSegments();
+ for (OutputSection<ELF64LE> *osi : _outputSections) {
+ for (Section<ELF64LE> *section : osi->sections()) {
+ StringRef InputSectionName = section->inputSectionName();
+ if (InputSectionName != ".hsatext")
+ continue;
+
+ auto *segment = new (_allocator) Segment<ELF64LE>(
+ _ctx, "PT_AMDGPU_HSA_LOAD_CODE_AGENT", PT_AMDGPU_HSA_LOAD_CODE_AGENT);
+ _segments.push_back(segment);
+ assert(segment);
+ segment->append(section);
+ }
+ }
+}
+
+} // namespace elf
+} // namespace lld
diff --git a/lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.h b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.h
new file mode 100644
index 000000000000..8d0f70b6e7f7
--- /dev/null
+++ b/lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.h
@@ -0,0 +1,80 @@
+//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.h ------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef AMDGPU_TARGET_HANDLER_H
+#define AMDGPU_TARGET_HANDLER_H
+
+#include "ELFFile.h"
+#include "ELFReader.h"
+#include "AMDGPURelocationHandler.h"
+#include "TargetLayout.h"
+
+namespace lld {
+namespace elf {
+class AMDGPULinkingContext;
+
+class HSATextSection : public AtomSection<ELF64LE> {
+public:
+ HSATextSection(const ELFLinkingContext &ctx);
+};
+
+/// \brief TargetLayout for AMDGPU
+class AMDGPUTargetLayout final : public TargetLayout<ELF64LE> {
+public:
+ AMDGPUTargetLayout(AMDGPULinkingContext &ctx) : TargetLayout(ctx) {}
+
+ void assignSectionsToSegments() override;
+
+ /// \brief Gets or creates a section.
+ AtomSection<ELF64LE> *
+ createSection(StringRef name, int32_t contentType,
+ DefinedAtom::ContentPermissions contentPermissions,
+ TargetLayout::SectionOrder sectionOrder) override {
+ if (name == ".hsatext")
+ return new (_allocator) HSATextSection(_ctx);
+
+ if (name == ".note")
+ contentType = DefinedAtom::typeRONote;
+
+ return TargetLayout::createSection(name, contentType, contentPermissions,
+ sectionOrder);
+ }
+};
+
+/// \brief TargetHandler for AMDGPU
+class AMDGPUTargetHandler final : public TargetHandler {
+public:
+ AMDGPUTargetHandler(AMDGPULinkingContext &targetInfo);
+
+ 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:
+ AMDGPULinkingContext &_ctx;
+ std::unique_ptr<AMDGPUTargetLayout> _targetLayout;
+ std::unique_ptr<AMDGPUTargetRelocationHandler> _relocationHandler;
+};
+
+void finalizeAMDGPURuntimeAtomValues(AMDGPUTargetLayout &layout);
+
+} // end namespace elf
+} // end namespace lld
+
+#endif
diff --git a/lib/ReaderWriter/ELF/AMDGPU/CMakeLists.txt b/lib/ReaderWriter/ELF/AMDGPU/CMakeLists.txt
new file mode 100644
index 000000000000..9c9cc10fe397
--- /dev/null
+++ b/lib/ReaderWriter/ELF/AMDGPU/CMakeLists.txt
@@ -0,0 +1,13 @@
+add_llvm_library(lldAMDGPUELFTarget
+ AMDGPUExecutableWriter.cpp
+ AMDGPULinkingContext.cpp
+ AMDGPURelocationHandler.cpp
+ AMDGPUSymbolTable.cpp
+ AMDGPUTargetHandler.cpp
+ LINK_LIBS
+ lldELF
+ lldReaderWriter
+ lldCore
+ LLVMObject
+ LLVMSupport
+ )
diff --git a/lib/ReaderWriter/ELF/ARM/ARMDynamicLibraryWriter.h b/lib/ReaderWriter/ELF/ARM/ARMDynamicLibraryWriter.h
new file mode 100644
index 000000000000..da843b97abc0
--- /dev/null
+++ b/lib/ReaderWriter/ELF/ARM/ARMDynamicLibraryWriter.h
@@ -0,0 +1,49 @@
+//===- 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
index bc5ee35b8213..8f5477017e55 100644
--- a/lib/ReaderWriter/ELF/ARM/ARMELFFile.h
+++ b/lib/ReaderWriter/ELF/ARM/ARMELFFile.h
@@ -17,53 +17,95 @@ namespace elf {
class ARMLinkingContext;
-template <class ELFT> class ARMELFDefinedAtom : public ELFDefinedAtom<ELFT> {
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
- typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
+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:
- ARMELFDefinedAtom(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)
- : ELFDefinedAtom<ELFT>(file, symbolName, sectionName, symbol, section,
- contentData, referenceStart, referenceEnd,
- referenceList) {}
-
- bool isThumbFunc(const Elf_Sym *symbol) const {
+ 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);
+ (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 Elf_Sym *symbol) const override {
- const auto value = static_cast<uint64_t>(symbol->st_value);
- return isThumbFunc(symbol) ? value & ~0x1 : value;
+ 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 {
- if (isThumbFunc(this->_symbol))
- return DefinedAtom::codeARMThumb;
- return DefinedAtom::codeNA;
+ return isThumbFunc() ? DefinedAtom::codeARMThumb : DefinedAtom::codeNA;
}
};
-template <class ELFT> class ARMELFFile : public ELFFile<ELFT> {
-public:
- ARMELFFile(std::unique_ptr<MemoryBuffer> mb, ARMLinkingContext &ctx)
- : ELFFile<ELFT>(std::move(mb), ctx) {}
+class ARMELFFile : public ELFFile<ELF32LE> {
+ typedef llvm::object::Elf_Rel_Impl<ELF32LE, false> Elf_Rel;
- static ErrorOr<std::unique_ptr<ARMELFFile>>
- create(std::unique_ptr<MemoryBuffer> mb, ARMLinkingContext &ctx) {
- return std::unique_ptr<ARMELFFile<ELFT>>(
- new ARMELFFile<ELFT>(std::move(mb), ctx));
+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<ELFT> Elf_Sym;
- typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
+ 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.
@@ -73,24 +115,39 @@ private:
}
/// Process the Defined symbol and create an atom for it.
- ErrorOr<ELFDefinedAtom<ELFT> *> handleDefinedSymbol(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 {
- return new (this->_readerStorage) ARMELFDefinedAtom<ELFT>(
+ 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);
}
};
-template <class ELFT> class ARMDynamicFile : public DynamicFile<ELFT> {
-public:
- ARMDynamicFile(const ARMLinkingContext &context, StringRef name)
- : DynamicFile<ELFT>(context, name) {}
-};
-
} // elf
} // lld
diff --git a/lib/ReaderWriter/ELF/ARM/ARMELFReader.h b/lib/ReaderWriter/ELF/ARM/ARMELFReader.h
deleted file mode 100644
index 31af531563ea..000000000000
--- a/lib/ReaderWriter/ELF/ARM/ARMELFReader.h
+++ /dev/null
@@ -1,62 +0,0 @@
-//===--------- lib/ReaderWriter/ELF/ARM/ARMELFReader.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_ARM_ARM_ELF_READER_H
-#define LLD_READER_WRITER_ARM_ARM_ELF_READER_H
-
-#include "ARMELFFile.h"
-#include "ELFReader.h"
-
-namespace lld {
-namespace elf {
-
-typedef llvm::object::ELFType<llvm::support::little, 2, false> ARMELFType;
-
-struct ARMDynamicFileCreateELFTraits {
- typedef llvm::ErrorOr<std::unique_ptr<lld::SharedLibraryFile>> result_type;
-
- template <class ELFT>
- static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb,
- ARMLinkingContext &ctx) {
- return lld::elf::ARMDynamicFile<ELFT>::create(std::move(mb), ctx);
- }
-};
-
-struct ARMELFFileCreateELFTraits {
- typedef llvm::ErrorOr<std::unique_ptr<lld::File>> result_type;
-
- template <class ELFT>
- static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb,
- ARMLinkingContext &ctx) {
- return lld::elf::ARMELFFile<ELFT>::create(std::move(mb), ctx);
- }
-};
-
-class ARMELFObjectReader
- : public ELFObjectReader<ARMELFType, ARMELFFileCreateELFTraits,
- ARMLinkingContext> {
-public:
- ARMELFObjectReader(ARMLinkingContext &ctx)
- : ELFObjectReader<ARMELFType, ARMELFFileCreateELFTraits,
- ARMLinkingContext>(ctx, llvm::ELF::EM_ARM) {}
-};
-
-class ARMELFDSOReader
- : public ELFDSOReader<ARMELFType, ARMDynamicFileCreateELFTraits,
- ARMLinkingContext> {
-public:
- ARMELFDSOReader(ARMLinkingContext &ctx)
- : ELFDSOReader<ARMELFType, ARMDynamicFileCreateELFTraits,
- ARMLinkingContext>(ctx, llvm::ELF::EM_ARM) {}
-};
-
-} // namespace elf
-} // namespace lld
-
-#endif // LLD_READER_WRITER_ARM_ARM_ELF_READER_H
diff --git a/lib/ReaderWriter/ELF/ARM/ARMELFWriters.h b/lib/ReaderWriter/ELF/ARM/ARMELFWriters.h
new file mode 100644
index 000000000000..a842ebe53038
--- /dev/null
+++ b/lib/ReaderWriter/ELF/ARM/ARMELFWriters.h
@@ -0,0 +1,120 @@
+//===- 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
index 19311d516e4d..974dab63a126 100644
--- a/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h
+++ b/lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h
@@ -10,111 +10,58 @@
#define LLD_READER_WRITER_ELF_ARM_ARM_EXECUTABLE_WRITER_H
#include "ExecutableWriter.h"
+#include "ARMELFWriters.h"
#include "ARMLinkingContext.h"
#include "ARMTargetHandler.h"
-#include "ARMSymbolTable.h"
-
-namespace {
-const char *gotSymbol = "_GLOBAL_OFFSET_TABLE_";
-}
namespace lld {
namespace elf {
-template <class ELFT>
-class ARMExecutableWriter : public ExecutableWriter<ELFT> {
+class ARMExecutableWriter : public ARMELFWriter<ExecutableWriter<ELF32LE>> {
public:
- ARMExecutableWriter(ARMLinkingContext &context,
- ARMTargetLayout<ELFT> &layout);
+ ARMExecutableWriter(ARMLinkingContext &ctx, ARMTargetLayout &layout);
protected:
// Add any runtime files and their atoms to the output
- bool createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-
- void finalizeDefaultAtomValues() override;
-
- void addDefaultAtoms() override {
- ExecutableWriter<ELFT>::addDefaultAtoms();
- }
-
- /// \brief Create symbol table.
- unique_bump_ptr<SymbolTable<ELFT>> createSymbolTable() override;
+ void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
void processUndefinedSymbol(StringRef symName,
- RuntimeFile<ELFT> &file) const override;
-
- // Setup the ELF header.
- std::error_code setELFHeader() override;
+ RuntimeFile<ELF32LE> &file) const override;
private:
- ARMLinkingContext &_context;
- ARMTargetLayout<ELFT> &_armLayout;
+ ARMLinkingContext &_ctx;
};
-template <class ELFT>
-ARMExecutableWriter<ELFT>::ARMExecutableWriter(ARMLinkingContext &context,
- ARMTargetLayout<ELFT> &layout)
- : ExecutableWriter<ELFT>(context, layout), _context(context),
- _armLayout(layout) {}
+ARMExecutableWriter::ARMExecutableWriter(ARMLinkingContext &ctx,
+ ARMTargetLayout &layout)
+ : ARMELFWriter(ctx, layout), _ctx(ctx) {}
-template <class ELFT>
-bool ARMExecutableWriter<ELFT>::createImplicitFiles(
+void ARMExecutableWriter::createImplicitFiles(
std::vector<std::unique_ptr<File>> &result) {
- ExecutableWriter<ELFT>::createImplicitFiles(result);
- return true;
-}
-
-template <class ELFT>
-void ARMExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
- // Finalize the atom values that are part of the parent.
- ExecutableWriter<ELFT>::finalizeDefaultAtomValues();
- auto gotAtomIter = _armLayout.findAbsoluteAtom(gotSymbol);
- if (gotAtomIter != _armLayout.absoluteAtoms().end()) {
- auto *gotAtom = *gotAtomIter;
- 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;
+ 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));
}
- // TODO: resolve addresses of __exidx_start/_end atoms
-}
-
-template <class ELFT>
-unique_bump_ptr<SymbolTable<ELFT>>
- ARMExecutableWriter<ELFT>::createSymbolTable() {
- return unique_bump_ptr<SymbolTable<ELFT>>(
- new (this->_alloc) ARMSymbolTable<ELFT>(this->_context));
}
-template <class ELFT>
-void ARMExecutableWriter<ELFT>::processUndefinedSymbol(
- StringRef symName, RuntimeFile<ELFT> &file) const {
+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");
}
}
-template <class ELFT>
-std::error_code ARMExecutableWriter<ELFT>::setELFHeader() {
- if (std::error_code ec = ExecutableWriter<ELFT>::setELFHeader())
- return ec;
-
- // Fixup entry point for Thumb code.
- StringRef entryName = _context.entrySymbolName();
- if (const AtomLayout *al = _armLayout.findAtomLayoutByName(entryName)) {
- const auto *ea = dyn_cast<DefinedAtom>(al->_atom);
- if (ea && ea->codeModel() == DefinedAtom::codeARMThumb)
- this->_elfHeader->e_entry(al->_virtualAddr | 0x1);
- }
-
- return std::error_code();
-}
-
} // namespace elf
} // namespace lld
diff --git a/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp b/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp
index 5f2436674268..74905b47820f 100644
--- a/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp
+++ b/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp
@@ -11,24 +11,54 @@
#include "ARMRelocationPass.h"
#include "ARMTargetHandler.h"
-using namespace lld;
-using namespace lld::elf;
+namespace lld {
+namespace elf {
std::unique_ptr<ELFLinkingContext>
-elf::ARMLinkingContext::create(llvm::Triple triple) {
+createARMLinkingContext(llvm::Triple triple) {
if (triple.getArch() == llvm::Triple::arm)
- return std::unique_ptr<ELFLinkingContext>(
- new elf::ARMLinkingContext(triple));
+ return llvm::make_unique<ARMLinkingContext>(triple);
return nullptr;
}
-elf::ARMLinkingContext::ARMLinkingContext(llvm::Triple triple)
- : ELFLinkingContext(triple, std::unique_ptr<TargetHandlerBase>(
- new ARMTargetHandler(*this))) {}
+ARMLinkingContext::ARMLinkingContext(llvm::Triple triple)
+ : ELFLinkingContext(triple, llvm::make_unique<ARMTargetHandler>(*this)) {}
-void elf::ARMLinkingContext::addPasses(PassManager &pm) {
+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
index 249b79c4f07d..f687713b25b8 100644
--- a/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h
+++ b/lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h
@@ -19,17 +19,61 @@ namespace elf {
class ARMLinkingContext final : public ELFLinkingContext {
public:
- static std::unique_ptr<ELFLinkingContext> create(llvm::Triple);
+ 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
diff --git a/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp b/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
index d24fdf0fa410..97b149133ff2 100644
--- a/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
+++ b/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp
@@ -14,6 +14,8 @@
#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;
@@ -74,7 +76,7 @@ static Reference::Addend readAddend_THM_JUMP11(const uint8_t *location) {
const auto value = read16le(location);
const uint16_t imm11 = value & 0x7FF;
- return llvm::SignExtend32<12>(imm11 << 1);
+ return llvm::SignExtend64<12>(imm11 << 1);
}
static Reference::Addend readAddend(const uint8_t *location,
@@ -82,11 +84,15 @@ static Reference::Addend readAddend(const uint8_t *location,
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 (int32_t)(read32le(location) & 0x7FFFFFFF);
+ return llvm::SignExtend64<31>(read32le(location) & 0x7FFFFFFF);
case R_ARM_THM_CALL:
case R_ARM_THM_JUMP24:
return readAddend_THM_CALL(location);
@@ -106,81 +112,98 @@ static Reference::Addend readAddend(const uint8_t *location,
}
}
-static inline void applyArmReloc(uint8_t *location, uint32_t result,
- uint32_t mask = 0xFFFFFFFF) {
+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 void applyThmReloc(uint8_t *location, uint16_t resHi,
- uint16_t resLo, uint16_t maskHi,
- uint16_t maskLo = 0xFFFF) {
+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 void applyThumb16Reloc(uint8_t *location, uint16_t result,
- uint16_t mask = 0xFFFF) {
+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 void relocR_ARM_ABS32(uint8_t *location, uint64_t P, uint64_t S,
- int64_t A, bool addressesThumb) {
+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_WITH_TYPE(
- "ARM", 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");
- applyArmReloc(location, result);
+ 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 void relocR_ARM_REL32(uint8_t *location, uint64_t P, uint64_t S,
- int64_t A, bool addressesThumb) {
+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_WITH_TYPE(
- "ARM", 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");
- applyArmReloc(location, result);
+ 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 void relocR_ARM_PREL31(uint8_t *location, uint64_t P, uint64_t S,
- int64_t A, bool addressesThumb) {
+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_WITH_TYPE(
- "ARM", 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");
+ 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");
- applyArmReloc(location, rel31, mask);
+ return applyArmReloc(location, rel31, mask);
}
/// \brief Relocate B/BL instructions. useJs defines whether J1 & J2 are used
-static void relocR_ARM_THM_B_L(uint8_t *location, uint32_t result, bool useJs) {
+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;
@@ -194,12 +217,13 @@ static void relocR_ARM_THM_B_L(uint8_t *location, uint32_t result, bool useJs) {
const uint16_t bitI1 = (~(bitJ1 ^ bitS)) & 0x1;
const uint16_t resLo = (bitI1 << 13) | (bitI2 << 11) | imm11;
- applyThmReloc(location, resHi, resLo, 0x7FF, 0x2FFF);
+ return applyThumb32Reloc(location, resHi, resLo, 0x7FF, 0x2FFF);
}
/// \brief R_ARM_THM_CALL - ((S + A) | T) - P
-static void relocR_ARM_THM_CALL(uint8_t *location, uint64_t P, uint64_t S,
- int64_t A, bool useJs, bool addressesThumb) {
+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;
@@ -209,137 +233,171 @@ static void relocR_ARM_THM_CALL(uint8_t *location, uint64_t P, uint64_t S,
uint32_t result = (uint32_t)(((S + A) | T) - P);
- DEBUG_WITH_TYPE(
- "ARM", 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");
- relocR_ARM_THM_B_L(location, result, useJs);
+ 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) {
- applyThmReloc(location, 0, 0, 0, 0x1001);
+ return applyThumb32Reloc(location, 0, 0, 0, 0x1001);
}
+ return std::error_code();
}
/// \brief R_ARM_THM_JUMP24 - ((S + A) | T) - P
-static void relocR_ARM_THM_JUMP24(uint8_t *location, uint64_t P, uint64_t S,
- int64_t A, bool addressesThumb) {
+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_WITH_TYPE(
- "ARM", 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");
- relocR_ARM_THM_B_L(location, result, true);
+ 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 void relocR_ARM_THM_JUMP11(uint8_t *location, uint64_t P, uint64_t S,
- int64_t A) {
+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_WITH_TYPE(
- "ARM", 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");
+ 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");
- //we cut off first bit because it is always 1 according to p. 4.5.3
+ 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);
+}
- applyThumb16Reloc(location, result, 0x7FF);
+/// \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 void relocR_ARM_CALL(uint8_t *location, uint64_t P, uint64_t S,
- int64_t A, bool addressesThumb) {
+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_WITH_TYPE(
- "ARM", 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");
- applyArmReloc(location, imm24, 0xFFFFFF);
+ 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;
- applyArmReloc(location, (0xFA | bitH) << 24, 0xFF000000);
+ return applyArmReloc(location, (0xFA | bitH) << 24, 0xFF000000);
}
+ return std::error_code();
}
/// \brief R_ARM_JUMP24 - ((S + A) | T) - P
-static void relocR_ARM_JUMP24(uint8_t *location, uint64_t P, uint64_t S,
- int64_t A, bool addressesThumb) {
+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_WITH_TYPE(
- "ARM", 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");
- applyArmReloc(location, imm24, 0xFFFFFF);
+ 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 void relocR_ARM_MOV(uint8_t *location, uint32_t result) {
+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;
- applyArmReloc(location, (imm4 << 16) | imm12, 0xF0FFF);
+ return applyArmReloc(location, (imm4 << 16) | imm12, 0xF0FFF);
}
/// \brief R_ARM_MOVW_ABS_NC - (S + A) | T
-static void relocR_ARM_MOVW_ABS_NC(uint8_t *location, uint64_t P, uint64_t S,
- int64_t A, bool addressesThumb) {
+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_WITH_TYPE(
- "ARM", 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");
+ 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 void relocR_ARM_MOVT_ABS(uint8_t *location, uint64_t P, uint64_t S,
- int64_t 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_WITH_TYPE(
- "ARM", 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");
+ 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 void relocR_ARM_THM_MOV(uint8_t *location, uint32_t result) {
+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;
@@ -348,153 +406,275 @@ static void relocR_ARM_THM_MOV(uint8_t *location, uint32_t result) {
const uint16_t bitI = (result >> 11) & 0x1;
const uint16_t resHi = (bitI << 10) | imm4;
- applyThmReloc(location, resHi, resLo, 0x40F, 0x70FF);
+ return applyThumb32Reloc(location, resHi, resLo, 0x40F, 0x70FF);
}
/// \brief R_ARM_THM_MOVW_ABS_NC - (S + A) | T
-static void relocR_ARM_THM_MOVW_ABS_NC(uint8_t *location, uint64_t P,
- uint64_t S, int64_t A,
- bool addressesThumb) {
+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_WITH_TYPE(
- "ARM", 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");
+ 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 void relocR_ARM_THM_MOVT_ABS(uint8_t *location, uint64_t P, uint64_t S,
- int64_t 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_WITH_TYPE(
- "ARM", 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");
+ 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 void relocR_ARM_TLS_IE32(uint8_t *location, uint64_t P, uint64_t S,
- int64_t A) {
+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_WITH_TYPE(
- "ARM", 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");
- applyArmReloc(location, result);
+ 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 void relocR_ARM_TLS_LE32(uint8_t *location, uint64_t P, uint64_t S,
- int64_t A, uint64_t 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_WITH_TYPE(
- "ARM", 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");
- applyArmReloc(location, result);
+ 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 lld::AtomLayout &atom,
+ ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
const Reference &ref) const {
uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
- uint8_t *location = atomContent + ref.offsetInAtom();
- uint64_t targetVAddress = writer.addressOfAtom(ref.target());
- uint64_t relocVAddress = atom._virtualAddr + ref.offsetInAtom();
+ 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(location, ref.kindValue());
+ readAddend(loc, ref.kindValue()) + ref.addend();
// Flags that the relocation addresses Thumb instruction
- bool addressesThumb = false;
-
+ bool thumb = false;
if (const auto *definedAtom = dyn_cast<DefinedAtom>(ref.target())) {
- addressesThumb = (DefinedAtom::codeARMThumb == definedAtom->codeModel());
+ thumb = isThumbCode(definedAtom);
}
switch (ref.kindValue()) {
case R_ARM_NONE:
- break;
+ return std::error_code();
case R_ARM_ABS32:
- relocR_ARM_ABS32(location, relocVAddress, targetVAddress, addend,
- addressesThumb);
- break;
+ return relocR_ARM_ABS32(loc, reloc, target, addend, thumb);
case R_ARM_REL32:
- relocR_ARM_REL32(location, relocVAddress, targetVAddress, addend,
- addressesThumb);
- break;
+ 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
- relocR_ARM_THM_CALL(location, relocVAddress, targetVAddress, addend, true,
- addressesThumb);
- break;
+ return relocR_ARM_THM_CALL(loc, reloc, target, addend, true, thumb);
case R_ARM_CALL:
- relocR_ARM_CALL(location, relocVAddress, targetVAddress, addend,
- addressesThumb);
- break;
+ return relocR_ARM_CALL(loc, reloc, target, addend, thumb);
case R_ARM_JUMP24:
- relocR_ARM_JUMP24(location, relocVAddress, targetVAddress, addend,
- addressesThumb);
- break;
+ return relocR_ARM_JUMP24(loc, reloc, target, addend, thumb);
case R_ARM_THM_JUMP24:
- relocR_ARM_THM_JUMP24(location, relocVAddress, targetVAddress, addend,
- addressesThumb);
- break;
+ return relocR_ARM_THM_JUMP24(loc, reloc, target, addend, thumb);
case R_ARM_THM_JUMP11:
- relocR_ARM_THM_JUMP11(location, relocVAddress, targetVAddress, addend);
- break;
+ return relocR_ARM_THM_JUMP11(loc, reloc, target, addend);
case R_ARM_MOVW_ABS_NC:
- relocR_ARM_MOVW_ABS_NC(location, relocVAddress, targetVAddress, addend,
- addressesThumb);
- break;
+ return relocR_ARM_MOVW_ABS_NC(loc, reloc, target, addend, thumb);
case R_ARM_MOVT_ABS:
- relocR_ARM_MOVT_ABS(location, relocVAddress, targetVAddress, addend);
- break;
+ return relocR_ARM_MOVT_ABS(loc, reloc, target, addend);
case R_ARM_THM_MOVW_ABS_NC:
- relocR_ARM_THM_MOVW_ABS_NC(location, relocVAddress, targetVAddress, addend,
- addressesThumb);
- break;
+ return relocR_ARM_THM_MOVW_ABS_NC(loc, reloc, target, addend, thumb);
case R_ARM_THM_MOVT_ABS:
- relocR_ARM_THM_MOVT_ABS(location, relocVAddress, targetVAddress, addend);
- break;
+ return relocR_ARM_THM_MOVT_ABS(loc, reloc, target, addend);
case R_ARM_PREL31:
- relocR_ARM_PREL31(location, relocVAddress, targetVAddress, addend,
- addressesThumb);
- break;
+ return relocR_ARM_PREL31(loc, reloc, target, addend, thumb);
case R_ARM_TLS_IE32:
- relocR_ARM_TLS_IE32(location, relocVAddress, targetVAddress, addend);
- break;
+ return relocR_ARM_TLS_IE32(loc, reloc, target, addend);
case R_ARM_TLS_LE32:
- relocR_ARM_TLS_LE32(location, relocVAddress, targetVAddress, addend,
- _armLayout.getTPOffset());
- break;
+ 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();
}
- return std::error_code();
+ llvm_unreachable("All switch cases must return directly");
}
diff --git a/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h b/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h
index 227d68617bf9..a1f3d091f204 100644
--- a/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h
+++ b/lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h
@@ -10,26 +10,23 @@
#ifndef LLD_READER_WRITER_ELF_ARM_ARM_RELOCATION_HANDLER_H
#define LLD_READER_WRITER_ELF_ARM_ARM_RELOCATION_HANDLER_H
-#include "ARMTargetHandler.h"
+#include "lld/ReaderWriter/ELFLinkingContext.h"
namespace lld {
namespace elf {
-typedef llvm::object::ELFType<llvm::support::little, 2, false> ARMELFType;
-template <class ELFT> class ARMTargetLayout;
+class ARMTargetLayout;
-class ARMTargetRelocationHandler final
- : public TargetRelocationHandler {
+class ARMTargetRelocationHandler final : public TargetRelocationHandler {
public:
- ARMTargetRelocationHandler(ARMTargetLayout<ARMELFType> &layout)
- : _armLayout(layout) {}
+ ARMTargetRelocationHandler(ARMTargetLayout &layout) : _armLayout(layout) {}
std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
- const lld::AtomLayout &,
+ const AtomLayout &,
const Reference &) const override;
private:
- ARMTargetLayout<ARMELFType> &_armLayout;
+ ARMTargetLayout &_armLayout;
};
} // end namespace elf
diff --git a/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp b/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp
index 27ec66ac5557..fc2ae75cd7a7 100644
--- a/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp
+++ b/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp
@@ -20,7 +20,7 @@
#include "ARMLinkingContext.h"
#include "Atoms.h"
#include "lld/Core/Simple.h"
-#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/MapVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/Support/Debug.h"
@@ -28,34 +28,77 @@ using namespace lld;
using namespace lld::elf;
using namespace llvm::ELF;
-// ARM B/BL instructions of static relocation veneer.
+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_StaticAtomContent[8] = {
- 0x04, 0xf0, 0x1f, 0xe5, // ldr pc, [pc, #-4]
+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 static relocation veneer.
+// 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_StaticAtomContent[8] = {
+static const uint8_t Veneer_THM_B_BL_Abs_t_AtomContent[4] = {
0x78, 0x47, // bx pc
- 0x00, 0x00, // nop
+ 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};
-namespace {
+// .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)
- : SimpleELFDefinedAtom(f), _section(secName) {}
+ VeneerAtom(const File &f, StringRef secName, const std::string &name = "")
+ : SimpleELFDefinedAtom(f), _section(secName), _name(name) {}
Scope scope() const override { return DefinedAtom::scopeTranslationUnit; }
@@ -65,58 +108,208 @@ public:
StringRef customSectionName() const override { return _section; }
- ContentType contentType() const override {
- return DefinedAtom::typeCode;
- }
+ 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 Alignment(2); }
+ Alignment alignment() const override { return 4; }
StringRef name() const override { return _name; }
+
+private:
std::string _name;
};
-/// \brief Atoms that hold veneer for statically relocated
-/// ARM B/BL instructions.
-class Veneer_ARM_B_BL_StaticAtom : public VeneerAtom {
+/// \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_StaticAtom(const File &f, StringRef secName)
- : VeneerAtom(f, secName) {}
+ 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_StaticAtomContent);
+ return llvm::makeArrayRef(Veneer_ARM_B_BL_Abs_a_AtomContent);
}
};
-/// \brief Atoms that hold veneer for statically relocated
-/// Thumb B/BL instructions.
-class Veneer_THM_B_BL_StaticAtom : public VeneerAtom {
+class Veneer_ARM_B_BL_Abs_d_Atom : public VeneerAtom {
public:
- Veneer_THM_B_BL_StaticAtom(const File &f, StringRef secName)
+ 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_StaticAtomContent);
+ 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, StringRef secName) : GOTAtom(f, secName) {}
+ ARMGOTAtom(const File &f) : GOTAtom(f, ".got") {}
ArrayRef<uint8_t> rawContent() const override {
return llvm::makeArrayRef(ARMGotAtomContent);
}
- Alignment alignment() const override { return Alignment(2); }
+ 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 {
@@ -140,30 +333,92 @@ template <class Derived> class ARMRelocationPass : public Pass {
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:
- static_cast<Derived *>(this)->handleVeneer(atom, ref);
- break;
+ 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:
- std::error_code handleVeneer(const DefinedAtom &atom, const Reference &ref) {
+ /// \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 || target->codeModel() == atom.codeModel())
+ if (!target || isThumbCode(target) == isThumbCode(&atom))
return std::error_code();
- // TODO: For unconditional jump instructions (R_ARM_CALL and R_ARM_THM_CALL)
- // fixup isn't possible without veneer generation for archs below ARMv5.
-
// Veneers may only be generated for STT_FUNC target symbols
// or for symbols located in sections different to the place of relocation.
- const auto kindValue = ref.kindValue();
StringRef secName = atom.customSectionName();
if (DefinedAtom::typeCode != target->contentType() &&
!target->customSectionName().equals(secName)) {
@@ -182,29 +437,69 @@ protected:
llvm_unreachable(errStr.c_str());
}
- const Atom *veneer = nullptr;
- switch (kindValue) {
- case R_ARM_JUMP24:
- veneer = static_cast<Derived *>(this)
- ->getVeneer_ARM_B_BL(target, secName);
- break;
- case R_ARM_THM_JUMP24:
- veneer = static_cast<Derived *>(this)
- ->getVeneer_THM_B_BL(target, secName);
- break;
- default:
- llvm_unreachable("Unhandled reference type for veneer generation");
- }
+ 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));
+ 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");
@@ -213,20 +508,160 @@ protected:
/// \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) {
- auto got = _gotMap.find(da);
- if (got != _gotMap.end())
- return got->second;
- auto g = new (_file._alloc) ARMGOTAtom(_file, ".got");
- g->addReferenceELF_ARM(R_ARM_TLS, 0, da, A);
+ StringRef source;
#ifndef NDEBUG
- g->_name = "__got_tls_";
+ 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
- _gotMap[da] = g;
- _gotVector.push_back(g);
+ _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) {}
@@ -238,35 +673,35 @@ public:
///
/// After all references are handled, the atoms created during that are all
/// added to mf.
- void perform(std::unique_ptr<MutableFile> &mf) override {
+ 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()) {
+ : mf.undefined()) {
llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
}
llvm::dbgs() << "Shared Library Atoms" << "\n";
for (const auto &atom
- : mf->sharedLibrary()) {
+ : mf.sharedLibrary()) {
llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
}
llvm::dbgs() << "Absolute Atoms" << "\n";
for (const auto &atom
- : mf->absolute()) {
+ : mf.absolute()) {
llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
}
llvm::dbgs() << "Defined Atoms" << "\n";
for (const auto &atom
- : mf->defined()) {
+ : mf.defined()) {
llvm::dbgs() << " Name of Atom: " << atom->name().str() << "\n";
});
// Process all references.
- for (const auto &atom : mf->defined()) {
+ for (const auto &atom : mf.defined()) {
for (const auto &ref : *atom) {
handleReference(*atom, *ref);
}
@@ -274,14 +709,58 @@ public:
// Add all created atoms to the link.
uint64_t ordinal = 0;
- for (auto &got : _gotVector) {
+ 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);
+ 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 &veneer : _veneerVector) {
- veneer->setOrdinal(ordinal++);
- mf->addAtom(*veneer);
+ 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:
@@ -290,16 +769,56 @@ protected:
const ELFLinkingContext &_ctx;
/// \brief Map Atoms to their GOT entries.
- llvm::DenseMap<const Atom *, GOTAtom *> _gotMap;
+ llvm::MapVector<const Atom *, GOTAtom *> _gotAtoms;
- /// \brief Map Atoms to their veneers.
- llvm::DenseMap<const Atom *, VeneerAtom *> _veneerMap;
+ /// \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 the list of GOT/PLT atoms
- std::vector<GOTAtom *> _gotVector;
+ /// \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) {}
- /// \brief the list of veneer atoms.
- std::vector<VeneerAtom *> _veneerVector;
+ 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
@@ -314,47 +833,138 @@ 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) {
- auto veneer = _veneerMap.find(da);
- if (_veneerMap.end() != veneer)
- return veneer->second;
+ 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 v = new (_file._alloc) Veneer_ARM_B_BL_StaticAtom(_file, secName);
- v->addReferenceELF_ARM(R_ARM_ABS32, 4, da, 0);
+ auto oa = new (_file._alloc) ARMObjectAtom(_file);
+ oa->addReferenceELF_ARM(R_ARM_COPY, 0, oa, 0);
- v->_name = "__";
- v->_name += da->name();
- v->_name += "_from_arm";
+ oa->_name = a->name();
+ oa->_size = a->size();
+
+ _objectAtoms[a] = oa;
+ return oa;
+ }
- _veneerMap[da] = v;
- _veneerVector.push_back(v);
- return v;
+ /// \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) {
- auto veneer = _veneerMap.find(da);
- if (_veneerMap.end() != veneer)
- return veneer->second;
+ if (_ctx.getOutputELFType() == llvm::ELF::ET_EXEC) {
+ return getVeneer_THM_B_BL_Abs(da, secName);
+ }
+ llvm_unreachable("Handle Thumb veneer for DSOs");
+ }
- auto v = new (_file._alloc) Veneer_THM_B_BL_StaticAtom(_file, secName);
- v->addReferenceELF_ARM(R_ARM_JUMP24, 4, da, 0);
+ /// \brief Create a GOT entry for R_ARM_TLS_TPOFF32 reloc.
+ const GOTAtom *getTLSTPOFF32(const DefinedAtom *da) {
+ return getGOTTLSEntry<R_ARM_TLS_TPOFF32>(da);
+ }
- v->_name = "__";
- v->_name += da->name();
- v->_name += "_from_thumb";
+ 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;
+ }
- _veneerMap[da] = v;
- _veneerVector.push_back(v);
- return v;
+ const GOTAtom *getSharedGOTEntry(const SharedLibraryAtom *sla) {
+ return getGOT<R_ARM_GLOB_DAT>(sla);
}
- /// \brief Create a GOT entry for R_ARM_TLS_TPOFF32 reloc.
- const GOTAtom *getTLSTPOFF32(const DefinedAtom *da) {
- return getGOTTLSEntry<R_ARM_TLS_LE32>(da);
+ 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);
}
};
@@ -365,8 +975,10 @@ lld::elf::createARMRelocationPass(const ARMLinkingContext &ctx) {
switch (ctx.getOutputELFType()) {
case llvm::ELF::ET_EXEC:
if (ctx.isDynamic())
- llvm_unreachable("Unhandled output file type");
+ 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/ARMSymbolTable.h b/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h
index 540a480421a8..85b9c9162589 100644
--- a/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h
+++ b/lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h
@@ -10,34 +10,47 @@
#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
-template<class ELFT>
-class ARMSymbolTable : public SymbolTable<ELFT> {
+class ARMSymbolTable : public SymbolTable<ELF32LE> {
public:
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
+ typedef llvm::object::Elf_Sym_Impl<ELF32LE> Elf_Sym;
- ARMSymbolTable(const ELFLinkingContext &context);
+ ARMSymbolTable(const ELFLinkingContext &ctx);
void addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
int64_t addr) override;
};
-template <class ELFT>
-ARMSymbolTable<ELFT>::ARMSymbolTable(const ELFLinkingContext &context)
- : SymbolTable<ELFT>(context, ".symtab",
- DefaultLayout<ELFT>::ORDER_SYMBOL_TABLE) {}
+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);
-template <class ELFT>
-void ARMSymbolTable<ELFT>::addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
- int64_t addr) {
- SymbolTable<ELFT>::addDefinedAtom(sym, da, addr);
+ if ((ARMELFDefinedAtom::ARMContentType)da->contentType() ==
+ ARMELFDefinedAtom::typeARMExidx)
+ sym.st_value = addr;
- // Set zero bit to distinguish symbols addressing Thumb instructions
+ // 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
diff --git a/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp b/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp
index de90f490f621..e1f5eadbe789 100644
--- a/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp
+++ b/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp
@@ -9,36 +9,24 @@
#include "Atoms.h"
#include "ARMExecutableWriter.h"
+#include "ARMDynamicLibraryWriter.h"
#include "ARMTargetHandler.h"
#include "ARMLinkingContext.h"
using namespace lld;
using namespace elf;
-ARMTargetHandler::ARMTargetHandler(ARMLinkingContext &context)
- : _context(context), _armTargetLayout(
- new ARMTargetLayout<ARMELFType>(context)),
- _armRelocationHandler(new ARMTargetRelocationHandler(
- *_armTargetLayout.get())) {}
-
-void ARMTargetHandler::registerRelocationNames(Registry &registry) {
- registry.addKindTable(Reference::KindNamespace::ELF, Reference::KindArch::ARM,
- kindStrings);
-}
+ARMTargetHandler::ARMTargetHandler(ARMLinkingContext &ctx)
+ : _ctx(ctx), _targetLayout(new ARMTargetLayout(ctx)),
+ _relocationHandler(new ARMTargetRelocationHandler(*_targetLayout)) {}
std::unique_ptr<Writer> ARMTargetHandler::getWriter() {
- switch (this->_context.getOutputELFType()) {
+ switch (this->_ctx.getOutputELFType()) {
case llvm::ELF::ET_EXEC:
- return std::unique_ptr<Writer>(
- new ARMExecutableWriter<ARMELFType>(_context, *_armTargetLayout.get()));
+ 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");
}
}
-
-#define ELF_RELOC(name, value) LLD_KIND_STRING_ENTRY(name),
-
-const Registry::KindStrings ARMTargetHandler::kindStrings[] = {
-#include "llvm/Support/ELFRelocs/ARM.def"
- LLD_KIND_STRING_END
-};
diff --git a/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h b/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h
index 10641954da25..0352e81a1f61 100644
--- a/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h
+++ b/lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h
@@ -11,75 +11,161 @@
#define LLD_READER_WRITER_ELF_ARM_ARM_TARGET_HANDLER_H
#include "ARMELFFile.h"
-#include "ARMELFReader.h"
#include "ARMRelocationHandler.h"
-#include "DefaultTargetHandler.h"
+#include "ELFReader.h"
#include "TargetLayout.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/Optional.h"
-#include <map>
-
namespace lld {
+class ELFLinkingContext;
+
namespace elf {
-typedef llvm::object::ELFType<llvm::support::little, 2, false> ARMELFType;
-class ARMLinkingContext;
-template <class ELFT> class ARMTargetLayout : public TargetLayout<ELFT> {
+/// \brief ARM specific section (.ARM.exidx) with indexes to exception handlers
+class ARMExidxSection : public AtomSection<ELF32LE> {
+ typedef AtomSection<ELF32LE> Base;
+
public:
- ARMTargetLayout(ARMLinkingContext &context)
- : TargetLayout<ELFT>(context) {}
+ 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;
+ }
- uint64_t getTPOffset() {
- if (_tpOff.hasValue())
- return *_tpOff;
+ bool hasOutputSegment() const override { return true; }
- for (const auto &phdr : *this->_programHeader) {
- if (phdr->p_type == llvm::ELF::PT_TLS) {
- _tpOff = llvm::RoundUpToAlignment(TCB_SIZE, phdr->p_align);
- return *_tpOff;
- }
+ 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);
}
- llvm_unreachable("TLS segment not found");
}
+ 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 };
- // Cached value of the TLS offset from the $tp pointer.
- llvm::Optional<uint64_t> _tpOff;
+private:
+ uint64_t _gotSymAddr = 0;
+ uint64_t _tpOff = 0;
+ std::once_flag _gotSymOnce;
+ std::once_flag _tpOffOnce;
};
-class ARMTargetHandler final : public DefaultTargetHandler<ARMELFType> {
+class ARMTargetHandler final : public TargetHandler {
public:
- ARMTargetHandler(ARMLinkingContext &context);
-
- ARMTargetLayout<ARMELFType> &getTargetLayout() override {
- return *(_armTargetLayout.get());
- }
-
- void registerRelocationNames(Registry &registry) override;
+ ARMTargetHandler(ARMLinkingContext &ctx);
- const ARMTargetRelocationHandler &getRelocationHandler() const override {
- return *(_armRelocationHandler.get());
+ const TargetRelocationHandler &getRelocationHandler() const override {
+ return *_relocationHandler;
}
std::unique_ptr<Reader> getObjReader() override {
- return std::unique_ptr<Reader>(new ARMELFObjectReader(_context));
+ return llvm::make_unique<ELFReader<ARMELFFile>>(_ctx);
}
std::unique_ptr<Reader> getDSOReader() override {
- return std::unique_ptr<Reader>(new ARMELFDSOReader(_context));
+ return llvm::make_unique<ELFReader<DynamicFile<ELF32LE>>>(_ctx);
}
std::unique_ptr<Writer> getWriter() override;
private:
- static const Registry::KindStrings kindStrings[];
- ARMLinkingContext &_context;
- std::unique_ptr<ARMTargetLayout<ARMELFType>> _armTargetLayout;
- std::unique_ptr<ARMTargetRelocationHandler> _armRelocationHandler;
+ ARMLinkingContext &_ctx;
+ std::unique_ptr<ARMTargetLayout> _targetLayout;
+ std::unique_ptr<ARMTargetRelocationHandler> _relocationHandler;
};
} // end namespace elf
diff --git a/lib/ReaderWriter/ELF/ARM/Makefile b/lib/ReaderWriter/ELF/ARM/Makefile
deleted file mode 100644
index f67d36a1b612..000000000000
--- a/lib/ReaderWriter/ELF/ARM/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-##===------ lld/lib/ReaderWriter/ELF/ARM/Makefile ----------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL := ../../../..
-LIBRARYNAME := lldARMELFTarget
-USEDLIBS = lldCore.a
-CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF/ARM -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF
-
-include $(LLD_LEVEL)/Makefile
diff --git a/lib/ReaderWriter/ELF/ARM/TODO.rst b/lib/ReaderWriter/ELF/ARM/TODO.rst
index d05419decb78..61b585ae698c 100644
--- a/lib/ReaderWriter/ELF/ARM/TODO.rst
+++ b/lib/ReaderWriter/ELF/ARM/TODO.rst
@@ -4,14 +4,15 @@ ELF ARM
Unimplemented Features
######################
-* Static executable linking - in progress
-* Dynamic executable linking
* DSO linking
-* PLT entries' generation for images larger than 2^28 bytes (see Sec. A.3 of the ELF reference)
-* ARM and Thumb interworking (see http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dui0203j/Bcghfebi.html)
-* .ARM.exidx section handling
+* 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
-* Lots of relocations
+* Proper debug information (DWARF data)
+* TLS relocations for dynamic models
+* Lots of other relocations
Unimplemented Relocations
#########################
diff --git a/lib/ReaderWriter/ELF/Atoms.cpp b/lib/ReaderWriter/ELF/Atoms.cpp
new file mode 100644
index 000000000000..639633393161
--- /dev/null
+++ b/lib/ReaderWriter/ELF/Atoms.cpp
@@ -0,0 +1,297 @@
+//===- 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
index 6a506d21d938..390c0e16baf8 100644
--- a/lib/ReaderWriter/ELF/Atoms.h
+++ b/lib/ReaderWriter/ELF/Atoms.h
@@ -13,6 +13,7 @@
#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>
@@ -41,19 +42,16 @@ public:
ELFReference(const Elf_Rela *rela, uint64_t off, Reference::KindArch arch,
Reference::KindValue relocType, uint32_t idx)
: Reference(Reference::KindNamespace::ELF, arch, relocType),
- _target(nullptr), _targetSymbolIndex(idx), _offsetInAtom(off),
- _addend(rela->r_addend) {}
+ _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),
- _target(nullptr), _targetSymbolIndex(idx), _offsetInAtom(off),
- _addend(0) {}
+ _targetSymbolIndex(idx), _offsetInAtom(off) {}
ELFReference(uint32_t edgeKind)
: Reference(Reference::KindNamespace::all, Reference::KindArch::all,
- edgeKind),
- _target(nullptr), _targetSymbolIndex(0), _offsetInAtom(0), _addend(0) {}
+ edgeKind) {}
uint64_t offsetInAtom() const override { return _offsetInAtom; }
@@ -73,10 +71,10 @@ public:
void setTarget(const Atom *newAtom) override { _target = newAtom; }
private:
- const Atom *_target;
- uint64_t _targetSymbolIndex;
- uint64_t _offsetInAtom;
- Addend _addend;
+ 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.
@@ -88,21 +86,11 @@ template <class ELFT> class ELFAbsoluteAtom : public AbsoluteAtom {
public:
ELFAbsoluteAtom(const ELFFile<ELFT> &file, StringRef name,
const Elf_Sym *symbol, uint64_t value)
- : _owningFile(file), _name(name), _symbol(symbol), _value(value) {
- }
+ : _owningFile(file), _name(name), _symbol(symbol), _value(value) {}
const ELFFile<ELFT> &file() const override { return _owningFile; }
-
- Scope scope() const override {
- if (_symbol->getVisibility() == llvm::ELF::STV_HIDDEN)
- return scopeLinkageUnit;
- if (_symbol->getBinding() == llvm::ELF::STB_LOCAL)
- return scopeTranslationUnit;
- return scopeGlobal;
- }
-
+ Scope scope() const override;
StringRef name() const override { return _name; }
-
uint64_t value() const override { return _value; }
private:
@@ -114,7 +102,7 @@ private:
/// \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 lld::UndefinedAtom {
+template <class ELFT> class ELFUndefinedAtom : public UndefinedAtom {
typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
public:
@@ -122,16 +110,11 @@ public:
: _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 {
- if (_symbol->getBinding() == llvm::ELF::STB_WEAK)
- return CanBeNull::canBeNullAtBuildtime;
- return CanBeNull::canBeNullNever;
- }
+ CanBeNull canBeNull() const override;
private:
const File &_owningFile;
@@ -157,283 +140,49 @@ public:
_referenceList(referenceList), _contentType(typeUnknown),
_permissions(permUnknown) {}
- ~ELFDefinedAtom() {}
+ ~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 {
- // 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();
- }
-
- Scope scope() const override {
- if (!_symbol)
- return scopeGlobal;
- if (_symbol->getVisibility() == llvm::ELF::STV_HIDDEN)
- return scopeLinkageUnit;
- if (_symbol->getBinding() != llvm::ELF::STB_LOCAL)
- return scopeGlobal;
- return scopeTranslationUnit;
- }
+ 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 {
- 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;
- }
-
- ContentType contentType() const override {
- if (_contentType != typeUnknown)
- return _contentType;
-
- ContentType ret = typeUnknown;
- uint64_t flags = _section->sh_flags;
-
- if (_section->sh_type == llvm::ELF::SHT_GROUP)
- return typeGroupComdat;
-
- if (!_symbol && _sectionName.startswith(".gnu.linkonce"))
- return typeGnuLinkOnce;
-
- if (!(flags & llvm::ELF::SHF_ALLOC))
- return _contentType = typeNoAlloc;
-
- if (_section->sh_flags ==
- (llvm::ELF::SHF_ALLOC | llvm::ELF::SHF_WRITE | llvm::ELF::SHF_TLS)) {
- return _contentType = _section->sh_type == llvm::ELF::SHT_NOBITS ? typeThreadZeroFill
- : typeThreadData;
- }
-
- if ((_section->sh_flags == llvm::ELF::SHF_ALLOC) &&
- (_section->sh_type == llvm::ELF::SHT_PROGBITS))
- return _contentType = typeConstant;
-
- if (_symbol->getType() == llvm::ELF::STT_GNU_IFUNC)
- return _contentType = typeResolver;
-
- if (_symbol->st_shndx == llvm::ELF::SHN_COMMON)
- return _contentType = typeZeroFill;
-
- switch (_section->sh_type) {
- case llvm::ELF::SHT_PROGBITS:
- flags &= ~llvm::ELF::SHF_ALLOC;
- flags &= ~llvm::ELF::SHF_GROUP;
- switch (flags) {
- case llvm::ELF::SHF_EXECINSTR:
- case (llvm::ELF::SHF_WRITE|llvm::ELF::SHF_EXECINSTR):
- ret = typeCode;
- break;
- case llvm::ELF::SHF_WRITE:
- ret = typeData;
- break;
- case (llvm::ELF::SHF_MERGE|llvm::ELF::SHF_STRINGS):
- case llvm::ELF::SHF_STRINGS:
- case llvm::ELF::SHF_MERGE:
- ret = typeConstant;
- break;
- default:
- ret = typeCode;
- break;
- }
- break;
- case llvm::ELF::SHT_NOTE:
- flags &= ~llvm::ELF::SHF_ALLOC;
- switch (flags) {
- case llvm::ELF::SHF_WRITE:
- ret = typeRWNote;
- break;
- default:
- ret = typeRONote;
- break;
- }
- break;
- case llvm::ELF::SHT_NOBITS:
- ret = typeZeroFill;
- break;
- case llvm::ELF::SHT_NULL:
- if ((_symbol->getType() == llvm::ELF::STT_COMMON)
- || _symbol->st_shndx == llvm::ELF::SHN_COMMON)
- ret = typeZeroFill;
- break;
- case llvm::ELF::SHT_INIT_ARRAY:
- case llvm::ELF::SHT_FINI_ARRAY:
- ret = typeData;
- break;
- }
-
- return _contentType = ret;
- }
-
- Alignment alignment() const override {
- if (!_symbol)
- return Alignment(0);
-
- // Obtain proper value of st_value field.
- const auto symValue = getSymbolValue(_symbol);
-
- // 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 Alignment(llvm::Log2_64(symValue));
- }
- if (_section->sh_addralign == 0) {
- // sh_addralign of 0 means no alignment
- return Alignment(0, symValue);
- }
- return Alignment(llvm::Log2_64(_section->sh_addralign),
- symValue % _section->sh_addralign);
- }
-
- // Do we have a choice for ELF? All symbols live in explicit sections.
- SectionChoice sectionChoice() const override {
- 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;
- }
-
- StringRef customSectionName() const override {
- if ((contentType() == typeZeroFill) ||
- (_symbol && _symbol->st_shndx == llvm::ELF::SHN_COMMON))
- return ".bss";
- return _sectionName;
- }
+ 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 {
- 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___;
- }
- }
-
+ ContentPermissions permissions() const override;
ArrayRef<uint8_t> rawContent() const override { return _contentData; }
- DefinedAtom::reference_iterator begin() const override {
- uintptr_t index = _referenceStartIndex;
- const void *it = reinterpret_cast<const void*>(index);
- return reference_iterator(*this, it);
- }
-
- DefinedAtom::reference_iterator end() const override {
- uintptr_t index = _referenceEndIndex;
- const void *it = reinterpret_cast<const void*>(index);
- return reference_iterator(*this, it);
- }
-
- const Reference *derefIterator(const void *It) const override {
- uintptr_t index = reinterpret_cast<uintptr_t>(It);
- assert(index >= _referenceStartIndex);
- assert(index < _referenceEndIndex);
- return ((_referenceList)[index]);
- }
-
- void incrementIterator(const void *&It) const override {
- uintptr_t index = reinterpret_cast<uintptr_t>(It);
- ++index;
- It = reinterpret_cast<const void *>(index);
- }
-
- void addReference(ELFReference<ELFT> *reference) {
- _referenceList.push_back(reference);
- _referenceEndIndex = _referenceList.size();
- }
+ 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 Elf_Sym *symbol) const {
- return symbol->st_value;
+ virtual uint64_t getSymbolValue() const {
+ return _symbol->st_value;
}
-protected:
+ ContentType doContentType() const;
+
const ELFFile<ELFT> &_owningFile;
StringRef _symbolName;
StringRef _sectionName;
@@ -463,39 +212,25 @@ public:
}
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(llvm::Log2_64(_section->sh_addralign));
+ 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 {
@@ -517,7 +252,6 @@ public:
void incrementIterator(const void *&It) const override {}
private:
-
const ELFFile<ELFT> &_owningFile;
StringRef _sectionName;
const Elf_Shdr *_section;
@@ -530,21 +264,14 @@ private:
template <class ELFT> class ELFCommonAtom : public DefinedAtom {
typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
public:
- ELFCommonAtom(const ELFFile<ELFT> &file,
- StringRef symbolName,
+ ELFCommonAtom(const ELFFile<ELFT> &file, StringRef symbolName,
const Elf_Sym *symbol)
- : _owningFile(file),
- _symbolName(symbolName),
- _symbol(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 {
@@ -556,23 +283,13 @@ public:
}
Interposable interposable() const override { return interposeNo; }
-
Merge merge() const override { return mergeAsTentative; }
-
ContentType contentType() const override { return typeZeroFill; }
-
- Alignment alignment() const override {
- return Alignment(llvm::Log2_64(_symbol->st_value));
- }
-
+ 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 {
@@ -608,42 +325,19 @@ public:
ELFDynamicAtom(const DynamicFile<ELFT> &file, StringRef symbolName,
StringRef loadName, const Elf_Sym *symbol)
: _owningFile(file), _symbolName(symbolName), _loadName(loadName),
- _symbol(symbol) {
- }
+ _symbol(symbol) {}
const DynamicFile<ELFT> &file() const override { return _owningFile; }
-
StringRef name() const override { return _symbolName; }
-
- virtual Scope scope() const {
- if (_symbol->getVisibility() == llvm::ELF::STV_HIDDEN)
- return scopeLinkageUnit;
- if (_symbol->getBinding() != llvm::ELF::STB_LOCAL)
- return scopeGlobal;
- return scopeTranslationUnit;
- }
-
+ 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 {
- 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;
- }
- }
-
- uint64_t size() const override {
- return _symbol->st_size;
- }
+ Type type() const override;
+ uint64_t size() const override { return _symbol->st_size; }
private:
@@ -658,35 +352,33 @@ public:
SimpleELFDefinedAtom(const File &f) : SimpleDefinedAtom(f) {}
void addReferenceELF(Reference::KindArch arch, Reference::KindValue kindValue,
- uint64_t off, const Atom *target,
- Reference::Addend addend) {
- this->addReference(Reference::KindNamespace::ELF, arch, kindValue, off,
- target, addend);
+ 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) {
- this->addReferenceELF(Reference::KindArch::Hexagon, relocType, off, t, 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) {
- this->addReferenceELF(Reference::KindArch::x86_64, relocType, off, t, 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) {
- this->addReferenceELF(Reference::KindArch::Mips, relocType, off, t, a);
+ addReferenceELF(Reference::KindArch::Mips, relocType, off, t, a);
}
void addReferenceELF_AArch64(Reference::KindValue relocType, uint64_t off,
const Atom *t, Reference::Addend a) {
- this->addReferenceELF(Reference::KindArch::AArch64, relocType, off, t, a);
+ addReferenceELF(Reference::KindArch::AArch64, relocType, off, t, a);
}
void addReferenceELF_ARM(Reference::KindValue relocType, uint64_t off,
const Atom *t, Reference::Addend a) {
- this->addReferenceELF(Reference::KindArch::ARM, relocType, off, t, a);
+ addReferenceELF(Reference::KindArch::ARM, relocType, off, t, a);
}
};
@@ -695,26 +387,14 @@ public:
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 {
- // The alignment should be 8 byte aligned
- return Alignment(3);
- }
-
+ Alignment alignment() const override { return 8; }
StringRef name() const override { return _name; }
std::string _name;
@@ -729,21 +409,12 @@ public:
: 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 {
- // The alignment should be 8 byte aligned
- return Alignment(3);
- }
+ Alignment alignment() const override { return 8; }
#ifndef NDEBUG
StringRef name() const override { return _name; }
@@ -761,20 +432,12 @@ public:
: 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 Alignment(4); // 16
- }
+ Alignment alignment() const override { return 16; }
#ifndef NDEBUG
StringRef name() const override { return _name; }
@@ -793,57 +456,38 @@ public:
}
};
-class GLOBAL_OFFSET_TABLEAtom : public SimpleELFDefinedAtom {
+class GlobalOffsetTableAtom : public SimpleELFDefinedAtom {
public:
- GLOBAL_OFFSET_TABLEAtom(const File &f) : SimpleELFDefinedAtom(f) {}
+ 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 {
- // Needs 8 byte alignment
- return Alignment(3);
- }
-
+ Alignment alignment() const override { return 8; }
ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
};
-class DYNAMICAtom : public SimpleELFDefinedAtom {
+class DynamicAtom : public SimpleELFDefinedAtom {
public:
- DYNAMICAtom(const File &f) : SimpleELFDefinedAtom(f) {}
+ 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 Alignment(0); }
-
+ Alignment alignment() const override { return 1; }
ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
};
+
} // end namespace elf
} // end namespace lld
-#endif
+#endif // LLD_READER_WRITER_ELF_ATOMS_H
diff --git a/lib/ReaderWriter/ELF/CMakeLists.txt b/lib/ReaderWriter/ELF/CMakeLists.txt
index fd4cb669904d..e3e4a02b2810 100644
--- a/lib/ReaderWriter/ELF/CMakeLists.txt
+++ b/lib/ReaderWriter/ELF/CMakeLists.txt
@@ -1,11 +1,21 @@
add_llvm_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
)
@@ -17,3 +27,4 @@ add_subdirectory(Mips)
add_subdirectory(Hexagon)
add_subdirectory(AArch64)
add_subdirectory(ARM)
+add_subdirectory(AMDGPU)
diff --git a/lib/ReaderWriter/ELF/Chunk.h b/lib/ReaderWriter/ELF/Chunk.h
index 2658d023b3a9..f223b6c54163 100644
--- a/lib/ReaderWriter/ELF/Chunk.h
+++ b/lib/ReaderWriter/ELF/Chunk.h
@@ -25,32 +25,33 @@ 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 {
+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
+ 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 };
+ enum ContentType : uint8_t { Unknown, Header, Code, Data, Note, TLS };
+
+ Chunk(StringRef name, Kind kind, const ELFLinkingContext &ctx)
+ : _name(name), _kind(kind), _ctx(ctx) {}
- Chunk(StringRef name, Kind kind, const ELFLinkingContext &context)
- : _name(name), _kind(kind), _fsize(0), _msize(0), _alignment(0), _order(0),
- _ordinal(1), _start(0), _fileoffset(0), _context(context) {}
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; }
@@ -59,41 +60,49 @@ public:
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;}
+ 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; }
+ 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; }
+ 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; }
- // Whats the contentType of the chunk?
+
+ // 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() = 0;
+ virtual void doPreFlight() {}
+
// Finalize the chunk before writing
- virtual void finalize() = 0;
+ virtual void finalize() {}
protected:
StringRef _name;
Kind _kind;
- uint64_t _fsize;
- uint64_t _msize;
- uint64_t _alignment;
- uint32_t _order;
- uint64_t _ordinal;
- uint64_t _start;
- uint64_t _fileoffset;
- const ELFLinkingContext &_context;
+ 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
diff --git a/lib/ReaderWriter/ELF/CreateELF.h b/lib/ReaderWriter/ELF/CreateELF.h
deleted file mode 100644
index ad34dddb24d3..000000000000
--- a/lib/ReaderWriter/ELF/CreateELF.h
+++ /dev/null
@@ -1,118 +0,0 @@
-//===- lib/ReaderWriter/ELF/CreateELF.h -----------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief This file provides a simple way to create an object templated on
-/// ELFType depending on the runtime type needed.
-///
-//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_CREATE_ELF_H
-#define LLD_READER_WRITER_ELF_CREATE_ELF_H
-
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/Compiler.h"
-
-namespace {
-using llvm::object::ELFType;
-
-/// \func createELF
-/// \brief Create an object depending on the runtime attributes and alignment
-/// of an ELF file.
-///
-/// \param Traits
-/// Traits::result_type must be a type convertable from what create returns.
-/// Traits::create must be a template function which takes an ELFType and
-/// returns something convertable to Traits::result_type.
-///
-/// \param ident pair of EI_CLASS and EI_DATA.
-/// \param maxAlignment the maximum alignment of the file.
-/// \param args arguments forwarded to CreateELFTraits<T>::create.
-
-#define LLVM_CREATE_ELF_CreateELFTraits(endian, align, is64, ...) \
- Traits::template create<ELFType<llvm::support::endian, align, is64>>( \
- __VA_ARGS__);
-
-#if !LLVM_IS_UNALIGNED_ACCESS_FAST
-# define LLVM_CREATE_ELF_MaxAlignCheck(normal, low, endian, is64, ...) \
- if (maxAlignment >= normal) \
- return LLVM_CREATE_ELF_CreateELFTraits(endian, normal, is64, __VA_ARGS__) \
- else if (maxAlignment >= low) \
- return LLVM_CREATE_ELF_CreateELFTraits(endian, low, is64, __VA_ARGS__) \
- else \
- llvm_unreachable("Invalid alignment for ELF file!");
-#else
-# define LLVM_CREATE_ELF_MaxAlignCheck(normal, low, endian, is64, ...) \
- if (maxAlignment >= low) \
- return LLVM_CREATE_ELF_CreateELFTraits(endian, low, is64, __VA_ARGS__) \
- else \
- llvm_unreachable("Invalid alignment for ELF file!");
-#endif
-
-#define LLVM_CREATE_ELF_IMPL(...) \
- if (ident.first == llvm::ELF::ELFCLASS32 && \
- ident.second == llvm::ELF::ELFDATA2LSB) { \
- LLVM_CREATE_ELF_MaxAlignCheck(4, 2, little, false, __VA_ARGS__) \
- } else if (ident.first == llvm::ELF::ELFCLASS32 && \
- ident.second == llvm::ELF::ELFDATA2MSB) { \
- LLVM_CREATE_ELF_MaxAlignCheck(4, 2, big, false, __VA_ARGS__) \
- } else if (ident.first == llvm::ELF::ELFCLASS64 && \
- ident.second == llvm::ELF::ELFDATA2MSB) { \
- LLVM_CREATE_ELF_MaxAlignCheck(8, 2, big, true, __VA_ARGS__) \
- } else if (ident.first == llvm::ELF::ELFCLASS64 && \
- ident.second == llvm::ELF::ELFDATA2LSB) { \
- LLVM_CREATE_ELF_MaxAlignCheck(8, 2, little, true, __VA_ARGS__) \
- } \
- llvm_unreachable("Invalid ELF type!");
-
-#if LLVM_HAS_VARIADIC_TEMPLATES
-template <class Traits, class ...Args>
-typename Traits::result_type createELF(
- std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment,
- Args &&...args) {
- LLVM_CREATE_ELF_IMPL(std::forward<Args>(args)...)
-}
-#else
-template <class Traits, class T1>
-typename Traits::result_type createELF(
- std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment,
- T1 &&t1) {
- LLVM_CREATE_ELF_IMPL(std::forward<T1>(t1))
-}
-
-template <class Traits, class T1, class T2>
-typename Traits::result_type createELF(
- std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment,
- T1 &&t1, T2 &&t2) {
- LLVM_CREATE_ELF_IMPL(std::forward<T1>(t1), std::forward<T2>(t2))
-}
-
-template <class Traits, class T1, class T2, class T3>
-typename Traits::result_type createELF(
- std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment,
- T1 &&t1, T2 &&t2, T3 &&t3) {
- LLVM_CREATE_ELF_IMPL(std::forward<T1>(t1), std::forward<T2>(t2),
- std::forward<T3>(t3))
-}
-
-template <class Traits, class T1, class T2, class T3, class T4>
-typename Traits::result_type createELF(
- std::pair<unsigned char, unsigned char> ident, std::size_t maxAlignment,
- T1 &&t1, T2 &&t2, T3 &&t3, T4 &&t4) {
- LLVM_CREATE_ELF_IMPL(std::forward<T1>(t1), std::forward<T2>(t2),
- std::forward<T3>(t3), std::forward<T4>(t4))
-}
-
-#endif // LLVM_HAS_VARIADIC_TEMPLATES
-} // end anon namespace
-
-#undef LLVM_CREATE_ELF_CreateELFTraits
-#undef LLVM_CREATE_ELF_MaxAlignCheck
-#undef LLVM_CREATE_ELF_IMPL
-
-#endif
diff --git a/lib/ReaderWriter/ELF/DefaultLayout.h b/lib/ReaderWriter/ELF/DefaultLayout.h
deleted file mode 100644
index 9af3b8eb8dc6..000000000000
--- a/lib/ReaderWriter/ELF/DefaultLayout.h
+++ /dev/null
@@ -1,1050 +0,0 @@
-//===- lib/ReaderWriter/ELF/DefaultLayout.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 "Chunk.h"
-#include "HeaderChunks.h"
-#include "Layout.h"
-#include "SectionChunks.h"
-#include "SegmentChunks.h"
-#include "lld/Core/Instrumentation.h"
-#include "lld/Core/STDExtras.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseSet.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/SmallVector.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/ADT/StringMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/Format.h"
-#include <map>
-#include <unordered_map>
-
-namespace lld {
-namespace elf {
-/// \brief The DefaultLayout 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 DefaultLayout
-/// class
-template<class ELFT>
-class DefaultLayout : public Layout {
-public:
-
- // 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;
-
- // The additional segments are used to figure out
- // if there is a segment by that type already created
- // For example : PT_TLS, we have two sections .tdata/.tbss
- // that are part of PT_TLS, we need to create this additional
- // segment only once
- typedef std::pair<int64_t, int64_t> AdditionalSegmentKey;
- // The segments are created using
- // SegmentName, Segment flags
- typedef std::pair<StringRef, int64_t> SegmentKey;
-
- // HashKey for the Segment
- class SegmentHashKey {
- public:
- int64_t operator() (const SegmentKey &k) const {
- // k.first = SegmentName
- // k.second = SegmentFlags
- return llvm::hash_combine(k.first, k.second);
- }
- };
-
- class AdditionalSegmentHashKey {
- public:
- int64_t operator()(const AdditionalSegmentKey &k) const {
- // k.first = SegmentName
- // k.second = SegmentFlags
- return llvm::hash_combine(k.first, k.second);
- }
- };
-
- // Output Sections contain the map of Sectionnames 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<AdditionalSegmentKey, Segment<ELFT> *,
- AdditionalSegmentHashKey> AdditionalSegmentMapT;
- typedef std::unordered_map<SegmentKey, Segment<ELFT> *, SegmentHashKey>
- SegmentMapT;
-
- /// \brief find a absolute atom pair given a absolute atom name
- struct FindByName {
- const std::string _name;
- FindByName(StringRef name) : _name(name) {}
- bool operator()(const lld::AtomLayout *j) { return j->_atom->name() == _name; }
- };
-
- typedef typename std::vector<lld::AtomLayout *>::iterator AbsoluteAtomIterT;
-
- typedef llvm::DenseSet<const Atom *> AtomSetT;
-
- DefaultLayout(ELFLinkingContext &context)
- : _context(context), _linkerScriptSema(context.linkerScriptSema()) {}
-
- /// \brief Return the section order for a input section
- SectionOrder getSectionOrder(StringRef name, int32_t contentType,
- int32_t contentPermissions) override;
-
- /// \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 Layout::SegmentType getSegmentType(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);
-
- // Adds an atom to the section
- ErrorOr<const lld::AtomLayout *> addAtom(const Atom *atom) override;
-
- /// \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
- AbsoluteAtomIterT findAbsoluteAtom(StringRef name) {
- return std::find_if(_absoluteAtoms.begin(), _absoluteAtoms.end(),
- FindByName(name));
- }
-
- // Output sections with the same name into a OutputSection
- void createOutputSections();
-
- /// \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);
-
- void assignSectionsToSegments() override;
-
- void assignVirtualAddress() override;
-
- 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();
- }
-
- const AtomLayout *findAtomLayoutByName(StringRef name) const override {
- for (auto sec : _sections)
- if (auto section = dyn_cast<Section<ELFT>>(sec))
- if (auto *al = section->findAtomLayoutByName(name))
- return al;
- return nullptr;
- }
-
- 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() {
- if (!_dynamicRelocationTable) {
- _dynamicRelocationTable = std::move(createRelocationTable(
- _context.isRelaOutputFormat() ? ".rela.dyn" : ".rel.dyn",
- ORDER_DYNAMIC_RELOCS));
- addSection(_dynamicRelocationTable.get());
- }
- return _dynamicRelocationTable.get();
- }
-
- /// \brief Get or create the PLT relocation table. Referenced by DT_JMPREL.
- RelocationTable<ELFT> *getPLTRelocationTable() {
- if (!_pltRelocationTable) {
- _pltRelocationTable = std::move(createRelocationTable(
- _context.isRelaOutputFormat() ? ".rela.plt" : ".rel.plt",
- ORDER_DYNAMIC_PLT_RELOCS));
- addSection(_pltRelocationTable.get());
- }
- return _pltRelocationTable.get();
- }
-
- uint64_t getTLSSize() const {
- for (const auto &phdr : *_programHeader)
- if (phdr->p_type == llvm::ELF::PT_TLS)
- return phdr->p_memsz;
- return 0;
- }
-
- bool isReferencedByDefinedAtom(const Atom *a) const {
- return _referencedDynAtoms.count(a);
- }
-
- bool isCopied(const SharedLibraryAtom *sla) const {
- return _copiedDynSymNames.count(sla->name());
- }
-
- /// \brief Handle SORT_BY_PRIORITY.
- void sortOutputSectionByPriority(StringRef outputSectionName,
- StringRef prefix);
-
-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>(_context, name, order));
- }
-
-private:
- /// Helper function that returns the priority value from an input section.
- uint32_t getPriorityFromSectionName(StringRef sectionName) const;
-
-protected:
- llvm::BumpPtrAllocator _allocator;
- SectionMapT _sectionMap;
- OutputSectionMapT _outputSectionMap;
- AdditionalSegmentMapT _additionalSegmentMap;
- 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<lld::AtomLayout *> _absoluteAtoms;
- AtomSetT _referencedDynAtoms;
- llvm::StringSet<> _copiedDynSymNames;
- ELFLinkingContext &_context;
- script::Sema &_linkerScriptSema;
-};
-
-template <class ELFT>
-Layout::SectionOrder DefaultLayout<ELFT>::getSectionOrder(
- StringRef name, int32_t contentType, int32_t contentPermissions) {
- switch (contentType) {
- case DefinedAtom::typeResolver:
- case DefinedAtom::typeCode:
- return llvm::StringSwitch<Layout::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<Layout::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<Layout::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
-DefaultLayout<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
-DefaultLayout<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>
-Layout::SegmentType DefaultLayout<ELFT>::getSegmentType(
- 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 DefaultLayout<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> *DefaultLayout<ELFT>::createSection(
- StringRef sectionName, int32_t contentType,
- DefinedAtom::ContentPermissions permissions, SectionOrder sectionOrder) {
- return new (_allocator) AtomSection<ELFT>(_context, sectionName, contentType,
- permissions, sectionOrder);
-}
-
-template <class ELFT>
-AtomSection<ELFT> *
-DefaultLayout<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 lld::AtomLayout *>
-DefaultLayout<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 (_context.isDynamicRelocation(*reloc)) {
- getDynamicRelocationTable()->addRelocation(*definedAtom, *reloc);
- isLocalReloc = false;
- } else if (_context.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 (_context.isCopyRelocation(*reloc)) {
- _copiedDynSymNames.insert(definedAtom->name());
- continue;
- }
-
- _referencedDynAtoms.insert(reloc->target());
- }
-
- return section->appendAtom(atom);
- } else if (const AbsoluteAtom *absoluteAtom = dyn_cast<AbsoluteAtom>(atom)) {
- // Absolute atoms are not part of any section, they are global for the whole
- // link
- _absoluteAtoms.push_back(new (_allocator)
- lld::AtomLayout(absoluteAtom, 0, absoluteAtom->value()));
- return _absoluteAtoms.back();
- } else {
- llvm_unreachable("Only absolute / defined atoms can be added here");
- }
-}
-
-/// Output sections with the same name into a OutputSection
-template <class ELFT> void DefaultLayout<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(si);
- }
-}
-
-template <class ELFT>
-uint32_t
-DefaultLayout<ELFT>::getPriorityFromSectionName(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 <class ELFT>
-void DefaultLayout<ELFT>::sortOutputSectionByPriority(
- StringRef outputSectionName, StringRef prefix) {
- OutputSection<ELFT> *outputSection = findOutputSection(outputSectionName);
- if (!outputSection)
- return;
-
- auto sections = outputSection->sections();
-
- std::sort(sections.begin(), sections.end(),
- [&](Chunk<ELFT> *lhs, Chunk<ELFT> *rhs) {
- Section<ELFT> *lhsSection = dyn_cast<Section<ELFT>>(lhs);
- Section<ELFT> *rhsSection = dyn_cast<Section<ELFT>>(rhs);
- if (!lhsSection || !rhsSection)
- return false;
- StringRef lhsSectionName = lhsSection->inputSectionName();
- StringRef rhsSectionName = rhsSection->inputSectionName();
-
- if (!prefix.empty()) {
- if (!lhsSectionName.startswith(prefix) ||
- !rhsSectionName.startswith(prefix))
- return false;
- }
- return getPriorityFromSectionName(lhsSectionName) <
- getPriorityFromSectionName(rhsSectionName);
- });
-}
-
-template <class ELFT> void DefaultLayout<ELFT>::assignSectionsToSegments() {
- ScopedTask task(getDefaultDomain(), "assignSectionsToSegments");
- ELFLinkingContext::OutputMagic outputMagic = _context.getOutputMagic();
- // 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 ai : osi->sections()) {
- if (auto section = dyn_cast<Section<ELFT> >(ai)) {
- if (!hasOutputSegment(section))
- continue;
-
- osi->setLoadableSection(section->isLoadableSection());
-
- // Get the segment type for the section
- int64_t segmentType = getSegmentType(section);
-
- osi->setHasSegment();
- section->setSegmentType(segmentType);
- StringRef segmentName = section->segmentKindToStr();
-
- int64_t lookupSectionFlag = osi->flags();
- if ((!(lookupSectionFlag & llvm::ELF::SHF_WRITE)) &&
- (_context.mergeRODataToTextSegment()))
- lookupSectionFlag &= ~llvm::ELF::SHF_EXECINSTR;
-
- // Merge string sections into Data segment itself
- lookupSectionFlag &= ~(llvm::ELF::SHF_STRINGS | llvm::ELF::SHF_MERGE);
-
- // Merge the TLS section into the DATA segment itself
- lookupSectionFlag &= ~(llvm::ELF::SHF_TLS);
-
- Segment<ELFT> *segment;
- // We need a separate segment for sections that don't have
- // the segment type to be PT_LOAD
- if (segmentType != llvm::ELF::PT_LOAD) {
- const AdditionalSegmentKey key(segmentType, lookupSectionFlag);
- const std::pair<AdditionalSegmentKey, Segment<ELFT> *>
- additionalSegment(key, nullptr);
- std::pair<typename AdditionalSegmentMapT::iterator, bool>
- additionalSegmentInsert(
- _additionalSegmentMap.insert(additionalSegment));
- if (!additionalSegmentInsert.second) {
- segment = additionalSegmentInsert.first->second;
- } else {
- segment = new (_allocator)
- Segment<ELFT>(_context, segmentName, segmentType);
- additionalSegmentInsert.first->second = segment;
- _segments.push_back(segment);
- }
- segment->append(section);
- }
- if (segmentType == llvm::ELF::PT_NULL)
- continue;
-
- // If the output magic is set to OutputMagic::NMAGIC or
- // OutputMagic::OMAGIC, Place the data alongside text in one single
- // segment
- if (outputMagic == ELFLinkingContext::OutputMagic::NMAGIC ||
- outputMagic == ELFLinkingContext::OutputMagic::OMAGIC)
- lookupSectionFlag = llvm::ELF::SHF_EXECINSTR | llvm::ELF::SHF_ALLOC |
- llvm::ELF::SHF_WRITE;
-
- // Use the flags of the merged Section for the segment
- const SegmentKey key("PT_LOAD", lookupSectionFlag);
- const std::pair<SegmentKey, Segment<ELFT> *> currentSegment(key,
- nullptr);
- std::pair<typename SegmentMapT::iterator, bool> segmentInsert(
- _segmentMap.insert(currentSegment));
- if (!segmentInsert.second) {
- segment = segmentInsert.first->second;
- } else {
- segment = new (_allocator)
- Segment<ELFT>(_context, "PT_LOAD", llvm::ELF::PT_LOAD);
- segmentInsert.first->second = segment;
- _segments.push_back(segment);
- }
- // 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);
- }
- }
- }
- if (_context.isDynamic() && !_context.isDynamicLibrary()) {
- Segment<ELFT> *segment =
- new (_allocator) ProgramHeaderSegment<ELFT>(_context);
- _segments.push_back(segment);
- segment->append(_elfHeader);
- segment->append(_programHeader);
- }
-}
-
-template<class ELFT>
-void
-DefaultLayout<ELFT>::assignVirtualAddress() {
- if (_segments.empty())
- return;
-
- std::sort(_segments.begin(), _segments.end(), Segment<ELFT>::compareSegments);
-
- uint64_t baseAddress = _context.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 && DefaultLayout<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 DefaultLayout<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 && DefaultLayout<ELFT>::hasOutputSegment(section))
- continue;
- fileoffset = llvm::RoundUpToAlignment(fileoffset, si->alignment());
- si->setFileOffset(fileoffset);
- si->setVirtualAddr(0);
- fileoffset += si->fileSize();
- }
-}
-
-template <class ELFT> void DefaultLayout<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>
-void DefaultLayout<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->_context, expr);
- segment->append(expChunk);
- }
-}
-
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/DefaultTargetHandler.h b/lib/ReaderWriter/ELF/DefaultTargetHandler.h
deleted file mode 100644
index 16668f2df618..000000000000
--- a/lib/ReaderWriter/ELF/DefaultTargetHandler.h
+++ /dev/null
@@ -1,38 +0,0 @@
-//===- lib/ReaderWriter/ELF/DefaultTargetHandler.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_TARGET_HANDLER_H
-#define LLD_READER_WRITER_ELF_DEFAULT_TARGET_HANDLER_H
-
-#include "DefaultLayout.h"
-#include "DynamicLibraryWriter.h"
-#include "ELFReader.h"
-#include "ExecutableWriter.h"
-#include "TargetHandler.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/ADT/Triple.h"
-#include "llvm/Support/ELF.h"
-
-namespace lld {
-namespace elf {
-template <class ELFT>
-class DefaultTargetHandler : public TargetHandler<ELFT> {
-public:
- const TargetRelocationHandler &getRelocationHandler() const = 0;
-
- virtual std::unique_ptr<Reader> getObjReader() = 0;
-
- virtual std::unique_ptr<Reader> getDSOReader() = 0;
-
- virtual std::unique_ptr<Writer> getWriter() = 0;
-};
-
-} // end namespace elf
-} // end namespace lld
-#endif
diff --git a/lib/ReaderWriter/ELF/DynamicFile.cpp b/lib/ReaderWriter/ELF/DynamicFile.cpp
new file mode 100644
index 000000000000..5339c7d66577
--- /dev/null
+++ b/lib/ReaderWriter/ELF/DynamicFile.cpp
@@ -0,0 +1,146 @@
+//===- 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
index c4e3e7165efd..a155900de781 100644
--- a/lib/ReaderWriter/ELF/DynamicFile.h
+++ b/lib/ReaderWriter/ELF/DynamicFile.h
@@ -12,96 +12,39 @@
#include "Atoms.h"
#include "lld/Core/SharedLibraryFile.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/Object/ELF.h"
-#include "llvm/Support/Path.h"
#include <unordered_map>
namespace lld {
+class ELFLinkingContext;
+
namespace elf {
+
template <class ELFT> class DynamicFile : public SharedLibraryFile {
public:
- static ErrorOr<std::unique_ptr<DynamicFile>>
- create(std::unique_ptr<llvm::MemoryBuffer> mb, ELFLinkingContext &ctx);
-
- const SharedLibraryAtom *exports(StringRef name,
- bool dataSymbolOnly) const override {
- 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);
- }
-
- StringRef getDSOName() const override { return _soname; }
-
-protected:
- std::error_code doParse() override {
- std::error_code ec;
- _objFile.reset(
- new llvm::object::ELFFile<ELFT>(_mb->getBuffer(), ec));
- if (ec)
- return ec;
-
- llvm::object::ELFFile<ELFT> &obj = *_objFile;
+ DynamicFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx);
- _soname = obj.getLoadName();
- if (_soname.empty())
- _soname = llvm::sys::path::filename(path());
+ static std::error_code isCompatible(MemoryBufferRef mb,
+ ELFLinkingContext &ctx);
- // 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.begin_dynamic_symbols(), e = obj.end_dynamic_symbols();
- i != e; ++i) {
- auto name = obj.getSymbolName(i);
- if ((ec = name.getError()))
- return ec;
+ const SharedLibraryAtom *exports(StringRef name,
+ bool dataSymbolOnly) const override;
- // 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;
+ StringRef getDSOName() const override;
- // TODO: Add absolute symbols
- if (i->st_shndx == llvm::ELF::SHN_ABS)
- continue;
+ static bool canParse(file_magic magic);
- 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._atoms.push_back(newAtom);
- }
- continue;
- }
- _nameToSym[*name]._symbol = &*i;
- }
- return std::error_code();
- }
+protected:
+ std::error_code doParse() override;
private:
- DynamicFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx)
- : SharedLibraryFile(mb->getBufferIdentifier()), _mb(std::move(mb)),
- _ctx(ctx), _useShlibUndefines(ctx.useShlibUndefines()) {}
-
mutable llvm::BumpPtrAllocator _alloc;
std::unique_ptr<llvm::object::ELFFile<ELFT>> _objFile;
/// \brief DT_SONAME
StringRef _soname;
struct SymAtomPair {
- SymAtomPair() : _symbol(nullptr), _atom(nullptr) {}
- const typename llvm::object::ELFFile<ELFT>::Elf_Sym *_symbol;
- const SharedLibraryAtom *_atom;
+ const typename llvm::object::ELFFile<ELFT>::Elf_Sym *_symbol = nullptr;
+ const SharedLibraryAtom *_atom = nullptr;
};
std::unique_ptr<MemoryBuffer> _mb;
@@ -110,13 +53,6 @@ private:
mutable std::unordered_map<StringRef, SymAtomPair> _nameToSym;
};
-template <class ELFT>
-ErrorOr<std::unique_ptr<DynamicFile<ELFT>>>
-DynamicFile<ELFT>::create(std::unique_ptr<llvm::MemoryBuffer> mb,
- ELFLinkingContext &ctx) {
- return std::unique_ptr<DynamicFile>(new DynamicFile(std::move(mb), ctx));
-}
-
} // end namespace elf
} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/DynamicLibraryWriter.h b/lib/ReaderWriter/ELF/DynamicLibraryWriter.h
index f97514b525c0..5f2c1d1a8288 100644
--- a/lib/ReaderWriter/ELF/DynamicLibraryWriter.h
+++ b/lib/ReaderWriter/ELF/DynamicLibraryWriter.h
@@ -16,27 +16,19 @@ namespace elf {
using namespace llvm;
using namespace llvm::object;
-template<class ELFT>
-class DynamicLibraryWriter;
-
//===----------------------------------------------------------------------===//
// DynamicLibraryWriter Class
//===----------------------------------------------------------------------===//
template<class ELFT>
class DynamicLibraryWriter : public OutputELFWriter<ELFT> {
public:
- DynamicLibraryWriter(ELFLinkingContext &context, TargetLayout<ELFT> &layout)
- : OutputELFWriter<ELFT>(context, layout),
- _runtimeFile(new RuntimeFile<ELFT>(context, "C runtime")) {}
-
-protected:
- virtual void buildDynamicSymbolTable(const File &file);
- virtual void addDefaultAtoms();
- virtual bool createImplicitFiles(std::vector<std::unique_ptr<File> > &);
- virtual void finalizeDefaultAtomValues();
+ DynamicLibraryWriter(ELFLinkingContext &ctx, TargetLayout<ELFT> &layout)
+ : OutputELFWriter<ELFT>(ctx, layout) {}
protected:
- std::unique_ptr<RuntimeFile<ELFT> > _runtimeFile;
+ void buildDynamicSymbolTable(const File &file) override;
+ void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
+ void finalizeDefaultAtomValues() override;
};
//===----------------------------------------------------------------------===//
@@ -62,30 +54,28 @@ void DynamicLibraryWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
OutputELFWriter<ELFT>::buildDynamicSymbolTable(file);
}
-template <class ELFT> void DynamicLibraryWriter<ELFT>::addDefaultAtoms() {
- _runtimeFile->addAbsoluteAtom("_end");
-}
-
/// \brief Hook in lld to add CRuntime file
template <class ELFT>
-bool DynamicLibraryWriter<ELFT>::createImplicitFiles(
+void DynamicLibraryWriter<ELFT>::createImplicitFiles(
std::vector<std::unique_ptr<File> > &result) {
- // Add the default atoms as defined by executables
- DynamicLibraryWriter<ELFT>::addDefaultAtoms();
OutputELFWriter<ELFT>::createImplicitFiles(result);
- result.push_back(std::move(_runtimeFile));
- return true;
+ // 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() {
- auto underScoreEndAtomIter = this->_layout.findAbsoluteAtom("_end");
+ OutputELFWriter<ELFT>::finalizeDefaultAtomValues();
+ AtomLayout *underScoreEndAtom = this->_layout.findAbsoluteAtom("_end");
+ assert(underScoreEndAtom);
if (auto bssSection = this->_layout.findOutputSection(".bss")) {
- (*underScoreEndAtomIter)->_virtualAddr =
+ underScoreEndAtom->_virtualAddr =
bssSection->virtualAddr() + bssSection->memSize();
} else if (auto dataSection = this->_layout.findOutputSection(".data")) {
- (*underScoreEndAtomIter)->_virtualAddr =
+ underScoreEndAtom->_virtualAddr =
dataSection->virtualAddr() + dataSection->memSize();
}
}
diff --git a/lib/ReaderWriter/ELF/ELFFile.cpp b/lib/ReaderWriter/ELF/ELFFile.cpp
new file mode 100644
index 000000000000..1488f1862b8d
--- /dev/null
+++ b/lib/ReaderWriter/ELF/ELFFile.cpp
@@ -0,0 +1,829 @@
+//===- 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
index 11f4ee4fc633..5e0c2fc75a87 100644
--- a/lib/ReaderWriter/ELF/ELFFile.h
+++ b/lib/ReaderWriter/ELF/ELFFile.h
@@ -1,4 +1,4 @@
-//===- lib/ReaderWriter/ELF/ELFFile.h -------------------------------------===//
+//===- lib/ReaderWriter/ELF/ELFFile.h ---------------------------*- C++ -*-===//
//
// The LLVM Linker
//
@@ -11,7 +11,8 @@
#define LLD_READER_WRITER_ELF_FILE_H
#include "Atoms.h"
-#include <llvm/ADT/MapVector.h>
+#include "FileCommon.h"
+#include "llvm/ADT/MapVector.h"
#include <map>
#include <unordered_map>
@@ -20,26 +21,20 @@ 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 File {
-
+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_Sym_Iter Elf_Sym_Iter;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela_Iter Elf_Rela_Iter;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel_Iter Elf_Rel_Iter;
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 {
- MergeSectionKey(const Elf_Shdr *shdr, int64_t offset)
- : _shdr(shdr), _offset(offset) {}
- // Data members
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),
@@ -71,23 +66,15 @@ template <class ELFT> class ELFFile : public File {
// offset
typedef std::vector<ELFMergeAtom<ELFT> *> MergeAtomsT;
- /// \brief find a mergeAtom given a start offset
- struct FindByOffset {
- const Elf_Shdr *_shdr;
- int64_t _offset;
- FindByOffset(const Elf_Shdr *shdr, int64_t offset)
- : _shdr(shdr), _offset(offset) {}
- bool operator()(const ELFMergeAtom<ELFT> *a) {
- int64_t off = a->offset();
- return (_shdr->sh_name == a->section()) &&
- ((_offset >= off) && (_offset <= off + (int64_t)a->size()));
- }
- };
-
/// \brief find a merge atom given a offset
- ELFMergeAtom<ELFT> *findMergeAtom(const Elf_Shdr *shdr, uint64_t offset) {
+ ELFMergeAtom<ELFT> *findMergeAtom(const Elf_Shdr *shdr, int64_t offset) {
auto it = std::find_if(_mergeAtoms.begin(), _mergeAtoms.end(),
- FindByOffset(shdr, offset));
+ [=](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;
}
@@ -97,19 +84,15 @@ template <class ELFT> class ELFFile : public File {
typedef typename MergedSectionMapT::iterator MergedSectionMapIterT;
public:
- ELFFile(StringRef name, ELFLinkingContext &ctx)
- : File(name, kindObject), _ordinal(0),
- _doStringsMerge(ctx.mergeCommonStrings()), _useWrap(false), _ctx(ctx) {
- setLastError(std::error_code());
- }
+ ELFFile(StringRef name, ELFLinkingContext &ctx);
+ ELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx);
- ELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx)
- : File(mb->getBufferIdentifier(), kindObject), _mb(std::move(mb)),
- _ordinal(0), _doStringsMerge(ctx.mergeCommonStrings()),
- _useWrap(ctx.wrapCalls().size()), _ctx(ctx) {}
+ static std::error_code isCompatible(MemoryBufferRef mb,
+ ELFLinkingContext &ctx);
- static ErrorOr<std::unique_ptr<ELFFile>>
- create(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx);
+ static bool canParse(file_magic magic) {
+ return magic == file_magic::elf_relocatable;
+ }
virtual Reference::KindArch kindArch();
@@ -132,41 +115,14 @@ public:
/// \brief Create individual atoms
std::error_code createAtoms();
- const atom_collection<DefinedAtom> &defined() const override {
- return _definedAtoms;
- }
-
- const atom_collection<UndefinedAtom> &undefined() const override {
- return _undefinedAtoms;
- }
-
- const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
- return _sharedLibraryAtoms;
- }
-
- const atom_collection<AbsoluteAtom> &absolute() const override {
- return _absoluteAtoms;
- }
-
- Atom *findAtom(const Elf_Sym *sourceSymbol, const Elf_Sym *targetSymbol) {
- // All references to atoms inside a group are through undefined atoms.
- Atom *targetAtom = _symbolToAtomMapping.lookup(targetSymbol);
- StringRef targetSymbolName = targetAtom->name();
- if (targetAtom->definition() != Atom::definitionRegular)
- return targetAtom;
- if ((llvm::dyn_cast<DefinedAtom>(targetAtom))->scope() ==
- DefinedAtom::scopeTranslationUnit)
- return targetAtom;
- if (!redirectReferenceUsingUndefAtom(sourceSymbol, targetSymbol))
- return targetAtom;
- auto undefForGroupchild = _undefAtomsForGroupChild.find(targetSymbolName);
- if (undefForGroupchild != _undefAtomsForGroupChild.end())
- return undefForGroupchild->getValue();
- auto undefGroupChildAtom =
- new (_readerStorage) SimpleUndefinedAtom(*this, targetSymbolName);
- _undefinedAtoms._atoms.push_back(undefGroupChildAtom);
- return (_undefAtomsForGroupChild[targetSymbolName] = undefGroupChildAtom);
- }
+ // 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(
@@ -179,13 +135,13 @@ protected:
/// \brief Iterate over Elf_Rela relocations list and create references.
virtual void createRelocationReferences(const Elf_Sym *symbol,
ArrayRef<uint8_t> content,
- range<Elf_Rela_Iter> rels);
+ 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,
- range<Elf_Rel_Iter> rels);
+ 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.
@@ -224,11 +180,7 @@ protected:
uint32_t edgeKind);
/// Get the section name for a section.
- ErrorOr<StringRef> getSectionName(const Elf_Shdr *shdr) const {
- if (!shdr)
- return StringRef();
- return _objFile->getSectionName(shdr);
- }
+ ErrorOr<StringRef> getSectionName(const Elf_Shdr *shdr) const;
/// Determines if the section occupy memory space.
bool sectionOccupiesMemorySpace(const Elf_Shdr *shdr) const {
@@ -242,45 +194,38 @@ protected:
return _objFile->getSectionContents(shdr);
}
- /// Returns true if the symbol is a undefined symbol.
- bool isUndefinedSymbol(const Elf_Sym *sym) const {
- return (sym->st_shndx == llvm::ELF::SHN_UNDEF);
- }
-
/// 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<Elf_Sym_Iter> &syms) const {
- return shdr && (shdr->sh_type == llvm::ELF::SHT_PROGBITS) && syms.empty();
+ 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(
- StringRef sectionName,
- llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> &atomsForSection,
- const Elf_Shdr *shdr);
+ const Elf_Shdr *section,
+ llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> &atomsForSection);
- // Handle Section groups/COMDAT scetions.
+ // Handle COMDAT scetions.
std::error_code handleSectionGroup(
- StringRef signature, StringRef groupSectionName,
- llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> &atomsForSection,
- llvm::DenseMap<const Elf_Shdr *, std::vector<StringRef>> &comdatSections,
- const Elf_Shdr *shdr);
+ const Elf_Shdr *section,
+ llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> &atomsForSection);
/// Process the Undefined symbol and create an atom for it.
- ErrorOr<ELFUndefinedAtom<ELFT> *>
- handleUndefinedSymbol(StringRef symName, const Elf_Sym *sym) {
+ ELFUndefinedAtom<ELFT> *createUndefinedAtom(StringRef symName,
+ const Elf_Sym *sym) {
return new (_readerStorage) ELFUndefinedAtom<ELFT>(*this, symName, sym);
}
- /// Returns true if the symbol is a absolute symbol.
- bool isAbsoluteSymbol(const Elf_Sym *sym) const {
- return (sym->st_shndx == llvm::ELF::SHN_ABS);
- }
-
/// Process the Absolute symbol and create an atom for it.
- ErrorOr<ELFAbsoluteAtom<ELFT> *>
- handleAbsoluteSymbol(StringRef symName, const Elf_Sym *sym, int64_t value) {
+ ELFAbsoluteAtom<ELFT> *createAbsoluteAtom(StringRef symName,
+ const Elf_Sym *sym, int64_t value) {
return new (_readerStorage)
ELFAbsoluteAtom<ELFT>(*this, symName, sym, value);
}
@@ -316,42 +261,39 @@ protected:
return symbol->st_value;
}
- /// Process the common symbol and create an atom for it.
- virtual ErrorOr<ELFCommonAtom<ELFT> *>
- handleCommonSymbol(StringRef symName, const Elf_Sym *sym) {
- return new (_readerStorage) ELFCommonAtom<ELFT>(*this, symName, sym);
+ /// 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);
}
- /// Returns true if the symbol is a defined symbol.
- virtual bool isDefinedSymbol(const Elf_Sym *sym) const {
- return (sym->getType() == llvm::ELF::STT_NOTYPE ||
- sym->getType() == llvm::ELF::STT_OBJECT ||
- sym->getType() == llvm::ELF::STT_FUNC ||
- sym->getType() == llvm::ELF::STT_GNU_IFUNC ||
- sym->getType() == llvm::ELF::STT_SECTION ||
- sym->getType() == llvm::ELF::STT_FILE ||
- sym->getType() == llvm::ELF::STT_TLS);
+ /// 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);
}
- /// Process the Defined symbol and create an atom for it.
- virtual ErrorOr<ELFDefinedAtom<ELFT> *>
- handleDefinedSymbol(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) {
+ /// 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.
- ErrorOr<ELFMergeAtom<ELFT> *>
- handleMergeString(StringRef sectionName, const Elf_Shdr *sectionHdr,
- ArrayRef<uint8_t> contentData, unsigned int offset) {
- ELFMergeAtom<ELFT> *mergeAtom = new (_readerStorage)
+ 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);
+ const MergeSectionKey mergedSectionKey = {sectionHdr, offset};
if (_mergedSectionMap.find(mergedSectionKey) == _mergedSectionMap.end())
_mergedSectionMap.insert(std::make_pair(mergedSectionKey, mergeAtom));
return mergeAtom;
@@ -380,19 +322,17 @@ protected:
llvm::BumpPtrAllocator _readerStorage;
std::unique_ptr<llvm::object::ELFFile<ELFT> > _objFile;
- atom_collection_vector<DefinedAtom> _definedAtoms;
- atom_collection_vector<UndefinedAtom> _undefinedAtoms;
- atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
- atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
+ 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<StringRef, range<Elf_Rela_Iter>>
- _relocationAddendReferences;
+ std::unordered_map<const Elf_Shdr *, range<const Elf_Rela *>>
+ _relocationAddendReferences;
MergedSectionMapT _mergedSectionMap;
- std::unordered_map<StringRef, range<Elf_Rel_Iter>> _relocationReferences;
+ 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 *>
@@ -409,7 +349,8 @@ protected:
/// \brief the section and the symbols that are contained within it to create
/// used to create atoms
- llvm::MapVector<const Elf_Shdr *, std::vector<Elf_Sym_Iter>> _sectionSymbols;
+ llvm::MapVector<const Elf_Shdr *, std::vector<const Elf_Sym *>>
+ _sectionSymbols;
/// \brief Sections that have merge string property
std::vector<const Elf_Shdr *> _mergeStringSections;
@@ -438,741 +379,16 @@ protected:
template <class ELFT> class RuntimeFile : public ELFFile<ELFT> {
public:
typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
- RuntimeFile(ELFLinkingContext &context, StringRef name)
- : ELFFile<ELFT>(name, context) {}
+ RuntimeFile(ELFLinkingContext &ctx, StringRef name)
+ : ELFFile<ELFT>(name, ctx) {}
/// \brief add a global absolute atom
- virtual Atom *addAbsoluteAtom(StringRef symbolName) {
- assert(!symbolName.empty() && "AbsoluteAtoms must have a name");
- Elf_Sym *symbol = new (this->_readerStorage) Elf_Sym;
- symbol->st_name = 0;
- symbol->st_value = 0;
- symbol->st_shndx = llvm::ELF::SHN_ABS;
- symbol->setBindingAndType(llvm::ELF::STB_GLOBAL, llvm::ELF::STT_OBJECT);
- symbol->setVisibility(llvm::ELF::STV_DEFAULT);
- symbol->st_size = 0;
- auto newAtom = this->handleAbsoluteSymbol(symbolName, symbol, -1);
- this->_absoluteAtoms._atoms.push_back(*newAtom);
- return *newAtom;
- }
+ virtual void addAbsoluteAtom(StringRef symbolName, bool isHidden = false);
/// \brief add an undefined atom
- virtual Atom *addUndefinedAtom(StringRef symbolName) {
- assert(!symbolName.empty() && "UndefinedAtoms must have a name");
- Elf_Sym *symbol = new (this->_readerStorage) Elf_Sym;
- symbol->st_name = 0;
- symbol->st_value = 0;
- symbol->st_shndx = llvm::ELF::SHN_UNDEF;
- symbol->setBindingAndType(llvm::ELF::STB_GLOBAL, llvm::ELF::STT_NOTYPE);
- symbol->setVisibility(llvm::ELF::STV_DEFAULT);
- symbol->st_size = 0;
- auto newAtom = this->handleUndefinedSymbol(symbolName, symbol);
- this->_undefinedAtoms._atoms.push_back(*newAtom);
- return *newAtom;
- }
-
- // cannot add atoms to Runtime file
- virtual void addAtom(const Atom &) {
- llvm_unreachable("cannot add atoms to Runtime files");
- }
+ virtual void addUndefinedAtom(StringRef symbolName);
};
-template <class ELFT>
-ErrorOr<std::unique_ptr<ELFFile<ELFT>>>
-ELFFile<ELFT>::create(std::unique_ptr<MemoryBuffer> mb,
- ELFLinkingContext &ctx) {
- std::unique_ptr<ELFFile<ELFT>> file(new ELFFile<ELFT>(std::move(mb), ctx));
- return std::move(file);
-}
-
-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()) {
- if (isIgnoredSection(&section))
- continue;
-
- if (isMergeableStringSection(&section)) {
- _mergeStringSections.push_back(&section);
- continue;
- }
-
- if (section.sh_type == llvm::ELF::SHT_RELA) {
- auto sHdr = _objFile->getSection(section.sh_info);
-
- auto sectionName = _objFile->getSectionName(sHdr);
- if (std::error_code ec = sectionName.getError())
- return ec;
-
- auto rai(_objFile->begin_rela(&section));
- auto rae(_objFile->end_rela(&section));
-
- _relocationAddendReferences[*sectionName] = make_range(rai, rae);
- totalRelocs += std::distance(rai, rae);
- } else if (section.sh_type == llvm::ELF::SHT_REL) {
- auto sHdr = _objFile->getSection(section.sh_info);
-
- auto sectionName = _objFile->getSectionName(sHdr);
- if (std::error_code ec = sectionName.getError())
- return ec;
-
- auto ri(_objFile->begin_rel(&section));
- auto re(_objFile->end_rel(&section));
-
- _relocationReferences[*sectionName] = make_range(ri, re);
- totalRelocs += std::distance(ri, re);
- } else {
- _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());
- ErrorOr<ELFMergeAtom<ELFT> *> mergeAtom =
- handleMergeString(tai->_sectionName, tai->_shdr, content, tai->_offset);
- (*mergeAtom)->setOrdinal(++_ordinal);
- _definedAtoms._atoms.push_back(*mergeAtom);
- _mergeAtoms.push_back(*mergeAtom);
- }
- 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.
- auto SymI = _objFile->begin_symbols(), SymE = _objFile->end_symbols();
-
- // Skip over dummy sym.
- if (SymI != SymE)
- ++SymI;
-
- for (; SymI != SymE; ++SymI) {
- const Elf_Shdr *section = _objFile->getSection(&*SymI);
-
- auto symbolName = _objFile->getSymbolName(SymI);
- if (std::error_code ec = symbolName.getError())
- return ec;
-
- if (isAbsoluteSymbol(&*SymI)) {
- ErrorOr<ELFAbsoluteAtom<ELFT> *> absAtom =
- handleAbsoluteSymbol(*symbolName, &*SymI, (int64_t)getSymbolValue(&*SymI));
- _absoluteAtoms._atoms.push_back(*absAtom);
- _symbolToAtomMapping.insert(std::make_pair(&*SymI, *absAtom));
- } else if (isUndefinedSymbol(&*SymI)) {
- if (_useWrap &&
- (_wrapSymbolMap.find(*symbolName) != _wrapSymbolMap.end())) {
- auto wrapAtom = _wrapSymbolMap.find(*symbolName);
- _symbolToAtomMapping.insert(
- std::make_pair(&*SymI, wrapAtom->getValue()));
- continue;
- }
- ErrorOr<ELFUndefinedAtom<ELFT> *> undefAtom =
- handleUndefinedSymbol(*symbolName, &*SymI);
- _undefinedAtoms._atoms.push_back(*undefAtom);
- _symbolToAtomMapping.insert(std::make_pair(&*SymI, *undefAtom));
- } else if (isCommonSymbol(&*SymI)) {
- ErrorOr<ELFCommonAtom<ELFT> *> commonAtom =
- handleCommonSymbol(*symbolName, &*SymI);
- (*commonAtom)->setOrdinal(++_ordinal);
- _definedAtoms._atoms.push_back(*commonAtom);
- _symbolToAtomMapping.insert(std::make_pair(&*SymI, *commonAtom));
- } else if (isDefinedSymbol(&*SymI)) {
- _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;
- // group sections have a mapping of the section header to the
- // signature/section.
- llvm::DenseMap<const Elf_Shdr *, std::pair<StringRef, StringRef>>
- groupSections;
- // Contains a list of comdat sections for a group.
- llvm::DenseMap<const Elf_Shdr *, std::vector<StringRef>> comdatSections;
- for (auto &i : _sectionSymbols) {
- const Elf_Shdr *section = i.first;
- std::vector<Elf_Sym_Iter> &symbols = i.second;
-
- // Sort symbols by position.
- std::stable_sort(symbols.begin(), symbols.end(),
- [this](Elf_Sym_Iter a, Elf_Sym_Iter 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;
-
- bool addAtoms = true;
-
- // 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.
- if (isGroupSection(section)) {
- const Elf_Word *groupMembers =
- reinterpret_cast<const Elf_Word *>(sectionContents->data());
- const long count = (section->sh_size) / sizeof(Elf_Word);
- for (int i = 1; i < count; i++) {
- const Elf_Shdr *sHdr = _objFile->getSection(groupMembers[i]);
- ErrorOr<StringRef> sectionName = _objFile->getSectionName(sHdr);
- if (std::error_code ec = sectionName.getError())
- return ec;
- comdatSections[section].push_back(*sectionName);
- }
- const Elf_Sym *symbol = _objFile->getSymbol(section->sh_info);
- const Elf_Shdr *symtab = _objFile->getSection(section->sh_link);
- ErrorOr<StringRef> symbolName = _objFile->getSymbolName(symtab, symbol);
- if (std::error_code ec = symbolName.getError())
- return ec;
- groupSections.insert(
- std::make_pair(section, std::make_pair(*symbolName, *sectionName)));
- continue;
- }
-
- if (isGnuLinkOnceSection(*sectionName)) {
- groupSections.insert(
- std::make_pair(section, std::make_pair(*sectionName, *sectionName)));
- addAtoms = false;
- }
-
- if (isSectionMemberOfGroup(section))
- addAtoms = false;
-
- if (handleSectionWithNoSymbols(section, symbols)) {
- ELFDefinedAtom<ELFT> *newAtom =
- createSectionAtom(section, *sectionName, *sectionContents);
- newAtom->setOrdinal(++_ordinal);
- if (addAtoms)
- _definedAtoms._atoms.push_back(newAtom);
- else
- atomsForSection[*sectionName].push_back(newAtom);
- continue;
- }
-
- ELFDefinedAtom<ELFT> *previousAtom = nullptr;
- ELFReference<ELFT> *anonFollowedBy = nullptr;
-
- 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 = _objFile->getSymbolName(symbol);
- 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>(lld::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) {
- auto definedMergeAtom = handleDefinedSymbol(
- symbolName, *sectionName, &**si, section, symbolData,
- _references.size(), _references.size(), _references);
- (*definedMergeAtom)->setOrdinal(++_ordinal);
- if (addAtoms)
- _definedAtoms._atoms.push_back(*definedMergeAtom);
- else
- atomsForSection[*sectionName].push_back(*definedMergeAtom);
- }
- 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>(lld::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)
- _definedAtoms._atoms.push_back(newAtom);
- else
- atomsForSection[*sectionName].push_back(newAtom);
-
- _symbolToAtomMapping.insert(std::make_pair(&*symbol, newAtom));
- if (anonAtom) {
- anonAtom->setOrdinal(++_ordinal);
- if (addAtoms)
- _definedAtoms._atoms.push_back(anonAtom);
- else
- atomsForSection[*sectionName].push_back(anonAtom);
- }
- }
- }
-
- // Iterate over all the group sections to create parent atoms pointing to
- // group-child atoms.
- for (auto &sect : groupSections) {
- StringRef signature = sect.second.first;
- StringRef groupSectionName = sect.second.second;
- if (isGnuLinkOnceSection(signature))
- handleGnuLinkOnceSection(signature, atomsForSection, sect.first);
- else if (isGroupSection(sect.first))
- handleSectionGroup(signature, groupSectionName, atomsForSection,
- comdatSections, sect.first);
- }
-
- updateReferences();
- return std::error_code();
-}
-
-template <class ELFT>
-std::error_code ELFFile<ELFT>::handleGnuLinkOnceSection(
- StringRef signature,
- llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> &atomsForSection,
- const Elf_Shdr *shdr) {
- // TODO: Check for errors.
- unsigned int referenceStart = _references.size();
- std::vector<ELFReference<ELFT> *> refs;
- for (auto ha : atomsForSection[signature]) {
- _groupChild[ha->symbol()] = std::make_pair(signature, shdr);
- ELFReference<ELFT> *ref =
- new (_readerStorage) ELFReference<ELFT>(lld::Reference::kindGroupChild);
- ref->setTarget(ha);
- refs.push_back(ref);
- }
- atomsForSection[signature].clear();
- // Create a gnu linkonce atom.
- auto gnuLinkOnceAtom = handleDefinedSymbol(
- signature, signature, nullptr, shdr, ArrayRef<uint8_t>(), referenceStart,
- _references.size(), _references);
- (*gnuLinkOnceAtom)->setOrdinal(++_ordinal);
- _definedAtoms._atoms.push_back(*gnuLinkOnceAtom);
- for (auto reference : refs)
- (*gnuLinkOnceAtom)->addReference(reference);
- return std::error_code();
-}
-
-template <class ELFT>
-std::error_code ELFFile<ELFT>::handleSectionGroup(
- StringRef signature, StringRef groupSectionName,
- llvm::StringMap<std::vector<ELFDefinedAtom<ELFT> *>> &atomsForSection,
- llvm::DenseMap<const Elf_Shdr *, std::vector<StringRef>> &comdatSections,
- const Elf_Shdr *shdr) {
- // TODO: Check for errors.
- unsigned int referenceStart = _references.size();
- std::vector<ELFReference<ELFT> *> refs;
- auto sectionNamesInGroup = comdatSections[shdr];
- for (auto sectionName : sectionNamesInGroup) {
- for (auto ha : atomsForSection[sectionName]) {
- _groupChild[ha->symbol()] = std::make_pair(signature, shdr);
- ELFReference<ELFT> *ref = new (_readerStorage)
- ELFReference<ELFT>(lld::Reference::kindGroupChild);
- ref->setTarget(ha);
- refs.push_back(ref);
- }
- atomsForSection[sectionName].clear();
- }
- // Create a gnu linkonce atom.
- auto sectionGroupAtom = handleDefinedSymbol(
- signature, groupSectionName, nullptr, shdr, ArrayRef<uint8_t>(),
- referenceStart, _references.size(), _references);
- (*sectionGroupAtom)->setOrdinal(++_ordinal);
- _definedAtoms._atoms.push_back(*sectionGroupAtom);
- for (auto reference : refs)
- (*sectionGroupAtom)->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));
- _undefinedAtoms._atoms.push_back(wrapSymAtom);
- _undefinedAtoms._atoms.push_back(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(sectionName);
- if (rari != _relocationAddendReferences.end())
- createRelocationReferences(symbol, symContent, rari->second);
-
- // Add Rel references.
- auto rri = _relocationReferences.find(sectionName);
- if (rri != _relocationReferences.end())
- createRelocationReferences(symbol, symContent, secContent, rri->second);
-
- // Create the DefinedAtom and add it to the list of DefinedAtoms.
- return *handleDefinedSymbol(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<Elf_Rela_Iter> 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,
- range<Elf_Rel_Iter> rels) {
- 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));
- int32_t addend = *(symContent.data() + rel.r_offset - symValue);
- 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() != lld::Reference::KindNamespace::ELF)
- continue;
- const Elf_Sym *symbol = _objFile->getSymbol(ri->targetSymbolIndex());
- const Elf_Shdr *shdr = _objFile->getSection(symbol);
-
- // 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) {
- Elf_Sym *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;
-}
-
} // end namespace elf
} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/ELFLinkingContext.cpp b/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
index c7dffda8a463..2904c7b0dae0 100644
--- a/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
+++ b/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
@@ -25,6 +25,9 @@
#include <cxxabi.h>
#endif
+using llvm::sys::fs::exists;
+using llvm::sys::path::is_absolute;
+
namespace lld {
class CommandLineUndefinedAtom : public SimpleUndefinedAtom {
@@ -37,18 +40,6 @@ public:
}
};
-ELFLinkingContext::ELFLinkingContext(
- llvm::Triple triple, std::unique_ptr<TargetHandlerBase> targetHandler)
- : _outputELFType(llvm::ELF::ET_EXEC), _triple(triple),
- _targetHandler(std::move(targetHandler)), _baseAddress(0),
- _isStaticExecutable(false), _noInhibitExec(false), _exportDynamic(false),
- _mergeCommonStrings(false), _useShlibUndefines(true),
- _dynamicLinkerArg(false), _noAllowDynamicLibraries(false),
- _mergeRODataToTextSegment(true), _demangle(true),
- _stripSymbols(false), _alignSegments(true), _collectStats(false),
- _outputMagic(OutputMagic::DEFAULT), _initFunction("_init"),
- _finiFunction("_fini"), _sysrootPath(""), _linkerScriptSema() {}
-
void ELFLinkingContext::addPasses(PassManager &pm) {
pm.add(llvm::make_unique<elf::OrderPass>());
}
@@ -61,13 +52,17 @@ uint16_t ELFLinkingContext::getOutputMachine() const {
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;
+ case llvm::Triple::amdgcn:
+ return llvm::ELF::EM_AMDGPU;
default:
llvm_unreachable("Unhandled arch");
}
@@ -84,11 +79,8 @@ bool ELFLinkingContext::validateImpl(raw_ostream &diagnostics) {
case LinkingContext::OutputFileType::YAML:
_writer = createWriterYAML(*this);
break;
- case LinkingContext::OutputFileType::Native:
- llvm_unreachable("Unimplemented");
- break;
default:
- _writer = createWriterELF(this->targetHandler());
+ _writer = createWriterELF(*this);
break;
}
@@ -116,11 +108,13 @@ Writer &ELFLinkingContext::writer() const { return *_writer; }
static void buildSearchPath(SmallString<128> &path, StringRef dir,
StringRef sysRoot) {
- if (!dir.startswith("=/"))
- path.assign(dir);
- else {
+ 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);
}
}
@@ -134,18 +128,18 @@ ErrorOr<StringRef> ELFLinkingContext::searchLibrary(StringRef libName) const {
llvm::sys::path::append(path, hasColonPrefix
? libName.drop_front()
: Twine("lib", libName) + ".so");
- if (llvm::sys::fs::exists(path.str()))
- return StringRef(*new (_allocator) std::string(path.str()));
+ 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 (llvm::sys::fs::exists(path.str()))
- return StringRef(*new (_allocator) std::string(path.str()));
+ if (exists(path.str()))
+ return path.str().copy(_allocator);
}
- if (hasColonPrefix && llvm::sys::fs::exists(libName.drop_front()))
+ if (hasColonPrefix && exists(libName.drop_front()))
return libName.drop_front();
return make_error_code(llvm::errc::no_such_file_or_directory);
@@ -154,22 +148,23 @@ ErrorOr<StringRef> ELFLinkingContext::searchLibrary(StringRef libName) const {
ErrorOr<StringRef> ELFLinkingContext::searchFile(StringRef fileName,
bool isSysRooted) const {
SmallString<128> path;
- if (llvm::sys::path::is_absolute(fileName) && isSysRooted) {
+ if (is_absolute(fileName) && isSysRooted) {
path.assign(_sysrootPath);
path.append(fileName);
- if (llvm::sys::fs::exists(path.str()))
- return StringRef(*new (_allocator) std::string(path.str()));
- } else if (llvm::sys::fs::exists(fileName))
+ if (exists(path.str()))
+ return path.str().copy(_allocator);
+ } else if (exists(fileName)) {
return fileName;
+ }
- if (llvm::sys::path::is_absolute(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 (llvm::sys::fs::exists(path.str()))
- return StringRef(*new (_allocator) std::string(path.str()));
+ if (exists(path.str()))
+ return path.str().copy(_allocator);
}
return make_error_code(llvm::errc::no_such_file_or_directory);
}
@@ -227,6 +222,7 @@ void ELFLinkingContext::notifySymbolTableCoalesce(const Atom *existingAtom,
}
std::string ELFLinkingContext::demangle(StringRef symbolName) const {
+#if defined(HAVE_CXXABI_H)
if (!demangleSymbols())
return symbolName;
@@ -234,21 +230,20 @@ std::string ELFLinkingContext::demangle(StringRef symbolName) const {
if (!symbolName.startswith("_Z"))
return symbolName;
-#if defined(HAVE_CXXABI_H)
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 != NULL) {
- std::string result(demangled);
- // __cxa_demangle() always uses a malloc'ed buffer to return the result.
- free(demangled);
- return result;
- }
-#endif
-
+ 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) {
@@ -256,4 +251,15 @@ void ELFLinkingContext::setUndefinesResolver(std::unique_ptr<File> resolver) {
_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
index 43f218115c66..60af6dff9980 100644
--- a/lib/ReaderWriter/ELF/ELFReader.h
+++ b/lib/ReaderWriter/ELF/ELFReader.h
@@ -10,90 +10,35 @@
#ifndef LLD_READER_WRITER_ELF_READER_H
#define LLD_READER_WRITER_ELF_READER_H
-#include "CreateELF.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 ELFT, typename ELFTraitsT, typename ContextT>
-class ELFObjectReader : public Reader {
+template <typename FileT> class ELFReader : public Reader {
public:
- typedef llvm::object::Elf_Ehdr_Impl<ELFT> Elf_Ehdr;
+ ELFReader(ELFLinkingContext &ctx) : _ctx(ctx) {}
- ELFObjectReader(ContextT &ctx, uint64_t machine)
- : _ctx(ctx), _machine(machine) {}
-
- bool canParse(file_magic magic, StringRef,
- const MemoryBuffer &buf) const override {
- return (magic == llvm::sys::fs::file_magic::elf_relocatable &&
- elfHeader(buf)->e_machine == _machine);
+ bool canParse(file_magic magic, MemoryBufferRef mb) const override {
+ return FileT::canParse(magic);
}
- std::error_code
- loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
- std::vector<std::unique_ptr<File>> &result) const override {
- std::size_t maxAlignment =
- 1ULL << llvm::countTrailingZeros(uintptr_t(mb->getBufferStart()));
- auto f =
- createELF<ELFTraitsT>(llvm::object::getElfArchType(mb->getBuffer()),
- maxAlignment, std::move(mb), _ctx);
- if (std::error_code ec = f.getError())
+ 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;
- result.push_back(std::move(*f));
- return std::error_code();
- }
-
- const Elf_Ehdr *elfHeader(const MemoryBuffer &buf) const {
- const uint8_t *data =
- reinterpret_cast<const uint8_t *>(buf.getBuffer().data());
- return (reinterpret_cast<const Elf_Ehdr *>(data));
- }
-
-protected:
- ContextT &_ctx;
- uint64_t _machine;
-};
-
-template <typename ELFT, typename ELFTraitsT, typename ContextT>
-class ELFDSOReader : public Reader {
-public:
- typedef llvm::object::Elf_Ehdr_Impl<ELFT> Elf_Ehdr;
-
- ELFDSOReader(ContextT &ctx, uint64_t machine)
- : _ctx(ctx), _machine(machine) {}
-
- bool canParse(file_magic magic, StringRef,
- const MemoryBuffer &buf) const override {
- return (magic == llvm::sys::fs::file_magic::elf_shared_object &&
- elfHeader(buf)->e_machine == _machine);
- }
-
- std::error_code
- loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
- std::vector<std::unique_ptr<File>> &result) const override {
- std::size_t maxAlignment =
- 1ULL << llvm::countTrailingZeros(uintptr_t(mb->getBufferStart()));
- auto f =
- createELF<ELFTraitsT>(llvm::object::getElfArchType(mb->getBuffer()),
- maxAlignment, std::move(mb), _ctx);
- if (std::error_code ec = f.getError())
- return ec;
- result.push_back(std::move(*f));
- return std::error_code();
- }
-
- const Elf_Ehdr *elfHeader(const MemoryBuffer &buf) const {
- const uint8_t *data =
- reinterpret_cast<const uint8_t *>(buf.getBuffer().data());
- return (reinterpret_cast<const Elf_Ehdr *>(data));
+ std::unique_ptr<File> ret = llvm::make_unique<FileT>(std::move(mb), _ctx);
+ return std::move(ret);
}
-protected:
- ContextT &_ctx;
- uint64_t _machine;
+private:
+ ELFLinkingContext &_ctx;
};
} // namespace elf
diff --git a/lib/ReaderWriter/ELF/ExecutableWriter.h b/lib/ReaderWriter/ELF/ExecutableWriter.h
index 477e3920abae..9d9f4d9ce0a5 100644
--- a/lib/ReaderWriter/ELF/ExecutableWriter.h
+++ b/lib/ReaderWriter/ELF/ExecutableWriter.h
@@ -16,32 +16,29 @@ namespace elf {
using namespace llvm;
using namespace llvm::object;
-template<class ELFT>
-class ExecutableWriter;
-
//===----------------------------------------------------------------------===//
// ExecutableWriter Class
//===----------------------------------------------------------------------===//
template<class ELFT>
class ExecutableWriter : public OutputELFWriter<ELFT> {
public:
- ExecutableWriter(ELFLinkingContext &context, TargetLayout<ELFT> &layout)
- : OutputELFWriter<ELFT>(context, layout),
- _runtimeFile(new RuntimeFile<ELFT>(context, "C runtime")) {}
+ ExecutableWriter(ELFLinkingContext &ctx, TargetLayout<ELFT> &layout)
+ : OutputELFWriter<ELFT>(ctx, layout) {}
protected:
- virtual void buildDynamicSymbolTable(const File &file);
- virtual void addDefaultAtoms();
- virtual bool createImplicitFiles(std::vector<std::unique_ptr<File> > &);
- virtual void finalizeDefaultAtomValues();
- virtual void createDefaultSections();
+ void buildDynamicSymbolTable(const File &file) override;
+ void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
+ void finalizeDefaultAtomValues() override;
+ void createDefaultSections() override;
- virtual bool isNeededTagRequired(const SharedLibraryAtom *sla) const {
+ bool isNeededTagRequired(const SharedLibraryAtom *sla) const override {
return this->_layout.isCopied(sla);
}
unique_bump_ptr<InterpSection<ELFT>> _interpSection;
- std::unique_ptr<RuntimeFile<ELFT> > _runtimeFile;
+
+private:
+ std::unique_ptr<RuntimeFile<ELFT>> createRuntimeFile();
};
//===----------------------------------------------------------------------===//
@@ -56,8 +53,8 @@ void ExecutableWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
if (!da)
continue;
if (da->dynamicExport() != DefinedAtom::dynamicExportAlways &&
- !this->_context.isDynamicallyExportedSymbol(da->name()) &&
- !(this->_context.shouldExportDynamic() &&
+ !this->_ctx.isDynamicallyExportedSymbol(da->name()) &&
+ !(this->_ctx.shouldExportDynamic() &&
da->scope() == Atom::Scope::scopeGlobal))
continue;
this->_dynamicSymbolTable->addSymbol(atom->_atom, section->ordinal(),
@@ -65,7 +62,7 @@ void ExecutableWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
}
// Put weak symbols in the dynamic symbol table.
- if (this->_context.isDynamic()) {
+ if (this->_ctx.isDynamic()) {
for (const UndefinedAtom *a : file.undefined()) {
if (this->_layout.isReferencedByDefinedAtom(a) &&
a->canBeNull() != UndefinedAtom::canBeNullNever)
@@ -76,48 +73,44 @@ void ExecutableWriter<ELFT>::buildDynamicSymbolTable(const File &file) {
OutputELFWriter<ELFT>::buildDynamicSymbolTable(file);
}
-/// \brief Add absolute symbols by default. These are linker added
-/// absolute symbols
template<class ELFT>
-void ExecutableWriter<ELFT>::addDefaultAtoms() {
- OutputELFWriter<ELFT>::addDefaultAtoms();
- _runtimeFile->addUndefinedAtom(this->_context.entrySymbolName());
- _runtimeFile->addAbsoluteAtom("__bss_start");
- _runtimeFile->addAbsoluteAtom("__bss_end");
- _runtimeFile->addAbsoluteAtom("_end");
- _runtimeFile->addAbsoluteAtom("end");
- _runtimeFile->addAbsoluteAtom("__preinit_array_start");
- _runtimeFile->addAbsoluteAtom("__preinit_array_end");
- _runtimeFile->addAbsoluteAtom("__init_array_start");
- _runtimeFile->addAbsoluteAtom("__init_array_end");
- if (this->_context.isRelaOutputFormat()) {
- _runtimeFile->addAbsoluteAtom("__rela_iplt_start");
- _runtimeFile->addAbsoluteAtom("__rela_iplt_end");
+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 {
- _runtimeFile->addAbsoluteAtom("__rel_iplt_start");
- _runtimeFile->addAbsoluteAtom("__rel_iplt_end");
+ file->addAbsoluteAtom("__rel_iplt_start");
+ file->addAbsoluteAtom("__rel_iplt_end");
}
- _runtimeFile->addAbsoluteAtom("__fini_array_start");
- _runtimeFile->addAbsoluteAtom("__fini_array_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>
-bool ExecutableWriter<ELFT>::createImplicitFiles(
+void ExecutableWriter<ELFT>::createImplicitFiles(
std::vector<std::unique_ptr<File> > &result) {
- // Add the default atoms as defined by executables
- ExecutableWriter<ELFT>::addDefaultAtoms();
OutputELFWriter<ELFT>::createImplicitFiles(result);
- result.push_back(std::move(_runtimeFile));
- return true;
+ result.push_back(createRuntimeFile());
}
template <class ELFT> void ExecutableWriter<ELFT>::createDefaultSections() {
OutputELFWriter<ELFT>::createDefaultSections();
- if (this->_context.isDynamic()) {
+ if (this->_ctx.isDynamic()) {
_interpSection.reset(new (this->_alloc) InterpSection<ELFT>(
- this->_context, ".interp", DefaultLayout<ELFT>::ORDER_INTERP,
- this->_context.getInterpreter()));
+ this->_ctx, ".interp", TargetLayout<ELFT>::ORDER_INTERP,
+ this->_ctx.getInterpreter()));
this->_layout.addSection(_interpSection.get());
}
}
@@ -126,53 +119,35 @@ template <class ELFT> void ExecutableWriter<ELFT>::createDefaultSections() {
/// created
template <class ELFT> void ExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
OutputELFWriter<ELFT>::finalizeDefaultAtomValues();
- auto bssStartAtomIter = this->_layout.findAbsoluteAtom("__bss_start");
- auto bssEndAtomIter = this->_layout.findAbsoluteAtom("__bss_end");
- auto underScoreEndAtomIter = this->_layout.findAbsoluteAtom("_end");
- auto endAtomIter = this->_layout.findAbsoluteAtom("end");
-
- auto startEnd = [&](StringRef sym, StringRef sec) -> void {
- std::string start = ("__" + sym + "_start").str();
- std::string end = ("__" + sym + "_end").str();
- auto s = this->_layout.findAbsoluteAtom(start);
- auto e = this->_layout.findAbsoluteAtom(end);
- auto section = this->_layout.findOutputSection(sec);
- if (section) {
- (*s)->_virtualAddr = section->virtualAddr();
- (*e)->_virtualAddr = section->virtualAddr() + section->memSize();
- } else {
- (*s)->_virtualAddr = 0;
- (*e)->_virtualAddr = 0;
- }
- };
+ 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");
- startEnd("preinit_array", ".preinit_array");
- startEnd("init_array", ".init_array");
- if (this->_context.isRelaOutputFormat())
- startEnd("rela_iplt", ".rela.plt");
- else
- startEnd("rel_iplt", ".rel.plt");
- startEnd("fini_array", ".fini_array");
-
- assert(!(bssStartAtomIter == this->_layout.absoluteAtoms().end() ||
- bssEndAtomIter == this->_layout.absoluteAtoms().end() ||
- underScoreEndAtomIter == this->_layout.absoluteAtoms().end() ||
- endAtomIter == this->_layout.absoluteAtoms().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) {
- (*bssStartAtomIter)->_virtualAddr = bssSection->virtualAddr();
- (*bssEndAtomIter)->_virtualAddr =
+ bssStartAtom->_virtualAddr = bssSection->virtualAddr();
+ bssEndAtom->_virtualAddr =
bssSection->virtualAddr() + bssSection->memSize();
- (*underScoreEndAtomIter)->_virtualAddr = (*bssEndAtomIter)->_virtualAddr;
- (*endAtomIter)->_virtualAddr = (*bssEndAtomIter)->_virtualAddr;
+ underScoreEndAtom->_virtualAddr = bssEndAtom->_virtualAddr;
+ endAtom->_virtualAddr = bssEndAtom->_virtualAddr;
} else if (auto dataSection = this->_layout.findOutputSection(".data")) {
- (*underScoreEndAtomIter)->_virtualAddr =
+ underScoreEndAtom->_virtualAddr =
dataSection->virtualAddr() + dataSection->memSize();
- (*endAtomIter)->_virtualAddr = (*underScoreEndAtomIter)->_virtualAddr;
+ endAtom->_virtualAddr = underScoreEndAtom->_virtualAddr;
}
}
diff --git a/lib/ReaderWriter/ELF/FileCommon.cpp b/lib/ReaderWriter/ELF/FileCommon.cpp
new file mode 100644
index 000000000000..c23e3f6656cd
--- /dev/null
+++ b/lib/ReaderWriter/ELF/FileCommon.cpp
@@ -0,0 +1,66 @@
+//===- 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
new file mode 100644
index 000000000000..eaff12afe72f
--- /dev/null
+++ b/lib/ReaderWriter/ELF/FileCommon.h
@@ -0,0 +1,45 @@
+//===- 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
new file mode 100644
index 000000000000..193937c18061
--- /dev/null
+++ b/lib/ReaderWriter/ELF/HeaderChunks.cpp
@@ -0,0 +1,205 @@
+//===- 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
index eab132b9b2f6..51fbe38f1a00 100644
--- a/lib/ReaderWriter/ELF/HeaderChunks.h
+++ b/lib/ReaderWriter/ELF/HeaderChunks.h
@@ -11,18 +11,18 @@
#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/Debug.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/Format.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;
@@ -33,9 +33,9 @@ public:
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_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; }
@@ -43,57 +43,25 @@ public:
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 { return sizeof(Elf_Ehdr); }
+ uint64_t fileSize() const override { return sizeof(Elf_Ehdr); }
static bool classof(const Chunk<ELFT> *c) {
- return c->Kind() == Chunk<ELFT>::Kind::ELFHeader;
+ return c->kind() == Chunk<ELFT>::Kind::ELFHeader;
}
- int getContentType() const { return Chunk<ELFT>::ContentType::Header; }
+ int getContentType() const override {
+ return Chunk<ELFT>::ContentType::Header;
+ }
void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer);
-
- virtual void doPreFlight() {}
-
- void 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->_context.getOutputELFType();
- _eh.e_machine = this->_context.getOutputMachine();
- }
+ llvm::FileOutputBuffer &buffer) override;
+
+ void finalize() override;
private:
Elf_Ehdr _eh;
};
-template <class ELFT>
-ELFHeader<ELFT>::ELFHeader(const ELFLinkingContext &context)
- : Chunk<ELFT>("elfhdr", Chunk<ELFT>::Kind::ELFHeader, context) {
- 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());
-}
-
/// \brief An ProgramHeader represents the Elf[32/64]_Phdr structure at the
/// start of an ELF executable file.
template<class ELFT>
@@ -103,160 +71,43 @@ public:
typedef typename std::vector<Elf_Phdr *>::iterator PhIterT;
typedef typename std::reverse_iterator<PhIterT> ReversePhIterT;
- /// \brief Find a program header entry, given the type of entry that
- /// we are looking for
- class FindPhdr {
- public:
- FindPhdr(uint64_t type, uint64_t flags, uint64_t flagsClear)
- : _type(type)
- , _flags(flags)
- , _flagsClear(flagsClear) {
- }
-
- bool operator()(const llvm::object::Elf_Phdr_Impl<ELFT> *j) const {
- return ((j->p_type == _type) &&
- ((j->p_flags & _flags) == _flags) &&
- (!(j->p_flags & _flagsClear)));
- }
- private:
- uint64_t _type;
- uint64_t _flags;
- uint64_t _flagsClear;
- };
-
- ProgramHeader(const ELFLinkingContext &context)
- : Chunk<ELFT>("elfphdr", Chunk<ELFT>::Kind::ProgramHeader, context) {
+ 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 { return sizeof(Elf_Phdr) * _ph.size(); }
+ 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;
+ return c->kind() == Chunk<ELFT>::Kind::ProgramHeader;
}
void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer);
-
- /// \brief find a program header entry in the list of program headers
- ReversePhIterT
- findProgramHeader(uint64_t type, uint64_t flags, uint64_t flagClear) {
- return std::find_if(_ph.rbegin(), _ph.rend(),
- FindPhdr(type, flags, flagClear));
- }
-
- PhIterT begin() {
- return _ph.begin();
- }
-
- PhIterT end() {
- return _ph.end();
- }
+ llvm::FileOutputBuffer &buffer) override;
+ PhIterT begin() { return _ph.begin(); }
+ PhIterT end() { return _ph.end(); }
ReversePhIterT rbegin() { return _ph.rbegin(); }
-
ReversePhIterT rend() { return _ph.rend(); }
- virtual void doPreFlight() {}
-
- void finalize() {}
-
int64_t entsize() { return sizeof(Elf_Phdr); }
+ int64_t numHeaders() { return _ph.size(); }
- int64_t numHeaders() {
- return _ph.size();
+ int getContentType() const override {
+ return Chunk<ELFT>::ContentType::Header;
}
- int getContentType() const { return Chunk<ELFT>::ContentType::Header; }
-
private:
- Elf_Phdr *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;
- }
+ Elf_Phdr *allocateProgramHeader(bool &allocatedNew);
std::vector<Elf_Phdr *> _ph;
PhIterT _phi;
llvm::BumpPtrAllocator _allocator;
};
-template <class ELFT>
-bool ProgramHeader<ELFT>::addSegment(Segment<ELFT> *segment) {
- bool allocatedNew = false;
- ELFLinkingContext::OutputMagic outputMagic = this->_context.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);
- }
-}
-
/// \brief An SectionHeader represents the Elf[32/64]_Shdr structure
/// at the end of the file
template<class ELFT>
@@ -265,13 +116,11 @@ 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->getChunkKind() == Chunk<ELFT>::Kind::SectionHeader;
+ return c->kind() == Chunk<ELFT>::Kind::SectionHeader;
}
void setStringSection(StringTable<ELFT> *s) {
@@ -279,85 +128,26 @@ public:
}
void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer);
+ llvm::FileOutputBuffer &buffer) override;
- virtual void doPreFlight() {}
-
- void finalize() {}
-
- uint64_t fileSize() const { return sizeof(Elf_Shdr) * _sectionInfo.size(); }
+ uint64_t fileSize() const override {
+ return sizeof(Elf_Shdr) * _sectionInfo.size();
+ }
uint64_t entsize() { return sizeof(Elf_Shdr); }
- int getContentType() const { return Chunk<ELFT>::ContentType::Header; }
+ 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;
+ std::vector<Elf_Shdr *> _sectionInfo;
+ llvm::BumpPtrAllocator _sectionAllocate;
};
-template <class ELFT>
-SectionHeader<ELFT>::SectionHeader(const ELFLinkingContext &context,
- int32_t order)
- : Chunk<ELFT>("shdr", Chunk<ELFT>::Kind::SectionHeader, context) {
- this->_fsize = 0;
- this->_alignment = 8;
- this->setOrder(order);
- // The first element in the list is always NULL
- Elf_Shdr *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) {
- Elf_Shdr *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);
-}
} // end namespace elf
} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicLibraryWriter.h b/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicLibraryWriter.h
index e2d3193045b7..84415b273f44 100644
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicLibraryWriter.h
+++ b/lib/ReaderWriter/ELF/Hexagon/HexagonDynamicLibraryWriter.h
@@ -10,67 +10,55 @@
#define HEXAGON_DYNAMIC_LIBRARY_WRITER_H
#include "DynamicLibraryWriter.h"
-#include "HexagonExecutableAtoms.h"
#include "HexagonLinkingContext.h"
namespace lld {
namespace elf {
-template <typename ELFT> class HexagonTargetLayout;
+class HexagonTargetLayout;
-template <class ELFT>
-class HexagonDynamicLibraryWriter : public DynamicLibraryWriter<ELFT>,
- public HexagonELFWriter<ELFT> {
+class HexagonDynamicLibraryWriter : public DynamicLibraryWriter<ELF32LE> {
public:
- HexagonDynamicLibraryWriter(HexagonLinkingContext &context,
- HexagonTargetLayout<ELFT> &layout);
+ HexagonDynamicLibraryWriter(HexagonLinkingContext &ctx,
+ HexagonTargetLayout &layout);
protected:
// Add any runtime files and their atoms to the output
- virtual bool createImplicitFiles(std::vector<std::unique_ptr<File>> &);
+ void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
- virtual void finalizeDefaultAtomValues();
+ void finalizeDefaultAtomValues() override;
- virtual std::error_code setELFHeader() {
- DynamicLibraryWriter<ELFT>::setELFHeader();
- HexagonELFWriter<ELFT>::setELFHeader(*this->_elfHeader);
+ std::error_code setELFHeader() override {
+ DynamicLibraryWriter::setELFHeader();
+ setHexagonELFHeader(*_elfHeader);
return std::error_code();
}
private:
- void addDefaultAtoms() {
- _hexagonRuntimeFile->addAbsoluteAtom("_GLOBAL_OFFSET_TABLE_");
- _hexagonRuntimeFile->addAbsoluteAtom("_DYNAMIC");
- }
-
- HexagonLinkingContext &_hexagonLinkingContext;
- HexagonTargetLayout<ELFT> &_hexagonTargetLayout;
- std::unique_ptr<HexagonRuntimeFile<ELFT>> _hexagonRuntimeFile;
+ HexagonLinkingContext &_ctx;
+ HexagonTargetLayout &_targetLayout;
};
-template <class ELFT>
-HexagonDynamicLibraryWriter<ELFT>::HexagonDynamicLibraryWriter(
- HexagonLinkingContext &context, HexagonTargetLayout<ELFT> &layout)
- : DynamicLibraryWriter<ELFT>(context, layout),
- HexagonELFWriter<ELFT>(context, layout), _hexagonLinkingContext(context),
- _hexagonTargetLayout(layout),
- _hexagonRuntimeFile(new HexagonRuntimeFile<ELFT>(context)) {}
+HexagonDynamicLibraryWriter::HexagonDynamicLibraryWriter(
+ HexagonLinkingContext &ctx, HexagonTargetLayout &layout)
+ : DynamicLibraryWriter(ctx, layout), _ctx(ctx), _targetLayout(layout) {}
-template <class ELFT>
-bool HexagonDynamicLibraryWriter<ELFT>::createImplicitFiles(
+void HexagonDynamicLibraryWriter::createImplicitFiles(
std::vector<std::unique_ptr<File>> &result) {
- DynamicLibraryWriter<ELFT>::createImplicitFiles(result);
+ DynamicLibraryWriter::createImplicitFiles(result);
// Add the default atoms as defined for hexagon
- addDefaultAtoms();
- result.push_back(std::move(_hexagonRuntimeFile));
- return true;
+ 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));
}
-template <class ELFT>
-void HexagonDynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues() {
+void HexagonDynamicLibraryWriter::finalizeDefaultAtomValues() {
// Finalize the atom values that are part of the parent.
- DynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues();
- HexagonELFWriter<ELFT>::finalizeHexagonRuntimeAtomValues();
+ DynamicLibraryWriter::finalizeDefaultAtomValues();
+ if (_ctx.isDynamic())
+ finalizeHexagonRuntimeAtomValues(_targetLayout);
}
} // namespace elf
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h b/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h
index ab0b9b432b43..3d0d38f387dd 100644
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h
+++ b/lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h
@@ -16,53 +16,46 @@
namespace lld {
namespace elf {
-template <class ELFT> class HexagonELFFile;
+class HexagonELFFile;
-template <class ELFT>
-class HexagonELFDefinedAtom : public ELFDefinedAtom<ELFT> {
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
- typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
+class HexagonELFDefinedAtom : public ELFDefinedAtom<ELF32LE> {
+ typedef llvm::object::Elf_Sym_Impl<ELF32LE> Elf_Sym;
+ typedef llvm::object::Elf_Shdr_Impl<ELF32LE> Elf_Shdr;
public:
- HexagonELFDefinedAtom(const HexagonELFFile<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) {}
-
- virtual DefinedAtom::ContentType contentType() const {
- if (this->_contentType != DefinedAtom::typeUnknown)
- return this->_contentType;
- else if (this->_section->sh_flags & llvm::ELF::SHF_HEX_GPREL) {
- if (this->_section->sh_type == llvm::ELF::SHT_NOBITS)
- return (this->_contentType = DefinedAtom::typeZeroFillFast);
- else
- return (this->_contentType = DefinedAtom::typeDataFast);
+ 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<ELFT>::contentType();
+ return ELFDefinedAtom::contentType();
}
- virtual DefinedAtom::ContentPermissions permissions() const {
- if (this->_section->sh_flags & llvm::ELF::SHF_HEX_GPREL)
+ DefinedAtom::ContentPermissions permissions() const override {
+ if (_section->sh_flags & llvm::ELF::SHF_HEX_GPREL)
return DefinedAtom::permRW_;
- return ELFDefinedAtom<ELFT>::permissions();
+ return ELFDefinedAtom::permissions();
}
};
-template <class ELFT> class HexagonELFCommonAtom : public ELFCommonAtom<ELFT> {
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
- typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
+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 HexagonELFFile<ELFT> &file, StringRef symbolName,
+ HexagonELFCommonAtom(const ELFFile<ELF32LE> &file, StringRef symbolName,
const Elf_Sym *symbol)
- : ELFCommonAtom<ELFT>(file, symbolName, symbol) {}
+ : ELFCommonAtom(file, symbolName, symbol) {}
virtual bool isSmallCommonSymbol() const {
- switch (this->_symbol->st_shndx) {
+ switch (_symbol->st_shndx) {
// Common symbols
case llvm::ELF::SHN_HEXAGON_SCOMMON:
case llvm::ELF::SHN_HEXAGON_SCOMMON_1:
@@ -76,52 +69,46 @@ public:
return false;
}
- virtual uint64_t size() const {
+ uint64_t size() const override {
if (isSmallCommonSymbol())
- return this->_symbol->st_size;
- return ELFCommonAtom<ELFT>::size();
+ return _symbol->st_size;
+ return ELFCommonAtom::size();
}
- virtual DefinedAtom::Merge merge() const {
- if (this->_symbol->getBinding() == llvm::ELF::STB_WEAK)
+ DefinedAtom::Merge merge() const override {
+ if (_symbol->getBinding() == llvm::ELF::STB_WEAK)
return DefinedAtom::mergeAsWeak;
if (isSmallCommonSymbol())
return DefinedAtom::mergeAsTentative;
- return ELFCommonAtom<ELFT>::merge();
+ return ELFCommonAtom::merge();
}
- virtual DefinedAtom::ContentType contentType() const {
+ DefinedAtom::ContentType contentType() const override {
if (isSmallCommonSymbol())
return DefinedAtom::typeZeroFillFast;
- return ELFCommonAtom<ELFT>::contentType();
+ return ELFCommonAtom::contentType();
}
- virtual DefinedAtom::Alignment alignment() const {
+ DefinedAtom::Alignment alignment() const override {
if (isSmallCommonSymbol())
- return DefinedAtom::Alignment(llvm::Log2_64(this->_symbol->st_value));
- return ELFCommonAtom<ELFT>::alignment();
+ return DefinedAtom::Alignment(_symbol->st_value);
+ return 1;
}
- virtual DefinedAtom::ContentPermissions permissions() const {
+ DefinedAtom::ContentPermissions permissions() const override {
if (isSmallCommonSymbol())
return DefinedAtom::permRW_;
- return ELFCommonAtom<ELFT>::permissions();
+ return ELFCommonAtom::permissions();
}
};
-template <class ELFT> class HexagonELFFile : public ELFFile<ELFT> {
- typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
- typedef llvm::object::Elf_Shdr_Impl<ELFT> Elf_Shdr;
+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, HexagonLinkingContext &ctx)
- : ELFFile<ELFT>(std::move(mb), ctx) {}
-
- static ErrorOr<std::unique_ptr<HexagonELFFile>>
- create(std::unique_ptr<MemoryBuffer> mb, HexagonLinkingContext &ctx) {
- return std::unique_ptr<HexagonELFFile<ELFT>>(
- new HexagonELFFile<ELFT>(std::move(mb), ctx));
- }
+ 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) {
@@ -135,35 +122,27 @@ public:
default:
break;
}
- return ELFFile<ELFT>::isCommonSymbol(symbol);
+ return ELFFile::isCommonSymbol(symbol);
}
/// Process the Defined symbol and create an atom for it.
- ErrorOr<ELFDefinedAtom<ELFT> *>
- handleDefinedSymbol(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 {
- return new (this->_readerStorage) HexagonELFDefinedAtom<ELFT>(
+ 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.
- ErrorOr<ELFCommonAtom<ELFT> *>
- handleCommonSymbol(StringRef symName, const Elf_Sym *sym) override {
- return new (this->_readerStorage)
- HexagonELFCommonAtom<ELFT>(*this, symName, sym);
+ ELFCommonAtom<ELF32LE> *createCommonAtom(StringRef symName,
+ const Elf_Sym *sym) override {
+ return new (_readerStorage) HexagonELFCommonAtom(*this, symName, sym);
}
};
-template <class ELFT> class HexagonDynamicFile : public DynamicFile<ELFT> {
-public:
- HexagonDynamicFile(const HexagonLinkingContext &context, StringRef name)
- : DynamicFile<ELFT>(context, name) {}
-};
-
} // elf
} // lld
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonELFReader.h b/lib/ReaderWriter/ELF/Hexagon/HexagonELFReader.h
deleted file mode 100644
index 1a4f891df799..000000000000
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonELFReader.h
+++ /dev/null
@@ -1,62 +0,0 @@
-//===- lib/ReaderWriter/ELF/HexagonELFReader.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_HEXAGON_ELF_READER_H
-#define LLD_READER_WRITER_HEXAGON_ELF_READER_H
-
-#include "ELFReader.h"
-#include "HexagonELFFile.h"
-
-namespace lld {
-namespace elf {
-
-typedef llvm::object::ELFType<llvm::support::little, 2, false> HexagonELFType;
-
-struct HexagonDynamicFileCreateELFTraits {
- typedef llvm::ErrorOr<std::unique_ptr<lld::SharedLibraryFile>> result_type;
-
- template <class ELFT>
- static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb,
- HexagonLinkingContext &ctx) {
- return lld::elf::HexagonDynamicFile<ELFT>::create(std::move(mb), ctx);
- }
-};
-
-struct HexagonELFFileCreateELFTraits {
- typedef llvm::ErrorOr<std::unique_ptr<lld::File>> result_type;
-
- template <class ELFT>
- static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb,
- HexagonLinkingContext &ctx) {
- return lld::elf::HexagonELFFile<ELFT>::create(std::move(mb), ctx);
- }
-};
-
-class HexagonELFObjectReader
- : public ELFObjectReader<HexagonELFType, HexagonELFFileCreateELFTraits,
- HexagonLinkingContext> {
-public:
- HexagonELFObjectReader(HexagonLinkingContext &ctx)
- : ELFObjectReader<HexagonELFType, HexagonELFFileCreateELFTraits,
- HexagonLinkingContext>(ctx, llvm::ELF::EM_HEXAGON) {}
-};
-
-class HexagonELFDSOReader
- : public ELFDSOReader<HexagonELFType, HexagonDynamicFileCreateELFTraits,
- HexagonLinkingContext> {
-public:
- HexagonELFDSOReader(HexagonLinkingContext &ctx)
- : ELFDSOReader<HexagonELFType, HexagonDynamicFileCreateELFTraits,
- HexagonLinkingContext>(ctx, llvm::ELF::EM_HEXAGON) {}
-};
-
-} // namespace elf
-} // namespace lld
-
-#endif // LLD_READER_WRITER_ELF_READER_H
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonELFWriters.h b/lib/ReaderWriter/ELF/Hexagon/HexagonELFWriters.h
deleted file mode 100644
index 96c74f72222d..000000000000
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonELFWriters.h
+++ /dev/null
@@ -1,61 +0,0 @@
-//===- lib/ReaderWriter/ELF/Hexagon/HexagonELFWriters.h -------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef HEXAGON_ELF_WRITERS_H
-#define HEXAGON_ELF_WRITERS_H
-
-#include "HexagonLinkingContext.h"
-#include "OutputELFWriter.h"
-
-namespace lld {
-namespace elf {
-
-template <class ELFT> class HexagonTargetLayout;
-
-template <typename ELFT> class HexagonELFWriter {
-public:
- HexagonELFWriter(HexagonLinkingContext &context,
- HexagonTargetLayout<ELFT> &targetLayout)
- : _hexagonLinkingContext(context), _hexagonTargetLayout(targetLayout) {}
-
-protected:
- bool setELFHeader(ELFHeader<ELFT> &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);
- return true;
- }
-
- void finalizeHexagonRuntimeAtomValues() {
- if (_hexagonLinkingContext.isDynamic()) {
- auto gotAtomIter =
- _hexagonTargetLayout.findAbsoluteAtom("_GLOBAL_OFFSET_TABLE_");
- auto gotpltSection = _hexagonTargetLayout.findOutputSection(".got.plt");
- if (gotpltSection)
- (*gotAtomIter)->_virtualAddr = gotpltSection->virtualAddr();
- else
- (*gotAtomIter)->_virtualAddr = 0;
- auto dynamicAtomIter = _hexagonTargetLayout.findAbsoluteAtom("_DYNAMIC");
- auto dynamicSection = _hexagonTargetLayout.findOutputSection(".dynamic");
- if (dynamicSection)
- (*dynamicAtomIter)->_virtualAddr = dynamicSection->virtualAddr();
- else
- (*dynamicAtomIter)->_virtualAddr = 0;
- }
- }
-
-private:
- HexagonLinkingContext &_hexagonLinkingContext;
- HexagonTargetLayout<ELFT> &_hexagonTargetLayout;
-};
-
-} // elf
-} // lld
-#endif // HEXAGON_ELF_WRITERS_H
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonEncodings.h b/lib/ReaderWriter/ELF/Hexagon/HexagonEncodings.h
index 3e12786704a2..6af43d88afbb 100644
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonEncodings.h
+++ b/lib/ReaderWriter/ELF/Hexagon/HexagonEncodings.h
@@ -6,7 +6,27 @@
// 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 },
@@ -599,3 +619,20 @@ Instruction insn_encodings[] = {
{ 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/HexagonExecutableAtoms.h b/lib/ReaderWriter/ELF/Hexagon/HexagonExecutableAtoms.h
deleted file mode 100644
index a2505aa460c5..000000000000
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonExecutableAtoms.h
+++ /dev/null
@@ -1,29 +0,0 @@
-//===- lib/ReaderWriter/ELF/Hexagon/HexagonExecutableAtoms.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_EXECUTABLE_ATOM_H
-#define LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_EXECUTABLE_ATOM_H
-
-#include "ELFFile.h"
-
-namespace lld {
-namespace elf {
-typedef llvm::object::ELFType<llvm::support::little, 2, false> HexagonELFType;
-class HexagonLinkingContext;
-
-template <class HexagonELFType> class HexagonRuntimeFile
- : public RuntimeFile<HexagonELFType> {
-public:
- HexagonRuntimeFile(HexagonLinkingContext &context)
- : RuntimeFile<HexagonELFType>(context, "Hexagon runtime file") {}
-};
-} // elf
-} // lld
-
-#endif // LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_EXECUTABLE_ATOM_H
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonExecutableWriter.h b/lib/ReaderWriter/ELF/Hexagon/HexagonExecutableWriter.h
index 0848e64166fa..390694954a75 100644
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonExecutableWriter.h
+++ b/lib/ReaderWriter/ELF/Hexagon/HexagonExecutableWriter.h
@@ -10,74 +10,61 @@
#define HEXAGON_EXECUTABLE_WRITER_H
#include "ExecutableWriter.h"
-#include "HexagonELFWriters.h"
-#include "HexagonExecutableAtoms.h"
#include "HexagonLinkingContext.h"
+#include "HexagonTargetHandler.h"
namespace lld {
namespace elf {
-template <typename ELFT> class HexagonTargetLayout;
+class HexagonTargetLayout;
-template <class ELFT>
-class HexagonExecutableWriter : public ExecutableWriter<ELFT>,
- public HexagonELFWriter<ELFT> {
+class HexagonExecutableWriter : public ExecutableWriter<ELF32LE> {
public:
- HexagonExecutableWriter(HexagonLinkingContext &context,
- HexagonTargetLayout<ELFT> &layout);
+ HexagonExecutableWriter(HexagonLinkingContext &ctx,
+ HexagonTargetLayout &layout);
protected:
// Add any runtime files and their atoms to the output
- virtual bool createImplicitFiles(std::vector<std::unique_ptr<File>> &);
+ void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
- virtual void finalizeDefaultAtomValues();
+ void finalizeDefaultAtomValues() override;
- virtual std::error_code setELFHeader() {
- ExecutableWriter<ELFT>::setELFHeader();
- HexagonELFWriter<ELFT>::setELFHeader(*this->_elfHeader);
+ std::error_code setELFHeader() override {
+ ExecutableWriter::setELFHeader();
+ setHexagonELFHeader(*_elfHeader);
return std::error_code();
}
private:
- void addDefaultAtoms() {
- _hexagonRuntimeFile->addAbsoluteAtom("_SDA_BASE_");
- if (this->_context.isDynamic()) {
- _hexagonRuntimeFile->addAbsoluteAtom("_GLOBAL_OFFSET_TABLE_");
- _hexagonRuntimeFile->addAbsoluteAtom("_DYNAMIC");
- }
- }
-
- HexagonLinkingContext &_hexagonLinkingContext;
- HexagonTargetLayout<ELFT> &_hexagonTargetLayout;
- std::unique_ptr<HexagonRuntimeFile<ELFT>> _hexagonRuntimeFile;
+ HexagonLinkingContext &_ctx;
+ HexagonTargetLayout &_targetLayout;
};
-template <class ELFT>
-HexagonExecutableWriter<ELFT>::HexagonExecutableWriter(
- HexagonLinkingContext &context, HexagonTargetLayout<ELFT> &layout)
- : ExecutableWriter<ELFT>(context, layout),
- HexagonELFWriter<ELFT>(context, layout), _hexagonLinkingContext(context),
- _hexagonTargetLayout(layout),
- _hexagonRuntimeFile(new HexagonRuntimeFile<ELFT>(context)) {}
+HexagonExecutableWriter::HexagonExecutableWriter(HexagonLinkingContext &ctx,
+ HexagonTargetLayout &layout)
+ : ExecutableWriter(ctx, layout), _ctx(ctx), _targetLayout(layout) {}
-template <class ELFT>
-bool HexagonExecutableWriter<ELFT>::createImplicitFiles(
+void HexagonExecutableWriter::createImplicitFiles(
std::vector<std::unique_ptr<File>> &result) {
- ExecutableWriter<ELFT>::createImplicitFiles(result);
+ ExecutableWriter::createImplicitFiles(result);
// Add the default atoms as defined for hexagon
- addDefaultAtoms();
- result.push_back(std::move(_hexagonRuntimeFile));
- return true;
+ 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));
}
-template <class ELFT>
-void HexagonExecutableWriter<ELFT>::finalizeDefaultAtomValues() {
+void HexagonExecutableWriter::finalizeDefaultAtomValues() {
// Finalize the atom values that are part of the parent.
- ExecutableWriter<ELFT>::finalizeDefaultAtomValues();
- auto sdabaseAtomIter = _hexagonTargetLayout.findAbsoluteAtom("_SDA_BASE_");
- (*sdabaseAtomIter)->_virtualAddr =
- _hexagonTargetLayout.getSDataSection()->virtualAddr();
- HexagonELFWriter<ELFT>::finalizeHexagonRuntimeAtomValues();
+ ExecutableWriter::finalizeDefaultAtomValues();
+ AtomLayout *sdabaseAtom = _targetLayout.findAbsoluteAtom("_SDA_BASE_");
+ sdabaseAtom->_virtualAddr = _targetLayout.getSDataSection()->virtualAddr();
+ if (_ctx.isDynamic())
+ finalizeHexagonRuntimeAtomValues(_targetLayout);
}
} // namespace elf
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp b/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp
index 7eacb2b44c3b..11eabf7e26fc 100644
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp
+++ b/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp
@@ -10,16 +10,38 @@
#include "HexagonLinkingContext.h"
#include "HexagonTargetHandler.h"
-using namespace lld::elf;
+namespace lld {
+namespace elf {
-std::unique_ptr<lld::ELFLinkingContext>
-HexagonLinkingContext::create(llvm::Triple triple) {
+std::unique_ptr<ELFLinkingContext>
+createHexagonLinkingContext(llvm::Triple triple) {
if (triple.getArch() == llvm::Triple::hexagon)
- return std::unique_ptr<lld::ELFLinkingContext>(
- new HexagonLinkingContext(triple));
+ return llvm::make_unique<HexagonLinkingContext>(triple);
return nullptr;
}
HexagonLinkingContext::HexagonLinkingContext(llvm::Triple triple)
- : ELFLinkingContext(triple, std::unique_ptr<TargetHandlerBase>(
+ : 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
index c920cdf153aa..ab91e405fd56 100644
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h
+++ b/lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h
@@ -10,6 +10,7 @@
#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"
@@ -17,14 +18,13 @@
namespace lld {
namespace elf {
-typedef llvm::object::ELFType<llvm::support::little, 2, false> HexagonELFType;
-
class HexagonLinkingContext final : public ELFLinkingContext {
public:
- static std::unique_ptr<ELFLinkingContext> create(llvm::Triple);
+ 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)
@@ -41,12 +41,7 @@ public:
bool isPLTRelocation(const Reference &r) const override {
if (r.kindNamespace() != Reference::KindNamespace::ELF)
return false;
- switch (r.kindValue()) {
- case llvm::ELF::R_HEX_JMP_SLOT:
- return true;
- default:
- return false;
- }
+ return r.kindValue() == llvm::ELF::R_HEX_JMP_SLOT;
}
/// \brief Hexagon has only one relative relocation
@@ -54,15 +49,12 @@ public:
bool isRelativeReloc(const Reference &r) const override {
if (r.kindNamespace() != Reference::KindNamespace::ELF)
return false;
- switch (r.kindValue()) {
- case llvm::ELF::R_HEX_RELATIVE:
- return true;
- default:
- return false;
- }
+ return r.kindValue() == llvm::ELF::R_HEX_RELATIVE;
}
};
+void setHexagonELFHeader(ELFHeader<ELF32LE> &elfHeader);
+
} // elf
} // lld
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h b/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h
deleted file mode 100644
index 2b9e25ce363b..000000000000
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationFunctions.h
+++ /dev/null
@@ -1,49 +0,0 @@
-//===- HexagonRelocationFunction.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_FUNCTIONS_H
-#define LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_RELOCATION_FUNCTIONS_H
-
-namespace lld {
-namespace elf {
-
-/// \brief HexagonInstruction which is used to store various values
-typedef struct {
- uint32_t insnMask;
- uint32_t insnCmpMask;
- uint32_t insnBitMask;
- bool isDuplex;
-} Instruction;
-
-#include "HexagonEncodings.h"
-
-#define FINDV4BITMASK(INSN) \
- findBitMask((uint32_t) * ((llvm::support::ulittle32_t *) INSN), \
- insn_encodings, \
- sizeof(insn_encodings) / sizeof(Instruction))
-
-/// \brief finds the scatter Bits that need to be used to apply relocations
-inline uint32_t
-findBitMask(uint32_t insn, Instruction *encodings, int32_t numInsns) {
- for (int32_t i = 0; i < numInsns; i++) {
- if (((insn & 0xc000) == 0) && !(encodings[i].isDuplex))
- continue;
-
- if (((insn & 0xc000) != 0) && (encodings[i].isDuplex))
- continue;
-
- if (((encodings[i].insnMask) & insn) == encodings[i].insnCmpMask)
- return encodings[i].insnBitMask;
- }
- llvm_unreachable("found unknown instruction");
-}
-
-} // elf
-} // lld
-
-#endif // LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_RELOCATION_FUNCTIONS_H
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp b/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp
index 21967d356a31..0a201b32b5f1 100644
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp
+++ b/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp
@@ -7,10 +7,10 @@
//
//===----------------------------------------------------------------------===//
+#include "HexagonEncodings.h"
#include "HexagonLinkingContext.h"
-#include "HexagonRelocationFunctions.h"
-#include "HexagonTargetHandler.h"
#include "HexagonRelocationHandler.h"
+#include "HexagonTargetHandler.h"
#include "llvm/Support/Endian.h"
using namespace lld;
@@ -18,263 +18,250 @@ using namespace lld::elf;
using namespace llvm::ELF;
using namespace llvm::support::endian;
-#define APPLY_RELOC(result) \
- write32le(location, result | read32le(location));
+// 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 int relocBNPCREL(uint8_t *location, uint64_t P, uint64_t S, uint64_t A,
- int32_t nBits) {
- int32_t result = (uint32_t)(((S + A) - P) >> 2);
+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 = lld::scatterBits<int32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+ result = scatterBits(result, findv4bitmask(loc));
+ write32le(loc, result | read32le(loc));
}
- return 1;
}
/// \brief Word32_LO: 0x00c03fff : (S + A) : Truncate
-static int relocLO16(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
- uint32_t result = (uint32_t)(S + A);
- result = lld::scatterBits<int32_t>(result, 0x00c03fff);
- APPLY_RELOC(result);
- return 0;
+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 int relocHI16(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
- uint32_t result = (uint32_t)((S + A) >> 16);
- result = lld::scatterBits<int32_t>(result, 0x00c03fff);
- APPLY_RELOC(result);
- return 0;
+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 int reloc32(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
- uint32_t result = (uint32_t)(S + A);
- APPLY_RELOC(result);
- return 0;
+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 int reloc32_6_X(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
- int64_t result = ((S + A) >> 6);
- int64_t range = ((int64_t)1) << 32;
+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)
- return 1;
- result = lld::scatterBits<int32_t>(result, 0xfff3fff);
- APPLY_RELOC(result);
- return 0;
+ result = scatterBits(result, 0xfff3fff);
+ write32le(loc, result | read32le(loc));
}
// R_HEX_B32_PCREL_X
-static int relocHexB32PCRELX(uint8_t *location, uint64_t P, uint64_t S,
- uint64_t A) {
- int64_t result = ((S + A - P) >> 6);
- result = lld::scatterBits<int32_t>(result, 0xfff3fff);
- APPLY_RELOC(result);
- return 0;
+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 int relocHexBNPCRELX(uint8_t *location, uint64_t P, uint64_t S,
- uint64_t A, int nbits) {
- int32_t result = ((S + A - P) & 0x3f);
+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 = lld::scatterBits<int32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+ result = scatterBits(result, findv4bitmask(loc));
+ write32le(loc, result | read32le(loc));
}
- return 1;
}
// R_HEX_6_PCREL_X
-static int relocHex6PCRELX(uint8_t *location, uint64_t P, uint64_t S,
- uint64_t A) {
- int32_t result = (S + A - P);
- result = lld::scatterBits<int32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+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 int relocHex_N_X(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
- uint32_t result = (S + A);
- result = lld::scatterBits<uint32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+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 relocations
-static int relocHexGPRELN(uint8_t *location, uint64_t P, uint64_t S, uint64_t A,
- uint64_t GP, int nShiftBits) {
- int32_t result = (int64_t)((S + A - GP) >> nShiftBits);
+// 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 = lld::scatterBits<uint32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+ result = scatterBits(result, findv4bitmask(loc));
+ write32le(loc, result | read32le(loc));
}
- return 1;
}
/// \brief Word32_LO: 0x00c03fff : (G) : Truncate
-static int relocHexGOTLO16(uint8_t *location, uint64_t A, uint64_t GOT) {
- int32_t result = (int32_t)(A-GOT);
- result = lld::scatterBits<int32_t>(result, 0x00c03fff);
- APPLY_RELOC(result);
- return 0;
+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 int relocHexGOTHI16(uint8_t *location, uint64_t A, uint64_t GOT) {
- int32_t result = (int32_t)((A-GOT) >> 16);
- result = lld::scatterBits<int32_t>(result, 0x00c03fff);
- APPLY_RELOC(result);
- return 0;
+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 int relocHexGOT32(uint8_t *location, uint64_t A, uint64_t GOT) {
- int32_t result = (int32_t)(GOT - A);
- APPLY_RELOC(result);
- return 0;
+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 int relocHexGOT16(uint8_t *location, uint64_t A, uint64_t GOT) {
- int32_t result = (int32_t)(GOT-A);
+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 = lld::scatterBits<int32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+ result = scatterBits(result, findv4bitmask(loc));
+ write32le(loc, result | read32le(loc));
}
- return 1;
}
-static int relocHexGOT32_6_X(uint8_t *location, uint64_t A, uint64_t GOT) {
- int32_t result = (int32_t)((A-GOT) >> 6);
- result = lld::scatterBits<int32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+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 int relocHexGOT16_X(uint8_t *location, uint64_t A, uint64_t GOT) {
- int32_t result = (int32_t)(A-GOT);
+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 = lld::scatterBits<int32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+ result = scatterBits(result, findv4bitmask(loc));
+ write32le(loc, result | read32le(loc));
}
- return 1;
}
-static int relocHexGOT11_X(uint8_t *location, uint64_t A, uint64_t GOT) {
- uint32_t result = (uint32_t)(A-GOT);
- result = lld::scatterBits<uint32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+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 int relocHexGOTRELSigned(uint8_t *location, uint64_t P, uint64_t S,
- uint64_t A, uint64_t GOT, int shiftBits = 0) {
- int32_t result = (int32_t)((S + A - GOT) >> shiftBits);
- result = lld::scatterBits<int32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+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 int relocHexGOTRELUnsigned(uint8_t *location, uint64_t P, uint64_t S,
- uint64_t A, uint64_t GOT, int shiftBits = 0) {
- uint32_t result = (uint32_t)((S + A - GOT) >> shiftBits);
- result = lld::scatterBits<uint32_t>(result, FINDV4BITMASK(location));
- APPLY_RELOC(result);
- return 0;
+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 int relocHexGOTREL_HILO16(uint8_t *location, uint64_t P, uint64_t S,
- uint64_t A, uint64_t GOT, int shiftBits = 0) {
- int32_t result = (int32_t)((S + A - GOT) >> shiftBits);
- result = lld::scatterBits<int32_t>(result, 0x00c03fff);
- APPLY_RELOC(result);
- return 0;
+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 int relocHexGOTREL_32(uint8_t *location, uint64_t P, uint64_t S,
- uint64_t A, uint64_t GOT) {
- int32_t result = (int32_t)(S + A - GOT);
- APPLY_RELOC(result);
- return 0;
+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 lld::AtomLayout &atom,
+ ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
const Reference &ref) const {
uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
- uint8_t *location = atomContent + ref.offsetInAtom();
- uint64_t targetVAddress = writer.addressOfAtom(ref.target());
- uint64_t relocVAddress = atom._virtualAddr + ref.offsetInAtom();
+ 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(location, relocVAddress, targetVAddress, ref.addend(), 21);
+ relocBNPCREL(loc, reloc, target, ref.addend(), 21);
break;
case R_HEX_B15_PCREL:
- relocBNPCREL(location, relocVAddress, targetVAddress, ref.addend(), 14);
+ relocBNPCREL(loc, reloc, target, ref.addend(), 14);
break;
case R_HEX_B9_PCREL:
- relocBNPCREL(location, relocVAddress, targetVAddress, ref.addend(), 8);
+ relocBNPCREL(loc, reloc, target, ref.addend(), 8);
break;
case R_HEX_LO16:
- relocLO16(location, relocVAddress, targetVAddress, ref.addend());
+ relocLO16(loc, reloc, target, ref.addend());
break;
case R_HEX_HI16:
- relocHI16(location, relocVAddress, targetVAddress, ref.addend());
+ relocHI16(loc, reloc, target, ref.addend());
break;
case R_HEX_32:
- reloc32(location, relocVAddress, targetVAddress, ref.addend());
+ reloc32(loc, reloc, target, ref.addend());
break;
case R_HEX_32_6_X:
- reloc32_6_X(location, relocVAddress, targetVAddress, ref.addend());
+ reloc32_6_X(loc, reloc, target, ref.addend());
break;
case R_HEX_B32_PCREL_X:
- relocHexB32PCRELX(location, relocVAddress, targetVAddress, ref.addend());
+ relocHexB32PCRELX(loc, reloc, target, ref.addend());
break;
case R_HEX_B22_PCREL_X:
- relocHexBNPCRELX(location, relocVAddress, targetVAddress, ref.addend(), 21);
+ relocHexBNPCRELX(loc, reloc, target, ref.addend(), 21);
break;
case R_HEX_B15_PCREL_X:
- relocHexBNPCRELX(location, relocVAddress, targetVAddress, ref.addend(), 14);
+ relocHexBNPCRELX(loc, reloc, target, ref.addend(), 14);
break;
case R_HEX_B13_PCREL_X:
- relocHexBNPCRELX(location, relocVAddress, targetVAddress, ref.addend(), 12);
+ relocHexBNPCRELX(loc, reloc, target, ref.addend(), 12);
break;
case R_HEX_B9_PCREL_X:
- relocHexBNPCRELX(location, relocVAddress, targetVAddress, ref.addend(), 8);
+ relocHexBNPCRELX(loc, reloc, target, ref.addend(), 8);
break;
case R_HEX_B7_PCREL_X:
- relocHexBNPCRELX(location, relocVAddress, targetVAddress, ref.addend(), 6);
+ relocHexBNPCRELX(loc, reloc, target, ref.addend(), 6);
break;
case R_HEX_GPREL16_0:
- relocHexGPRELN(location, relocVAddress, targetVAddress, ref.addend(),
- _hexagonTargetLayout.getSDataSection()->virtualAddr(), 0);
+ relocHexGPRELN(loc, reloc, target, ref.addend(),
+ _targetLayout.getSDataSection()->virtualAddr(), 0);
break;
case R_HEX_GPREL16_1:
- relocHexGPRELN(location, relocVAddress, targetVAddress, ref.addend(),
- _hexagonTargetLayout.getSDataSection()->virtualAddr(), 1);
+ relocHexGPRELN(loc, reloc, target, ref.addend(),
+ _targetLayout.getSDataSection()->virtualAddr(), 1);
break;
case R_HEX_GPREL16_2:
- relocHexGPRELN(location, relocVAddress, targetVAddress, ref.addend(),
- _hexagonTargetLayout.getSDataSection()->virtualAddr(), 2);
+ relocHexGPRELN(loc, reloc, target, ref.addend(),
+ _targetLayout.getSDataSection()->virtualAddr(), 2);
break;
case R_HEX_GPREL16_3:
- relocHexGPRELN(location, relocVAddress, targetVAddress, ref.addend(),
- _hexagonTargetLayout.getSDataSection()->virtualAddr(), 3);
+ relocHexGPRELN(loc, reloc, target, ref.addend(),
+ _targetLayout.getSDataSection()->virtualAddr(), 3);
break;
case R_HEX_16_X:
case R_HEX_12_X:
@@ -284,62 +271,55 @@ std::error_code HexagonTargetRelocationHandler::applyRelocation(
case R_HEX_8_X:
case R_HEX_7_X:
case R_HEX_6_X:
- relocHex_N_X(location, relocVAddress, targetVAddress, ref.addend());
+ relocHex_N_X(loc, reloc, target, ref.addend());
break;
case R_HEX_6_PCREL_X:
- relocHex6PCRELX(location, relocVAddress, targetVAddress, ref.addend());
+ 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(location, relocVAddress, targetVAddress, ref.addend(),
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOTREL_32(loc, reloc, target, ref.addend(),
+ _targetLayout.getGOTSymAddr());
break;
case R_HEX_GOTREL_LO16:
- relocHexGOTREL_HILO16(location, relocVAddress, targetVAddress, ref.addend(),
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOTREL_HILO16(loc, reloc, target, ref.addend(),
+ _targetLayout.getGOTSymAddr(), 0);
break;
case R_HEX_GOTREL_HI16:
- relocHexGOTREL_HILO16(location, relocVAddress, targetVAddress, ref.addend(),
- _hexagonTargetLayout.getGOTSymAddr(), 16);
+ relocHexGOTREL_HILO16(loc, reloc, target, ref.addend(),
+ _targetLayout.getGOTSymAddr(), 16);
break;
case R_HEX_GOT_LO16:
- relocHexGOTLO16(location, targetVAddress,
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOTLO16(loc, target, _targetLayout.getGOTSymAddr());
break;
case R_HEX_GOT_HI16:
- relocHexGOTHI16(location, targetVAddress,
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOTHI16(loc, target, _targetLayout.getGOTSymAddr());
break;
case R_HEX_GOT_32:
- relocHexGOT32(location, targetVAddress,
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOT32(loc, target, _targetLayout.getGOTSymAddr());
break;
case R_HEX_GOT_16:
- relocHexGOT16(location, targetVAddress,
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOT16(loc, target, _targetLayout.getGOTSymAddr());
break;
case R_HEX_GOT_32_6_X:
- relocHexGOT32_6_X(location, targetVAddress,
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOT32_6_X(loc, target, _targetLayout.getGOTSymAddr());
break;
case R_HEX_GOT_16_X:
- relocHexGOT16_X(location, targetVAddress,
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOT16_X(loc, target, _targetLayout.getGOTSymAddr());
break;
case R_HEX_GOT_11_X:
- relocHexGOT11_X(location, targetVAddress,
- _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOT11_X(loc, target, _targetLayout.getGOTSymAddr());
break;
case R_HEX_GOTREL_32_6_X:
- relocHexGOTRELSigned(location, relocVAddress, targetVAddress, ref.addend(),
- _hexagonTargetLayout.getGOTSymAddr(), 6);
+ relocHexGOTRELSigned(loc, reloc, target, ref.addend(),
+ _targetLayout.getGOTSymAddr(), 6);
break;
case R_HEX_GOTREL_16_X:
case R_HEX_GOTREL_11_X:
- relocHexGOTRELUnsigned(location, relocVAddress, targetVAddress,
- ref.addend(), _hexagonTargetLayout.getGOTSymAddr());
+ relocHexGOTRELUnsigned(loc, reloc, target, ref.addend(),
+ _targetLayout.getGOTSymAddr());
break;
default:
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h b/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h
index 4795d0264b9c..6afba0ddb8f3 100644
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h
+++ b/lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h
@@ -9,26 +9,24 @@
#ifndef LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_RELOCATION_HANDLER_H
#define LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_RELOCATION_HANDLER_H
-#include "HexagonSectionChunks.h"
-#include "HexagonTargetHandler.h"
-#include "lld/ReaderWriter/RelocationHelperFunctions.h"
+#include "lld/ReaderWriter/ELFLinkingContext.h"
namespace lld {
namespace elf {
-
class HexagonTargetHandler;
+class HexagonTargetLayout;
class HexagonTargetRelocationHandler final : public TargetRelocationHandler {
public:
- HexagonTargetRelocationHandler(HexagonTargetLayout<HexagonELFType> &layout)
- : _hexagonTargetLayout(layout) {}
+ HexagonTargetRelocationHandler(HexagonTargetLayout &layout)
+ : _targetLayout(layout) {}
std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
- const lld::AtomLayout &,
+ const AtomLayout &,
const Reference &) const override;
private:
- HexagonTargetLayout<HexagonELFType> &_hexagonTargetLayout;
+ HexagonTargetLayout &_targetLayout;
};
} // elf
} // lld
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonSectionChunks.h b/lib/ReaderWriter/ELF/Hexagon/HexagonSectionChunks.h
deleted file mode 100644
index 5b3fbbbd899b..000000000000
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonSectionChunks.h
+++ /dev/null
@@ -1,86 +0,0 @@
-//===- lib/ReaderWriter/ELF/Hexagon/HexagonSectionChunks.h-----------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-#ifndef HEXAGON_SECTION_CHUNKS_H
-#define HEXAGON_SECTION_CHUNKS_H
-
-#include "HexagonTargetHandler.h"
-
-namespace lld {
-namespace elf {
-template <typename ELFT> class HexagonTargetLayout;
-class HexagonLinkingContext;
-
-/// \brief Handle Hexagon SData section
-template <class HexagonELFType>
-class SDataSection : public AtomSection<HexagonELFType> {
-public:
- SDataSection(const HexagonLinkingContext &context)
- : AtomSection<HexagonELFType>(
- context, ".sdata", DefinedAtom::typeDataFast, 0,
- HexagonTargetLayout<HexagonELFType>::ORDER_SDATA) {
- this->_type = SHT_PROGBITS;
- this->_flags = SHF_ALLOC | SHF_WRITE;
- this->_alignment = 4096;
- }
-
- /// \brief Finalize the section contents before writing
- virtual void doPreFlight();
-
- /// \brief Does this section have an output segment.
- virtual bool hasOutputSegment() { return true; }
-
- const lld::AtomLayout *appendAtom(const Atom *atom) {
- const DefinedAtom *definedAtom = cast<DefinedAtom>(atom);
- DefinedAtom::Alignment atomAlign = definedAtom->alignment();
- uint64_t alignment = 1u << atomAlign.powerOf2;
- this->_atoms.push_back(new (this->_alloc) lld::AtomLayout(atom, 0, 0));
- // Set the section alignment to the largest alignment
- // std::max doesn't support uint64_t
- if (this->_alignment < alignment)
- this->_alignment = alignment;
- return (this->_atoms.back());
- }
-
-}; // SDataSection
-
-template <class HexagonELFType>
-void SDataSection<HexagonELFType>::doPreFlight() {
- // sort the atoms on the alignments they have been set
- std::stable_sort(this->_atoms.begin(), this->_atoms.end(),
- [](const lld::AtomLayout * A,
- const lld::AtomLayout * B) {
- const DefinedAtom *definedAtomA = cast<DefinedAtom>(A->_atom);
- const DefinedAtom *definedAtomB = cast<DefinedAtom>(B->_atom);
- int64_t alignmentA = 1 << definedAtomA->alignment().powerOf2;
- int64_t alignmentB = 1 << definedAtomB->alignment().powerOf2;
- 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 : this->_atoms) {
- const DefinedAtom *definedAtom = cast<DefinedAtom>(ai->_atom);
- DefinedAtom::Alignment atomAlign = definedAtom->alignment();
- uint64_t fOffset = this->alignOffset(this->fileSize(), atomAlign);
- uint64_t mOffset = this->alignOffset(this->memSize(), atomAlign);
- ai->_fileOffset = fOffset;
- this->_fsize = fOffset + definedAtom->size();
- this->_msize = mOffset + definedAtom->size();
- }
-} // finalize
-
-} // elf
-} // lld
-
-#endif // LLD_READER_WRITER_ELF_HEXAGON_HEXAGON_SECTION_CHUNKS_H
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp b/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
index 9b10c2f160f4..6c0360c310f4 100644
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
+++ b/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp
@@ -12,29 +12,23 @@
#include "HexagonLinkingContext.h"
#include "HexagonTargetHandler.h"
-using namespace lld;
-using namespace elf;
using namespace llvm::ELF;
using llvm::makeArrayRef;
-HexagonTargetHandler::HexagonTargetHandler(HexagonLinkingContext &context)
- : _hexagonLinkingContext(context),
- _hexagonRuntimeFile(new HexagonRuntimeFile<HexagonELFType>(context)),
- _hexagonTargetLayout(new HexagonTargetLayout<HexagonELFType>(context)),
- _hexagonRelocationHandler(new HexagonTargetRelocationHandler(
- *_hexagonTargetLayout.get())) {}
+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 (_hexagonLinkingContext.getOutputELFType()) {
+ switch (_ctx.getOutputELFType()) {
case llvm::ELF::ET_EXEC:
- return std::unique_ptr<Writer>(
- new elf::HexagonExecutableWriter<HexagonELFType>(
- _hexagonLinkingContext, *_hexagonTargetLayout.get()));
+ return llvm::make_unique<HexagonExecutableWriter>(_ctx, *_targetLayout);
case llvm::ELF::ET_DYN:
- return std::unique_ptr<Writer>(
- new elf::HexagonDynamicLibraryWriter<HexagonELFType>(
- _hexagonLinkingContext, *_hexagonTargetLayout.get()));
+ return llvm::make_unique<HexagonDynamicLibraryWriter>(_ctx, *_targetLayout);
case llvm::ELF::ET_REL:
llvm_unreachable("TODO: support -r mode");
default:
@@ -77,7 +71,7 @@ public:
return makeArrayRef(hexagonGotAtomContent);
}
- Alignment alignment() const override { return Alignment(2); }
+ Alignment alignment() const override { return 4; }
};
class HexagonGOTPLTAtom : public GOTAtom {
@@ -88,7 +82,7 @@ public:
return makeArrayRef(hexagonGotPltAtomContent);
}
- Alignment alignment() const override { return Alignment(2); }
+ Alignment alignment() const override { return 4; }
};
class HexagonGOTPLT0Atom : public GOTAtom {
@@ -99,7 +93,7 @@ public:
return makeArrayRef(hexagonGotPlt0AtomContent);
}
- Alignment alignment() const override { return Alignment(3); }
+ Alignment alignment() const override { return 8; }
};
class HexagonPLT0Atom : public PLT0Atom {
@@ -165,8 +159,7 @@ protected:
}
public:
- GOTPLTPass(const ELFLinkingContext &ctx)
- : _file(ctx), _null(nullptr), _PLT0(nullptr), _got0(nullptr) {}
+ GOTPLTPass(const ELFLinkingContext &ctx) : _file(ctx) {}
/// \brief Do the pass.
///
@@ -176,34 +169,36 @@ public:
///
/// After all references are handled, the atoms created during that are all
/// added to mf.
- void perform(std::unique_ptr<MutableFile> &mf) override {
+ std::error_code perform(SimpleFile &mf) override {
// Process all references.
- for (const auto &atom : mf->defined())
+ 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);
+ if (_plt0) {
+ _plt0->setOrdinal(ordinal++);
+ mf.addAtom(*_plt0);
}
for (auto &plt : _pltVector) {
plt->setOrdinal(ordinal++);
- mf->addAtom(*plt);
+ mf.addAtom(*plt);
}
if (_null) {
_null->setOrdinal(ordinal++);
- mf->addAtom(*_null);
+ mf.addAtom(*_null);
}
if (_got0) {
_got0->setOrdinal(ordinal++);
- mf->addAtom(*_got0);
+ mf.addAtom(*_got0);
}
for (auto &got : _gotVector) {
got->setOrdinal(ordinal++);
- mf->addAtom(*got);
+ mf.addAtom(*got);
}
+
+ return std::error_code();
}
protected:
@@ -221,19 +216,19 @@ protected:
std::vector<PLTAtom *> _pltVector;
/// \brief GOT entry that is always 0. Used for undefined weaks.
- GOTAtom *_null;
+ 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;
- GOTAtom *_got0;
+ PLT0Atom *_plt0 = nullptr;
+ GOTAtom *_got0 = nullptr;
/// @}
};
class DynamicGOTPLTPass final : public GOTPLTPass<DynamicGOTPLTPass> {
public:
- DynamicGOTPLTPass(const elf::HexagonLinkingContext &ctx) : GOTPLTPass(ctx) {
+ DynamicGOTPLTPass(const HexagonLinkingContext &ctx) : GOTPLTPass(ctx) {
_got0 = new (_file._alloc) HexagonGOTPLT0Atom(_file);
#ifndef NDEBUG
_got0->_name = "__got0";
@@ -241,14 +236,14 @@ public:
}
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);
+ 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;
+ return _plt0;
}
const PLTAtom *getPLTEntry(const Atom *a) {
@@ -313,22 +308,75 @@ public:
}
};
-void elf::HexagonLinkingContext::addPasses(PassManager &pm) {
+void HexagonLinkingContext::addPasses(PassManager &pm) {
if (isDynamic())
pm.add(llvm::make_unique<DynamicGOTPLTPass>(*this));
ELFLinkingContext::addPasses(pm);
}
-void HexagonTargetHandler::registerRelocationNames(Registry &registry) {
- registry.addKindTable(Reference::KindNamespace::ELF,
- Reference::KindArch::Hexagon, kindStrings);
+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;
}
-#define ELF_RELOC(name, value) LLD_KIND_STRING_ENTRY(name),
+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();
+}
-const Registry::KindStrings HexagonTargetHandler::kindStrings[] = {
-#include "llvm/Support/ELFRelocs/Hexagon.def"
- LLD_KIND_STRING_END
-};
+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;
+}
-#undef ELF_RELOC
+} // namespace elf
+} // namespace lld
diff --git a/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h b/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h
index f4315f710ec7..b1366bed09ea 100644
--- a/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h
+++ b/lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h
@@ -10,44 +10,51 @@
#ifndef HEXAGON_TARGET_HANDLER_H
#define HEXAGON_TARGET_HANDLER_H
-#include "DefaultTargetHandler.h"
-#include "HexagonELFReader.h"
-#include "HexagonExecutableAtoms.h"
+#include "ELFReader.h"
+#include "HexagonELFFile.h"
#include "HexagonRelocationHandler.h"
-#include "HexagonSectionChunks.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
-template <class HexagonELFType>
-class HexagonTargetLayout final : public TargetLayout<HexagonELFType> {
+class HexagonTargetLayout final : public TargetLayout<ELF32LE> {
public:
enum HexagonSectionOrder {
ORDER_SDATA = 205
};
- HexagonTargetLayout(HexagonLinkingContext &hti)
- : TargetLayout<HexagonELFType>(hti), _sdataSection(nullptr),
- _gotSymAtom(nullptr), _cachedGotSymAtom(false) {
- _sdataSection = new (_alloc) SDataSection<HexagonELFType>(hti);
- }
+ HexagonTargetLayout(HexagonLinkingContext &ctx)
+ : TargetLayout(ctx), _sdataSection(ctx) {}
/// \brief Return the section order for a input section
- virtual Layout::SectionOrder getSectionOrder(
- StringRef name, int32_t contentType, int32_t contentPermissions) {
- if ((contentType == DefinedAtom::typeDataFast) ||
- (contentType == DefinedAtom::typeZeroFillFast))
+ TargetLayout::SectionOrder
+ getSectionOrder(StringRef name, int32_t contentType,
+ int32_t contentPermissions) override {
+ if (contentType == DefinedAtom::typeDataFast ||
+ contentType == DefinedAtom::typeZeroFillFast)
return ORDER_SDATA;
-
- return DefaultLayout<HexagonELFType>::getSectionOrder(name, contentType,
- contentPermissions);
+ return TargetLayout::getSectionOrder(name, contentType, contentPermissions);
}
/// \brief Return the appropriate input section name.
- virtual StringRef getInputSectionName(const DefinedAtom *da) const {
+ StringRef getInputSectionName(const DefinedAtom *da) const override {
switch (da->contentType()) {
case DefinedAtom::typeDataFast:
case DefinedAtom::typeZeroFillFast:
@@ -55,88 +62,72 @@ public:
default:
break;
}
- return DefaultLayout<HexagonELFType>::getInputSectionName(da);
+ return TargetLayout::getInputSectionName(da);
}
/// \brief Gets or creates a section.
- virtual AtomSection<HexagonELFType> *
+ AtomSection<ELF32LE> *
createSection(StringRef name, int32_t contentType,
DefinedAtom::ContentPermissions contentPermissions,
- Layout::SectionOrder sectionOrder) {
- if ((contentType == DefinedAtom::typeDataFast) ||
- (contentType == DefinedAtom::typeZeroFillFast))
- return _sdataSection;
- return DefaultLayout<HexagonELFType>::createSection(
- name, contentType, contentPermissions, sectionOrder);
+ 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
- virtual Layout::SegmentType
- getSegmentType(Section<HexagonELFType> *section) const {
+ TargetLayout::SegmentType
+ getSegmentType(const Section<ELF32LE> *section) const override {
if (section->order() == ORDER_SDATA)
return PT_LOAD;
-
- return DefaultLayout<HexagonELFType>::getSegmentType(section);
+ return TargetLayout::getSegmentType(section);
}
- Section<HexagonELFType> *getSDataSection() const {
- return _sdataSection;
- }
+ Section<ELF32LE> *getSDataSection() { return &_sdataSection; }
uint64_t getGOTSymAddr() {
- if (!_cachedGotSymAtom) {
- auto gotAtomIter = this->findAbsoluteAtom("_GLOBAL_OFFSET_TABLE_");
- _gotSymAtom = (*gotAtomIter);
- _cachedGotSymAtom = true;
- }
- if (_gotSymAtom)
- return _gotSymAtom->_virtualAddr;
- return 0;
+ std::call_once(_gotOnce, [this]() {
+ if (AtomLayout *got = findAbsoluteAtom("_GLOBAL_OFFSET_TABLE_"))
+ _gotAddr = got->_virtualAddr;
+ });
+ return _gotAddr;
}
private:
- llvm::BumpPtrAllocator _alloc;
- SDataSection<HexagonELFType> *_sdataSection;
- AtomLayout *_gotSymAtom;
- bool _cachedGotSymAtom;
+ SDataSection _sdataSection;
+ uint64_t _gotAddr = 0;
+ std::once_flag _gotOnce;
};
/// \brief TargetHandler for Hexagon
-class HexagonTargetHandler final :
- public DefaultTargetHandler<HexagonELFType> {
+class HexagonTargetHandler final : public TargetHandler {
public:
HexagonTargetHandler(HexagonLinkingContext &targetInfo);
- void registerRelocationNames(Registry &registry) override;
-
- const HexagonTargetRelocationHandler &getRelocationHandler() const override {
- return *(_hexagonRelocationHandler.get());
- }
-
- HexagonTargetLayout<HexagonELFType> &getTargetLayout() override {
- return *(_hexagonTargetLayout.get());
+ const TargetRelocationHandler &getRelocationHandler() const override {
+ return *_relocationHandler;
}
std::unique_ptr<Reader> getObjReader() override {
- return std::unique_ptr<Reader>(
- new HexagonELFObjectReader(_hexagonLinkingContext));
+ return llvm::make_unique<ELFReader<HexagonELFFile>>(_ctx);
}
std::unique_ptr<Reader> getDSOReader() override {
- return std::unique_ptr<Reader>(
- new HexagonELFDSOReader(_hexagonLinkingContext));
+ return llvm::make_unique<ELFReader<DynamicFile<ELF32LE>>>(_ctx);
}
std::unique_ptr<Writer> getWriter() override;
private:
- llvm::BumpPtrAllocator _alloc;
- static const Registry::KindStrings kindStrings[];
- HexagonLinkingContext &_hexagonLinkingContext;
- std::unique_ptr<HexagonRuntimeFile<HexagonELFType> > _hexagonRuntimeFile;
- std::unique_ptr<HexagonTargetLayout<HexagonELFType>> _hexagonTargetLayout;
- std::unique_ptr<HexagonTargetRelocationHandler> _hexagonRelocationHandler;
+ HexagonLinkingContext &_ctx;
+ std::unique_ptr<HexagonTargetLayout> _targetLayout;
+ std::unique_ptr<HexagonTargetRelocationHandler> _relocationHandler;
};
+
+void finalizeHexagonRuntimeAtomValues(HexagonTargetLayout &layout);
+
} // end namespace elf
} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/Hexagon/Makefile b/lib/ReaderWriter/ELF/Hexagon/Makefile
deleted file mode 100644
index 8d6f1a0a3b1e..000000000000
--- a/lib/ReaderWriter/ELF/Hexagon/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-##===- lld/lib/ReaderWriter/ELF/Hexagon/Makefile ----------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL := ../../../..
-LIBRARYNAME := lldHexagonELFTarget
-USEDLIBS = lldCore.a
-
-CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF/Hexagon -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF
-
-include $(LLD_LEVEL)/Makefile
diff --git a/lib/ReaderWriter/ELF/Layout.h b/lib/ReaderWriter/ELF/Layout.h
deleted file mode 100644
index 826cf5035d59..000000000000
--- a/lib/ReaderWriter/ELF/Layout.h
+++ /dev/null
@@ -1,59 +0,0 @@
-//===- lib/ReaderWriter/ELF/Layout.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_LAYOUT_H
-#define LLD_READER_WRITER_ELF_LAYOUT_H
-
-#include "lld/Core/DefinedAtom.h"
-#include "lld/ReaderWriter/AtomLayout.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/ErrorOr.h"
-
-namespace lld {
-namespace elf {
-
-/// \brief The ELFLayout is an abstract class for managing the final layout for
-/// the kind of binaries(Shared Libraries / Relocatables / Executables 0
-/// Each architecture (Hexagon, MIPS) would have a concrete
-/// subclass derived from Layout for generating each binary thats
-// needed by the lld linker
-class Layout {
-public:
- typedef uint32_t SectionOrder;
- typedef uint32_t SegmentType;
- typedef uint32_t Flags;
-
-public:
- /// Return the order the section would appear in the output file
- virtual SectionOrder getSectionOrder(StringRef name, int32_t contentType,
- int32_t contentPerm) = 0;
- /// \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 lld::AtomLayout *> addAtom(const Atom *atom) = 0;
- /// find the Atom in the current layout
- virtual const AtomLayout *findAtomLayoutByName(StringRef name) const = 0;
- /// associates a section to a segment
- virtual void assignSectionsToSegments() = 0;
- /// associates a virtual address to the segment, section, and the atom
- virtual void assignVirtualAddress() = 0;
-
-public:
- Layout() {}
-
- virtual ~Layout() { }
-};
-} // end namespace elf
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Makefile b/lib/ReaderWriter/ELF/Makefile
deleted file mode 100644
index 5791ecb9733d..000000000000
--- a/lib/ReaderWriter/ELF/Makefile
+++ /dev/null
@@ -1,18 +0,0 @@
-##===- lld/lib/ReaderWriter/ELF/Makefile --------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL := ../../..
-LIBRARYNAME := lldELF
-
-CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF
-
-# these link against this lib
-PARALLEL_DIRS := Hexagon X86 X86_64 Mips AArch64 ARM
-
-include $(LLD_LEVEL)/Makefile
diff --git a/lib/ReaderWriter/ELF/Mips/CMakeLists.txt b/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
index d982508b7ddc..434e310640bd 100644
--- a/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
+++ b/lib/ReaderWriter/ELF/Mips/CMakeLists.txt
@@ -1,10 +1,14 @@
add_llvm_library(lldMipsELFTarget
+ MipsAbiInfoHandler.cpp
MipsCtorsOrderPass.cpp
- MipsELFFlagsMerger.cpp
+ MipsELFFile.cpp
+ MipsELFWriters.cpp
MipsLinkingContext.cpp
MipsRelocationHandler.cpp
MipsRelocationPass.cpp
+ MipsSectionChunks.cpp
MipsTargetHandler.cpp
+ MipsTargetLayout.cpp
LINK_LIBS
lldELF
lldReaderWriter
diff --git a/lib/ReaderWriter/ELF/Mips/Makefile b/lib/ReaderWriter/ELF/Mips/Makefile
deleted file mode 100644
index 0b2f4ff82279..000000000000
--- a/lib/ReaderWriter/ELF/Mips/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-##===- lld/lib/ReaderWriter/ELF/Mips/Makefile ----------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL := ../../../..
-LIBRARYNAME := lldMipsELFTarget
-USEDLIBS = lldCore.a
-CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF
-
-include $(LLD_LEVEL)/Makefile
diff --git a/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp b/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp
new file mode 100644
index 000000000000..ad4e62e64680
--- /dev/null
+++ b/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp
@@ -0,0 +1,675 @@
+//===- 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
new file mode 100644
index 000000000000..44da29f09214
--- /dev/null
+++ b/lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h
@@ -0,0 +1,83 @@
+//===- 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
index 8bf80257fc89..a7062813df42 100644
--- a/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.cpp
+++ b/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.cpp
@@ -8,6 +8,7 @@
//===----------------------------------------------------------------------===//
#include "MipsCtorsOrderPass.h"
+#include "lld/Core/Simple.h"
#include <algorithm>
#include <climits>
@@ -48,8 +49,8 @@ static int32_t getSectionPriority(StringRef path, StringRef sectionName) {
return priority;
}
-void MipsCtorsOrderPass::perform(std::unique_ptr<MutableFile> &f) {
- auto definedAtoms = f->definedAtoms();
+std::error_code MipsCtorsOrderPass::perform(SimpleFile &f) {
+ auto definedAtoms = f.definedAtoms();
auto last = std::stable_partition(definedAtoms.begin(), definedAtoms.end(),
[](const DefinedAtom *atom) {
@@ -70,4 +71,6 @@ void MipsCtorsOrderPass::perform(std::unique_ptr<MutableFile> &f) {
return leftPriority < rightPriority;
});
+
+ return std::error_code();
}
diff --git a/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.h b/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.h
index eeb1a194f9c7..5b12b7de0fa2 100644
--- a/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.h
+++ b/lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.h
@@ -17,7 +17,7 @@ namespace elf {
/// \brief This pass sorts atoms in .{ctors,dtors}.<priority> sections.
class MipsCtorsOrderPass : public Pass {
public:
- void perform(std::unique_ptr<MutableFile> &mergedFile) override;
+ std::error_code perform(SimpleFile &mergedFile) override;
};
}
}
diff --git a/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h b/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h
deleted file mode 100644
index 30b5b0ba6dae..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.h
+++ /dev/null
@@ -1,101 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsDynamicLibraryWriter.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_LIBRARY_WRITER_H
-#define LLD_READER_WRITER_ELF_MIPS_MIPS_DYNAMIC_LIBRARY_WRITER_H
-
-#include "DynamicLibraryWriter.h"
-#include "MipsDynamicTable.h"
-#include "MipsELFWriters.h"
-#include "MipsLinkingContext.h"
-
-namespace lld {
-namespace elf {
-
-template <typename ELFT> class MipsSymbolTable;
-template <typename ELFT> class MipsDynamicSymbolTable;
-template <typename ELFT> class MipsTargetLayout;
-
-template <class ELFT>
-class MipsDynamicLibraryWriter : public DynamicLibraryWriter<ELFT> {
-public:
- MipsDynamicLibraryWriter(MipsLinkingContext &ctx,
- MipsTargetLayout<ELFT> &layout);
-
-protected:
- // Add any runtime files and their atoms to the output
- bool createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-
- void finalizeDefaultAtomValues() override;
-
- std::error_code setELFHeader() override {
- DynamicLibraryWriter<ELFT>::setELFHeader();
- _writeHelper.setELFHeader(*this->_elfHeader);
- return std::error_code();
- }
-
- 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> &_mipsTargetLayout;
-};
-
-template <class ELFT>
-MipsDynamicLibraryWriter<ELFT>::MipsDynamicLibraryWriter(
- MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout)
- : DynamicLibraryWriter<ELFT>(ctx, layout), _writeHelper(ctx, layout),
- _mipsTargetLayout(layout) {}
-
-template <class ELFT>
-bool MipsDynamicLibraryWriter<ELFT>::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &result) {
- DynamicLibraryWriter<ELFT>::createImplicitFiles(result);
- result.push_back(std::move(_writeHelper.createRuntimeFile()));
- return true;
-}
-
-template <class ELFT>
-void MipsDynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues() {
- // Finalize the atom values that are part of the parent.
- DynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues();
- _writeHelper.finalizeMipsRuntimeAtomValues();
-}
-
-template <class ELFT>
-unique_bump_ptr<SymbolTable<ELFT>>
- MipsDynamicLibraryWriter<ELFT>::createSymbolTable() {
- return unique_bump_ptr<SymbolTable<ELFT>>(new (
- this->_alloc) MipsSymbolTable<ELFT>(this->_context));
-}
-
-/// \brief create dynamic table
-template <class ELFT>
-unique_bump_ptr<DynamicTable<ELFT>>
- MipsDynamicLibraryWriter<ELFT>::createDynamicTable() {
- return unique_bump_ptr<DynamicTable<ELFT>>(new (
- this->_alloc) MipsDynamicTable<ELFT>(this->_context, _mipsTargetLayout));
-}
-
-/// \brief create dynamic symbol table
-template <class ELFT>
-unique_bump_ptr<DynamicSymbolTable<ELFT>>
- MipsDynamicLibraryWriter<ELFT>::createDynamicSymbolTable() {
- return unique_bump_ptr<DynamicSymbolTable<ELFT>>(
- new (this->_alloc) MipsDynamicSymbolTable<ELFT>(
- this->_context, _mipsTargetLayout));
-}
-
-} // namespace elf
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h b/lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h
index 2b9562f42b57..480c69cf4600 100644
--- a/lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h
+++ b/lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h
@@ -9,83 +9,89 @@
#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_DYNAMIC_TABLE_H
#define LLD_READER_WRITER_ELF_MIPS_MIPS_DYNAMIC_TABLE_H
-#include "DefaultLayout.h"
+#include "TargetLayout.h"
#include "SectionChunks.h"
namespace lld {
namespace elf {
-template <class ELFType> class MipsTargetLayout;
+template <class ELFT> class MipsTargetLayout;
-template <class MipsELFType>
-class MipsDynamicTable : public DynamicTable<MipsELFType> {
+template <class ELFT> class MipsDynamicTable : public DynamicTable<ELFT> {
public:
- MipsDynamicTable(const ELFLinkingContext &ctx,
- MipsTargetLayout<MipsELFType> &layout)
- : DynamicTable<MipsELFType>(ctx, layout, ".dynamic",
- DefaultLayout<MipsELFType>::ORDER_DYNAMIC),
- _mipsTargetLayout(layout) {}
+ MipsDynamicTable(const ELFLinkingContext &ctx, MipsTargetLayout<ELFT> &layout)
+ : DynamicTable<ELFT>(ctx, layout, ".dynamic",
+ TargetLayout<ELFT>::ORDER_DYNAMIC),
+ _targetLayout(layout) {}
void createDefaultEntries() override {
- DynamicTable<MipsELFType>::createDefaultEntries();
-
- typename DynamicTable<MipsELFType>::Elf_Dyn dyn;
+ DynamicTable<ELFT>::createDefaultEntries();
// Version id for the Runtime Linker Interface.
- dyn.d_un.d_val = 1;
- dyn.d_tag = DT_MIPS_RLD_VERSION;
- this->addEntry(dyn);
+ 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.
- dyn.d_un.d_val = RHF_NOTPOT;
- dyn.d_tag = DT_MIPS_FLAGS;
- this->addEntry(dyn);
+ this->addEntry(DT_MIPS_FLAGS, RHF_NOTPOT);
// The base address of the segment.
- dyn.d_un.d_ptr = 0;
- dyn.d_tag = DT_MIPS_BASE_ADDRESS;
- _dt_baseaddr = this->addEntry(dyn);
+ _dt_baseaddr = this->addEntry(DT_MIPS_BASE_ADDRESS, 0);
// Number of local global offset table entries.
- dyn.d_un.d_val = 0;
- dyn.d_tag = DT_MIPS_LOCAL_GOTNO;
- _dt_localgot = this->addEntry(dyn);
+ _dt_localgot = this->addEntry(DT_MIPS_LOCAL_GOTNO, 0);
// Number of entries in the .dynsym section.
- dyn.d_un.d_val = 0;
- dyn.d_tag = DT_MIPS_SYMTABNO;
- _dt_symtabno = this->addEntry(dyn);
+ _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.
- dyn.d_un.d_val = 0;
- dyn.d_tag = DT_MIPS_GOTSYM;
- _dt_gotsym = this->addEntry(dyn);
+ _dt_gotsym = this->addEntry(DT_MIPS_GOTSYM, 0);
// Address of the .got section.
- dyn.d_un.d_val = 0;
- dyn.d_tag = DT_PLTGOT;
- _dt_pltgot = this->addEntry(dyn);
+ _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<MipsELFType>::updateDynamicTable();
+ 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 : _mipsTargetLayout.segments())
+ 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 = _mipsTargetLayout.getGOTSection();
+ 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->getSymbolTable()->size() - got.getGlobalCount();
this->_entries[_dt_localgot].d_un.d_val = got.getLocalCount();
- this->_entries[_dt_pltgot].d_un.d_ptr =
- _mipsTargetLayout.findOutputSection(".got")->virtualAddr();
+ 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; }
@@ -106,7 +112,10 @@ private:
std::size_t _dt_gotsym;
std::size_t _dt_pltgot;
std::size_t _dt_baseaddr;
- MipsTargetLayout<MipsELFType> &_mipsTargetLayout;
+ std::size_t _dt_options;
+ std::size_t _dt_rldmap;
+ std::size_t _dt_rldmaprel;
+ MipsTargetLayout<ELFT> &_targetLayout;
};
} // end namespace elf
diff --git a/lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp b/lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp
new file mode 100644
index 000000000000..b081b63d77f7
--- /dev/null
+++ b/lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp
@@ -0,0 +1,348 @@
+//===- 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
index 7381c7e977bf..934934b539cc 100644
--- a/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
+++ b/lib/ReaderWriter/ELF/Mips/MipsELFFile.h
@@ -12,42 +12,7 @@
#include "ELFReader.h"
#include "MipsLinkingContext.h"
#include "MipsRelocationHandler.h"
-
-namespace llvm {
-namespace object {
-
-template <class ELFT>
-struct Elf_RegInfo;
-
-template <llvm::support::endianness TargetEndianness, std::size_t MaxAlign>
-struct Elf_RegInfo<ELFType<TargetEndianness, MaxAlign, false>> {
- LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, false)
- Elf_Word ri_gprmask; // bit-mask of used general registers
- Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers
- Elf_Addr ri_gp_value; // gp register value
-};
-
-template <llvm::support::endianness TargetEndianness, std::size_t MaxAlign>
-struct Elf_RegInfo<ELFType<TargetEndianness, MaxAlign, true>> {
- LLVM_ELF_IMPORT_TYPES(TargetEndianness, MaxAlign, true)
- Elf_Word ri_gprmask; // bit-mask of used general registers
- Elf_Word ri_pad; // unused padding field
- Elf_Word ri_cprmask[4]; // bit-mask of used co-processor registers
- Elf_Addr ri_gp_value; // gp register value
-};
-
-template <class ELFT> struct Elf_Mips_Options {
- LLVM_ELF_IMPORT_TYPES(ELFT::TargetEndianness, ELFT::MaxAlignment,
- ELFT::Is64Bits)
- uint8_t kind; // Determines interpretation of variable part of descriptor
- uint8_t size; // Byte size of descriptor, including this header
- Elf_Half section; // Section header index of section affected,
- // or 0 for global options
- Elf_Word info; // Kind-specific information
-};
-
-} // end namespace object.
-} // end namespace llvm.
+#include "llvm/ADT/STLExtras.h"
namespace lld {
namespace elf {
@@ -64,50 +29,21 @@ public:
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) {}
+ std::vector<ELFReference<ELFT> *> &referenceList);
- const MipsELFFile<ELFT>& file() const override {
- return static_cast<const MipsELFFile<ELFT> &>(this->_owningFile);
- }
+ const MipsELFFile<ELFT>& file() const override;
+ DefinedAtom::CodeModel codeModel() const override;
- DefinedAtom::CodeModel codeModel() const override {
- 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;
- }
- }
+ 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;
- static const bool _isMips64EL =
- ELFT::Is64Bits && ELFT::TargetEndianness == llvm::support::little;
-
public:
- MipsELFReference(uint64_t symValue, const Elf_Rela &rel)
- : ELFReference<ELFT>(
- &rel, rel.r_offset - symValue, Reference::KindArch::Mips,
- rel.getType(_isMips64EL) & 0xff, rel.getSymbol(_isMips64EL)),
- _tag(uint32_t(rel.getType(_isMips64EL)) >> 8) {}
-
- MipsELFReference(uint64_t symValue, const Elf_Rel &rel)
- : ELFReference<ELFT>(rel.r_offset - symValue, Reference::KindArch::Mips,
- rel.getType(_isMips64EL) & 0xff,
- rel.getSymbol(_isMips64EL)),
- _tag(uint32_t(rel.getType(_isMips64EL)) >> 8) {}
+ 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; }
@@ -118,211 +54,70 @@ private:
template <class ELFT> class MipsELFFile : public ELFFile<ELFT> {
public:
- MipsELFFile(std::unique_ptr<MemoryBuffer> mb, MipsLinkingContext &ctx)
- : ELFFile<ELFT>(std::move(mb), ctx) {}
+ MipsELFFile(std::unique_ptr<MemoryBuffer> mb, ELFLinkingContext &ctx);
- static ErrorOr<std::unique_ptr<MipsELFFile>>
- create(std::unique_ptr<MemoryBuffer> mb, MipsLinkingContext &ctx) {
- return std::unique_ptr<MipsELFFile<ELFT>>(
- new MipsELFFile<ELFT>(std::move(mb), ctx));
- }
-
- bool isPIC() const {
- return this->_objFile->getHeader()->e_flags & llvm::ELF::EF_MIPS_PIC;
- }
+ bool isPIC() const;
/// \brief gp register value stored in the .reginfo section.
- int64_t getGP0() const { return _gp0 ? *_gp0 : 0; }
+ 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; }
+ uint64_t getTPOffset() const { return _tpOff; }
+ uint64_t getDTPOffset() const { return _dtpOff; }
protected:
- std::error_code doParse() override {
- 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();
- }
+ 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 llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rel_Iter Elf_Rel_Iter;
- typedef typename llvm::object::ELFFile<ELFT>::Elf_Rela_Iter Elf_Rela_Iter;
+ 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 };
- static const bool _isMips64EL =
- ELFT::Is64Bits && ELFT::TargetEndianness == llvm::support::little;
-
- llvm::Optional<int64_t> _gp0;
- llvm::Optional<uint64_t> _tpOff;
- llvm::Optional<uint64_t> _dtpOff;
+ int64_t _gp0 = 0;
+ uint64_t _tpOff = 0;
+ uint64_t _dtpOff = 0;
- ErrorOr<ELFDefinedAtom<ELFT> *> handleDefinedSymbol(
- 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 {
- return new (this->_readerStorage) MipsELFDefinedAtom<ELFT>(
- *this, symName, sectionName, sym, sectionHdr, contentData,
- referenceStart, referenceEnd, referenceList);
- }
-
- const Elf_Shdr *findSectionByType(uint64_t type) {
- for (const Elf_Shdr &section : this->_objFile->sections())
- if (section.sh_type == type)
- return &section;
- return nullptr;
- }
-
- const Elf_Shdr *findSectionByFlags(uint64_t flags) {
- for (const Elf_Shdr &section : this->_objFile->sections())
- if (section.sh_flags & flags)
- return &section;
- return nullptr;
- }
-
- std::error_code 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;
- }
-
- typedef llvm::object::Elf_RegInfo<ELFT> Elf_RegInfo;
- typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;
-
- 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) {
- _gp0 = reinterpret_cast<const Elf_RegInfo *>(opt + 1)->ri_gp_value;
- break;
- }
- 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_RegInfo))
- return make_dynamic_error_code(
- StringRef("Invalid size of MIPS_REGINFO section"));
-
- _gp0 = reinterpret_cast<const Elf_RegInfo *>(raw.data())->ri_gp_value;
- }
- return std::error_code();
- }
+ 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<Elf_Rela_Iter> rels) override {
- const auto value = this->getSymbolValue(symbol);
- for (const auto &rel : rels) {
- if (rel.r_offset < value || value + content.size() <= rel.r_offset)
- continue;
- auto r = new (this->_readerStorage) MipsELFReference<ELFT>(value, rel);
- this->addReferenceToSymbol(r, symbol);
- this->_references.push_back(r);
- }
- }
-
+ range<const Elf_Rela *> rels) override;
void createRelocationReferences(const Elf_Sym *symbol,
ArrayRef<uint8_t> symContent,
ArrayRef<uint8_t> secContent,
- range<Elf_Rel_Iter> rels) override {
- const auto value = this->getSymbolValue(symbol);
- for (Elf_Rel_Iter rit = rels.begin(), eit = rels.end(); rit != eit; ++rit) {
- if (rit->r_offset < value || value + symContent.size() <= rit->r_offset)
- continue;
+ const Elf_Shdr *RelSec) override;
- auto r = new (this->_readerStorage) MipsELFReference<ELFT>(value, *rit);
- this->addReferenceToSymbol(r, symbol);
- this->_references.push_back(r);
+ const Elf_Shdr *findSectionByType(uint64_t type) const;
+ const Elf_Shdr *findSectionByFlags(uint64_t flags) const;
- auto addend = readAddend(*rit, secContent);
- auto pairRelType = getPairRelocation(*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);
- }
- }
+ 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;
- Reference::Addend readAddend(const Elf_Rel &ri,
- const ArrayRef<uint8_t> content) const {
- const auto &rh =
- this->_ctx.template getTargetHandler<ELFT>().getRelocationHandler();
- return static_cast<const MipsRelocationHandler &>(rh)
- .readAddend(getPrimaryType(ri), content.data() + ri.r_offset);
- }
+ ErrorOr<const Elf_Mips_RegInfo *> findRegInfoSec() const;
+ ErrorOr<const Elf_Mips_ABIFlags*> findAbiFlagsSec() const;
- uint32_t getPairRelocation(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(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(rel))
- return llvm::ELF::R_MICROMIPS_LO16;
- break;
- default:
- // Nothing to do.
- break;
- }
- return llvm::ELF::R_MIPS_NONE;
- }
+ std::error_code readAuxData();
- Elf_Rel_Iter findMatchingRelocation(uint32_t pairRelType, Elf_Rel_Iter rit,
- Elf_Rel_Iter eit) const {
- return std::find_if(rit, eit, [&](const Elf_Rel &rel) {
- return getPrimaryType(rel) == pairRelType &&
- rel.getSymbol(_isMips64EL) == rit->getSymbol(_isMips64EL);
- });
- }
+ Reference::Addend readAddend(const Elf_Rel &ri,
+ const ArrayRef<uint8_t> content) const;
- static uint8_t getPrimaryType(const Elf_Rel &rel) {
- return rel.getType(_isMips64EL) & 0xff;
- }
- bool isLocalBinding(const Elf_Rel &rel) const {
- return this->_objFile->getSymbol(rel.getSymbol(_isMips64EL))
- ->getBinding() == llvm::ELF::STB_LOCAL;
- }
-};
+ uint32_t getPairRelocation(const Elf_Shdr *Symtab, const Elf_Rel &rel) const;
-template <class ELFT> class MipsDynamicFile : public DynamicFile<ELFT> {
-public:
- MipsDynamicFile(const MipsLinkingContext &context, StringRef name)
- : DynamicFile<ELFT>(context, name) {}
+ 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
diff --git a/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.cpp b/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.cpp
deleted file mode 100644
index 0ef2c70b8156..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.cpp
+++ /dev/null
@@ -1,149 +0,0 @@
-//===- lib/ReaderWriter/ELF/MipsELFFlagsMerger.cpp ------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "MipsELFFlagsMerger.h"
-#include "lld/Core/Error.h"
-#include "llvm/ADT/Twine.h"
-#include "llvm/Support/ELF.h"
-#include "llvm/Support/raw_ostream.h"
-
-using namespace lld;
-using namespace lld::elf;
-using namespace llvm::ELF;
-
-struct MipsISATreeEdge {
- unsigned child;
- unsigned parent;
-};
-
-static MipsISATreeEdge isaTree[] = {
- // MIPS32R6 and MIPS64R6 are not compatible with other extensions
-
- // MIPS64 extensions.
- {EF_MIPS_ARCH_64R2, EF_MIPS_ARCH_64},
- // MIPS V extensions.
- {EF_MIPS_ARCH_64, EF_MIPS_ARCH_5},
- // MIPS IV extensions.
- {EF_MIPS_ARCH_5, EF_MIPS_ARCH_4},
- // MIPS III extensions.
- {EF_MIPS_ARCH_4, EF_MIPS_ARCH_3},
- // MIPS32 extensions.
- {EF_MIPS_ARCH_32R2, EF_MIPS_ARCH_32},
- // MIPS II extensions.
- {EF_MIPS_ARCH_3, EF_MIPS_ARCH_2},
- {EF_MIPS_ARCH_32, EF_MIPS_ARCH_2},
- // MIPS I extensions.
- {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1},
-};
-
-static bool matchMipsISA(unsigned base, unsigned ext) {
- if (base == ext)
- return true;
- if (base == EF_MIPS_ARCH_32 && matchMipsISA(EF_MIPS_ARCH_64, ext))
- return true;
- if (base == EF_MIPS_ARCH_32R2 && matchMipsISA(EF_MIPS_ARCH_64R2, ext))
- return true;
- for (const auto &edge : isaTree) {
- if (ext == edge.child) {
- ext = edge.parent;
- if (ext == base)
- return true;
- }
- }
- return false;
-}
-
-MipsELFFlagsMerger::MipsELFFlagsMerger(bool is64Bits)
- : _is64Bit(is64Bits), _flags(0) {}
-
-uint32_t MipsELFFlagsMerger::getMergedELFFlags() const { return _flags; }
-
-std::error_code MipsELFFlagsMerger::merge(uint8_t newClass, uint32_t newFlags) {
- // Check bitness.
- if (_is64Bit != (newClass == ELFCLASS64))
- return make_dynamic_error_code(
- Twine("Bitness is incompatible with that of the selected target"));
-
- // We support two ABI: O32 and N64. The last one does not have
- // the corresponding ELF flag.
- uint32_t inAbi = newFlags & EF_MIPS_ABI;
- uint32_t supportedAbi = _is64Bit ? 0 : uint32_t(EF_MIPS_ABI_O32);
- if (inAbi != supportedAbi)
- return make_dynamic_error_code(Twine("Unsupported ABI"));
-
- // ... and reduced set of architectures ...
- uint32_t newArch = newFlags & EF_MIPS_ARCH;
- switch (newArch) {
- case EF_MIPS_ARCH_1:
- case EF_MIPS_ARCH_2:
- case EF_MIPS_ARCH_3:
- case EF_MIPS_ARCH_4:
- case EF_MIPS_ARCH_5:
- case EF_MIPS_ARCH_32:
- case EF_MIPS_ARCH_64:
- case EF_MIPS_ARCH_32R2:
- case EF_MIPS_ARCH_64R2:
- case EF_MIPS_ARCH_32R6:
- case EF_MIPS_ARCH_64R6:
- break;
- default:
- return make_dynamic_error_code(Twine("Unsupported instruction set"));
- }
-
- // ... and still do not support MIPS-16 extension.
- if (newFlags & EF_MIPS_ARCH_ASE_M16)
- return make_dynamic_error_code(Twine("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 (newFlags & EF_MIPS_PIC)
- newFlags |= EF_MIPS_CPIC;
-
- std::lock_guard<std::mutex> lock(_mutex);
-
- // If the old set of flags is empty, use the new one as a result.
- if (!_flags) {
- _flags = newFlags;
- return std::error_code();
- }
-
- // Check PIC / CPIC flags compatibility.
- uint32_t newPic = newFlags & (EF_MIPS_PIC | EF_MIPS_CPIC);
- uint32_t oldPic = _flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
-
- if ((newPic != 0) != (oldPic != 0))
- llvm::errs() << "lld warning: linking abicalls and non-abicalls files\n";
-
- if (!(newPic & EF_MIPS_PIC))
- _flags &= ~EF_MIPS_PIC;
- if (newPic)
- _flags |= EF_MIPS_CPIC;
-
- // Check mixing -mnan=2008 / -mnan=legacy modules.
- if ((newFlags & EF_MIPS_NAN2008) != (_flags & EF_MIPS_NAN2008))
- return make_dynamic_error_code(
- Twine("Linking -mnan=2008 and -mnan=legacy modules"));
-
- // Check ISA compatibility and update the extension flag.
- uint32_t oldArch = _flags & EF_MIPS_ARCH;
- if (!matchMipsISA(newArch, oldArch)) {
- if (!matchMipsISA(oldArch, newArch))
- return make_dynamic_error_code(
- Twine("Linking modules with incompatible ISA"));
- _flags &= ~EF_MIPS_ARCH;
- _flags |= newArch;
- }
-
- _flags |= newFlags & EF_MIPS_NOREORDER;
- _flags |= newFlags & EF_MIPS_MICROMIPS;
- _flags |= newFlags & EF_MIPS_NAN2008;
- _flags |= newFlags & EF_MIPS_32BITMODE;
-
- return std::error_code();
-}
diff --git a/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.h b/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.h
deleted file mode 100644
index 6ade86f0163c..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsELFFlagsMerger.h
+++ /dev/null
@@ -1,36 +0,0 @@
-//===- lib/ReaderWriter/ELF/MipsELFFlagsMerger.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_FLAGS_MERGER_H
-#define LLD_READER_WRITER_ELF_MIPS_MIPS_ELF_FLAGS_MERGER_H
-
-#include <mutex>
-#include <system_error>
-
-namespace lld {
-namespace elf {
-
-class MipsELFFlagsMerger {
-public:
- MipsELFFlagsMerger(bool is64Bits);
-
- uint32_t getMergedELFFlags() const;
-
- /// \brief Merge saved ELF header flags and the new set of flags.
- std::error_code merge(uint8_t newClass, uint32_t newFlags);
-
-private:
- const bool _is64Bit;
- std::mutex _mutex;
- uint32_t _flags;
-};
-
-} // namespace elf
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Mips/MipsELFReader.h b/lib/ReaderWriter/ELF/Mips/MipsELFReader.h
deleted file mode 100644
index 8b325b38bb52..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsELFReader.h
+++ /dev/null
@@ -1,93 +0,0 @@
-//===- lib/ReaderWriter/ELF/MipsELFReader.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_READER_H
-#define LLD_READER_WRITER_ELF_MIPS_MIPS_ELF_READER_H
-
-#include "ELFReader.h"
-#include "MipsELFFile.h"
-#include "MipsELFFlagsMerger.h"
-#include "MipsLinkingContext.h"
-
-namespace lld {
-namespace elf {
-
-struct MipsELFFileCreateTraits {
- typedef llvm::ErrorOr<std::unique_ptr<lld::File>> result_type;
-
- template <class ELFT>
- static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb,
- MipsLinkingContext &ctx) {
- return lld::elf::MipsELFFile<ELFT>::create(std::move(mb), ctx);
- }
-};
-
-struct MipsDynamicFileCreateELFTraits {
- typedef llvm::ErrorOr<std::unique_ptr<lld::SharedLibraryFile>> result_type;
-
- template <class ELFT>
- static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb,
- MipsLinkingContext &ctx) {
- return lld::elf::MipsDynamicFile<ELFT>::create(std::move(mb), ctx);
- }
-};
-
-template <class ELFT>
-class MipsELFObjectReader
- : public ELFObjectReader<ELFT, MipsELFFileCreateTraits,
- MipsLinkingContext> {
- typedef ELFObjectReader<ELFT, MipsELFFileCreateTraits, MipsLinkingContext>
- BaseReaderType;
-
-public:
- MipsELFObjectReader(MipsLinkingContext &ctx)
- : BaseReaderType(ctx, llvm::ELF::EM_MIPS),
- _flagMerger(ctx.getELFFlagsMerger()) {}
-
- std::error_code
- loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry &registry,
- std::vector<std::unique_ptr<File>> &result) const override {
- auto &hdr = *this->elfHeader(*mb);
- if (std::error_code ec = _flagMerger.merge(hdr.getFileClass(), hdr.e_flags))
- return ec;
- return BaseReaderType::loadFile(std::move(mb), registry, result);
- }
-
-private:
- MipsELFFlagsMerger &_flagMerger;
-};
-
-template <class ELFT>
-class MipsELFDSOReader
- : public ELFDSOReader<ELFT, MipsDynamicFileCreateELFTraits,
- MipsLinkingContext> {
- typedef ELFDSOReader<ELFT, MipsDynamicFileCreateELFTraits, MipsLinkingContext>
- BaseReaderType;
-
-public:
- MipsELFDSOReader(MipsLinkingContext &ctx)
- : BaseReaderType(ctx, llvm::ELF::EM_MIPS),
- _flagMerger(ctx.getELFFlagsMerger()) {}
-
- std::error_code
- loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry &registry,
- std::vector<std::unique_ptr<File>> &result) const override {
- auto &hdr = *this->elfHeader(*mb);
- if (std::error_code ec = _flagMerger.merge(hdr.getFileClass(), hdr.e_flags))
- return ec;
- return BaseReaderType::loadFile(std::move(mb), registry, result);
- }
-
-private:
- MipsELFFlagsMerger &_flagMerger;
-};
-
-} // namespace elf
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp b/lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp
new file mode 100644
index 000000000000..b97a4f5a9070
--- /dev/null
+++ b/lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp
@@ -0,0 +1,292 @@
+//===- 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
index d94dd757a0f3..31b84f947c95 100644
--- a/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h
+++ b/lib/ReaderWriter/ELF/Mips/MipsELFWriters.h
@@ -9,71 +9,91 @@
#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"
-#include "OutputELFWriter.h"
namespace lld {
namespace elf {
-template <class ELFT> class MipsRuntimeFile;
-
template <class ELFT> class MipsTargetLayout;
template <typename ELFT> class MipsELFWriter {
public:
- MipsELFWriter(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &targetLayout)
- : _ctx(ctx), _targetLayout(targetLayout) {}
-
- void 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);
- if (_targetLayout.findOutputSection(".got.plt"))
- elfHeader.e_ident(llvm::ELF::EI_ABIVERSION, 1);
- else
- elfHeader.e_ident(llvm::ELF::EI_ABIVERSION, 0);
-
- elfHeader.e_flags(_ctx.getMergedELFFlags());
- }
-
- void finalizeMipsRuntimeAtomValues() {
- if (!_ctx.isDynamic())
- return;
-
- auto gotSection = _targetLayout.findOutputSection(".got");
- auto got = gotSection ? gotSection->virtualAddr() : 0;
- auto gp = gotSection ? got + _targetLayout.getGPOffset() : 0;
-
- setAtomValue("_GLOBAL_OFFSET_TABLE_", got);
- setAtomValue("_gp", gp);
- setAtomValue("_gp_disp", gp);
- setAtomValue("__gnu_local_gp", gp);
- }
-
- bool hasGlobalGOTEntry(const Atom *a) const {
- return _targetLayout.getGOTSection().hasGlobalGOTEntry(a);
- }
-
- std::unique_ptr<MipsRuntimeFile<ELFT>> createRuntimeFile() {
- auto file = llvm::make_unique<MipsRuntimeFile<ELFT>>(_ctx);
- if (_ctx.isDynamic()) {
- file->addAbsoluteAtom("_GLOBAL_OFFSET_TABLE_");
- file->addAbsoluteAtom("_gp");
- file->addAbsoluteAtom("_gp_disp");
- file->addAbsoluteAtom("__gnu_local_gp");
- }
- return file;
- }
+ 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);
- void setAtomValue(StringRef name, uint64_t value) {
- auto atom = _targetLayout.findAbsoluteAtom(name);
- assert(atom != _targetLayout.absoluteAtoms().end());
- (*atom)->_virtualAddr = value;
- }
+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
diff --git a/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h b/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h
deleted file mode 100644
index 1a85bba3bd0f..000000000000
--- a/lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.h
+++ /dev/null
@@ -1,154 +0,0 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsExecutableWriter.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_EXECUTABLE_WRITER_H
-#define LLD_READER_WRITER_ELF_MIPS_MIPS_EXECUTABLE_WRITER_H
-
-#include "ExecutableWriter.h"
-#include "MipsDynamicTable.h"
-#include "MipsELFWriters.h"
-#include "MipsLinkingContext.h"
-
-namespace lld {
-namespace elf {
-
-template <typename ELFT> class MipsTargetLayout;
-
-template <class ELFT>
-class MipsExecutableWriter : public ExecutableWriter<ELFT> {
-public:
- MipsExecutableWriter(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout);
-
-protected:
- void buildDynamicSymbolTable(const File &file) override;
-
- // Add any runtime files and their atoms to the output
- bool createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
-
- void finalizeDefaultAtomValues() 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> &_mipsTargetLayout;
-};
-
-template <class ELFT>
-MipsExecutableWriter<ELFT>::MipsExecutableWriter(MipsLinkingContext &ctx,
- MipsTargetLayout<ELFT> &layout)
- : ExecutableWriter<ELFT>(ctx, layout), _writeHelper(ctx, layout),
- _mipsTargetLayout(layout) {}
-
-template <class ELFT>
-std::error_code MipsExecutableWriter<ELFT>::setELFHeader() {
- std::error_code ec = ExecutableWriter<ELFT>::setELFHeader();
- if (ec)
- return ec;
-
- StringRef entryName = this->_context.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 (_writeHelper.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->_context.isDynamicallyExportedSymbol(da->name()) &&
- !(this->_context.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 (_writeHelper.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>
-bool MipsExecutableWriter<ELFT>::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &result) {
- ExecutableWriter<ELFT>::createImplicitFiles(result);
- result.push_back(std::move(_writeHelper.createRuntimeFile()));
- return true;
-}
-
-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>
-unique_bump_ptr<SymbolTable<ELFT>>
- MipsExecutableWriter<ELFT>::createSymbolTable() {
- return unique_bump_ptr<SymbolTable<ELFT>>(new (
- this->_alloc) MipsSymbolTable<ELFT>(this->_context));
-}
-
-/// \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->_context, _mipsTargetLayout));
-}
-
-/// \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->_context, _mipsTargetLayout));
-}
-
-} // namespace elf
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp b/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
index 7bffcbeb5c08..b6cdd5c1487c 100644
--- a/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
+++ b/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp
@@ -17,43 +17,46 @@ using namespace lld;
using namespace lld::elf;
std::unique_ptr<ELFLinkingContext>
-MipsLinkingContext::create(llvm::Triple triple) {
- if (triple.getArch() == llvm::Triple::mipsel ||
+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 std::unique_ptr<ELFLinkingContext>(new MipsLinkingContext(triple));
+ return llvm::make_unique<MipsLinkingContext>(triple);
return nullptr;
}
-typedef std::unique_ptr<TargetHandlerBase> TargetHandlerBasePtr;
-
-static TargetHandlerBasePtr createTarget(llvm::Triple triple,
- MipsLinkingContext &ctx) {
+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 TargetHandlerBasePtr(new MipsTargetHandler<Mips32ELType>(ctx));
+ return llvm::make_unique<MipsTargetHandler<ELF32LE>>(ctx);
+ case llvm::Triple::mips64:
+ return llvm::make_unique<MipsTargetHandler<ELF64BE>>(ctx);
case llvm::Triple::mips64el:
- return TargetHandlerBasePtr(new MipsTargetHandler<Mips64ELType>(ctx));
+ return llvm::make_unique<MipsTargetHandler<ELF64LE>>(ctx);
default:
llvm_unreachable("Unhandled arch");
}
}
MipsLinkingContext::MipsLinkingContext(llvm::Triple triple)
- : ELFLinkingContext(triple, createTarget(triple, *this)),
- _flagsMerger(triple.isArch64Bit()) {}
-
-uint32_t MipsLinkingContext::getMergedELFFlags() const {
- return _flagsMerger.getMergedELFFlags();
-}
-
-MipsELFFlagsMerger &MipsLinkingContext::getELFFlagsMerger() {
- return _flagsMerger;
-}
+ : ELFLinkingContext(triple, createTarget(triple, *this)) {}
uint64_t MipsLinkingContext::getBaseAddress() const {
- if (_baseAddress == 0 && getOutputELFType() == llvm::ELF::ET_EXEC)
- return getTriple().isArch64Bit() ? 0x120000000 : 0x400000;
- return _baseAddress;
+ 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 {
@@ -63,7 +66,15 @@ StringRef MipsLinkingContext::entrySymbolName() const {
}
StringRef MipsLinkingContext::getDefaultInterpreter() const {
- return getTriple().isArch64Bit() ? "/lib64/ld.so.1" : "/lib/ld.so.1";
+ 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) {
@@ -81,13 +92,14 @@ bool MipsLinkingContext::isDynamicRelocation(const Reference &r) const {
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 true;
+ return isDynamic();
default:
return false;
}
@@ -113,3 +125,40 @@ bool MipsLinkingContext::isPLTRelocation(const Reference &r) const {
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
index 824605f5fa7f..414d2c785e17 100644
--- a/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
+++ b/lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h
@@ -9,7 +9,7 @@
#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_LINKING_CONTEXT_H
#define LLD_READER_WRITER_ELF_MIPS_MIPS_LINKING_CONTEXT_H
-#include "MipsELFFlagsMerger.h"
+#include "MipsAbiInfoHandler.h"
#include "lld/ReaderWriter/ELFLinkingContext.h"
namespace lld {
@@ -23,10 +23,6 @@ enum {
LLD_R_MIPS_32_HI16 = 1025,
/// \brief The same as R_MIPS_26 but for global symbols.
LLD_R_MIPS_GLOBAL_26 = 1026,
- /// \brief Setup hi 16 bits using the symbol this reference refers to.
- LLD_R_MIPS_HI16 = 1027,
- /// \brief Setup low 16 bits using the symbol this reference refers to.
- LLD_R_MIPS_LO16 = 1028,
/// \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.
@@ -35,20 +31,12 @@ enum {
LLD_R_MIPS_64_HI16 = 1031,
};
-typedef llvm::object::ELFType<llvm::support::little, 2, false> Mips32ELType;
-typedef llvm::object::ELFType<llvm::support::little, 2, true> Mips64ELType;
-typedef llvm::object::ELFType<llvm::support::big, 2, false> Mips32BEType;
-typedef llvm::object::ELFType<llvm::support::big, 2, true> Mips64BEType;
-
class MipsLinkingContext final : public ELFLinkingContext {
public:
- static std::unique_ptr<ELFLinkingContext> create(llvm::Triple);
MipsLinkingContext(llvm::Triple triple);
- uint32_t getMergedELFFlags() const;
- MipsELFFlagsMerger &getELFFlagsMerger();
-
- // ELFLinkingContext
+ 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;
@@ -57,9 +45,9 @@ public:
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;
-private:
- MipsELFFlagsMerger _flagsMerger;
+ MipsAbi getAbi() const;
};
} // elf
diff --git a/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp b/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
index 173ce0e6b1a8..c55a7a4116e6 100644
--- a/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
+++ b/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp
@@ -7,9 +7,10 @@
//
//===----------------------------------------------------------------------===//
-#include "MipsTargetHandler.h"
#include "MipsLinkingContext.h"
#include "MipsRelocationHandler.h"
+#include "MipsTargetLayout.h"
+#include "llvm/Support/Format.h"
using namespace lld;
using namespace elf;
@@ -20,306 +21,265 @@ 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
+ 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 MipsRelocationHandler {
+template <class ELFT> class RelocationHandler : public TargetRelocationHandler {
public:
- RelocationHandler(MipsLinkingContext &ctx) : _ctx(ctx) {}
+ RelocationHandler(MipsLinkingContext &ctx, MipsTargetLayout<ELFT> &layout)
+ : _ctx(ctx), _targetLayout(layout) {}
std::error_code applyRelocation(ELFWriter &writer,
llvm::FileOutputBuffer &buf,
- const lld::AtomLayout &atom,
+ const AtomLayout &atom,
const Reference &ref) const override;
- Reference::Addend readAddend(Reference::KindValue kind,
- const uint8_t *content) 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};
+ return {4, 0x0, 0, false, dummyCheck};
case R_MIPS_64:
case R_MIPS_SUB:
- return {8, 0xffffffffffffffffull, 0, false};
+ 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:
- return {4, 0xffffffff, 0, false};
+ case R_MIPS_EH:
+ return {4, 0xffffffff, 0, false, dummyCheck};
case LLD_R_MIPS_32_HI16:
- return {4, 0xffff0000, 0, false};
+ return {4, 0xffff0000, 0, false, dummyCheck};
case LLD_R_MIPS_64_HI16:
- return {8, 0xffffffffffff0000ull, 0, false};
+ return {8, 0xffffffffffff0000ull, 0, false, dummyCheck};
case R_MIPS_26:
case LLD_R_MIPS_GLOBAL_26:
- return {4, 0x3ffffff, 2, false};
+ 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};
+ return {4, 0x3ffff, 3, false, signedCheck<21>};
case R_MIPS_PC19_S2:
- return {4, 0x7ffff, 2, false};
+ return {4, 0x7ffff, 2, false, signedCheck<21>};
case R_MIPS_PC21_S2:
- return {4, 0x1fffff, 2, false};
+ return {4, 0x1fffff, 2, false, signedCheck<23>};
case R_MIPS_PC26_S2:
- return {4, 0x3ffffff, 2, false};
+ 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_GPREL16:
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:
- case LLD_R_MIPS_HI16:
- case LLD_R_MIPS_LO16:
- return {4, 0xffff, 0, false};
+ 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};
+ return {4, 0xffff, 0, true, dummyCheck};
case R_MICROMIPS_26_S1:
case LLD_R_MICROMIPS_GLOBAL_26_S1:
- return {4, 0x3ffffff, 1, true};
+ return {4, 0x3ffffff, 1, true, dummyCheck};
case R_MICROMIPS_HI16:
+ return {4, 0xffff, 0, true, gpDispCheck<16>};
case R_MICROMIPS_LO16:
- case R_MICROMIPS_GOT16:
- return {4, 0xffff, 0, true};
+ 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};
+ return {4, 0xffff, 1, true, signedCheck<17>};
case R_MICROMIPS_PC7_S1:
- return {4, 0x7f, 1, false};
+ return {4, 0x7f, 1, false, signedCheck<8>};
case R_MICROMIPS_PC10_S1:
- return {4, 0x3ff, 1, false};
+ return {4, 0x3ff, 1, false, signedCheck<11>};
case R_MICROMIPS_PC23_S2:
- return {4, 0x7fffff, 2, true};
- case R_MIPS_CALL16:
- case R_MIPS_TLS_GD:
- case R_MIPS_TLS_LDM:
- case R_MIPS_TLS_GOTTPREL:
- return {4, 0xffff, 0, false};
+ 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:
- return {4, 0xffff, 0, true};
+ 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, 0x0, 0, false};
+ return {4, 0xffffffff, 0, false, dummyCheck};
case R_MICROMIPS_JALR:
- return {4, 0x0, 0, true};
- case R_MIPS_REL32:
+ 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:
- // Ignore runtime relocations.
- return {4, 0x0, 0, false};
+ return {4, 0xffffffff, 0, false, dummyCheck};
case R_MIPS_TLS_DTPMOD64:
case R_MIPS_TLS_DTPREL64:
case R_MIPS_TLS_TPREL64:
- return {8, 0x0, 0, false};
+ 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};
+ return {4, 0x0, 0, false, dummyCheck};
default:
llvm_unreachable("Unknown relocation");
}
}
-/// \brief R_MIPS_32
-/// local/external: word32 S + A (truncate)
-static uint32_t reloc32(uint64_t S, int64_t A) { return S + A; }
-
-/// \brief R_MIPS_64
-/// local/external: word64 S + A (truncate)
-static uint64_t reloc64(uint64_t S, int64_t A) { return S + A; }
-
-/// \brief R_MIPS_SUB
-/// local/external: word64 S - A (truncate)
-static uint64_t relocSub(uint64_t S, int64_t A) { return S - A; }
-
-/// \brief R_MIPS_PC32
-/// local/external: word32 S + A i- P (truncate)
-static uint32_t relocpc32(uint64_t P, uint64_t S, int64_t A) {
- return S + A - P;
-}
-
-/// \brief R_MIPS_26, R_MICROMIPS_26_S1
-/// local : ((A | ((P + 4) & 0x3F000000)) + S) >> 2
-static uint32_t reloc26loc(uint64_t P, uint64_t S, int32_t A, uint32_t shift) {
- uint32_t result = (A | ((P + 4) & (0xfc000000 << shift))) + S;
- return result >> shift;
-}
-
-/// \brief LLD_R_MIPS_GLOBAL_26, LLD_R_MICROMIPS_GLOBAL_26_S1
-/// external: (sign-extend(A) + S) >> 2
-static uint32_t reloc26ext(uint64_t S, int32_t A, uint32_t shift) {
- int32_t result =
- shift == 1 ? llvm::SignExtend32<27>(A) : llvm::SignExtend32<28>(A);
- return (result + S) >> shift;
-}
-
-/// \brief R_MIPS_HI16, R_MIPS_TLS_DTPREL_HI16, R_MIPS_TLS_TPREL_HI16,
-/// R_MICROMIPS_HI16, R_MICROMIPS_TLS_DTPREL_HI16, R_MICROMIPS_TLS_TPREL_HI16,
-/// LLD_R_MIPS_HI16
-/// local/external: hi16 (AHL + S) - (short)(AHL + S) (truncate)
-/// _gp_disp : hi16 (AHL + GP - P) - (short)(AHL + GP - P) (verify)
-static uint32_t relocHi16(uint64_t P, uint64_t S, int64_t AHL, bool isGPDisp) {
- int32_t result = isGPDisp ? AHL + S - P : AHL + S;
- return (result + 0x8000) >> 16;
-}
+template <class ELFT>
+static uint64_t relocRead(const MipsRelocationParams &params,
+ const uint8_t *loc);
-/// \brief R_MIPS_PCHI16
-/// local/external: hi16 (S + AHL - P)
-static uint32_t relocPcHi16(uint64_t P, uint64_t S, int64_t AHL) {
- int32_t result = S + AHL - P;
- return (result + 0x8000) >> 16;
+static int64_t getHi16(int64_t value) {
+ return ((value + 0x8000) >> 16) & 0xffff;
}
-/// \brief R_MIPS_LO16, R_MIPS_TLS_DTPREL_LO16, R_MIPS_TLS_TPREL_LO16,
-/// R_MICROMIPS_LO16, R_MICROMIPS_TLS_DTPREL_LO16, R_MICROMIPS_TLS_TPREL_LO16,
-/// LLD_R_MIPS_LO16
-/// local/external: lo16 AHL + S (truncate)
-/// _gp_disp : lo16 AHL + GP - P + 4 (verify)
-static uint32_t relocLo16(uint64_t P, uint64_t S, int64_t AHL, bool isGPDisp,
- bool micro) {
- int32_t result = isGPDisp ? AHL + S - P + (micro ? 3 : 4) : AHL + S;
- return result;
+static int64_t getHigher16(int64_t value) {
+ return ((value + 0x80008000ull) >> 32) & 0xffff;
}
-/// \brief R_MIPS_PCLO16
-/// local/external: lo16 (S + AHL - P)
-static uint32_t relocPcLo16(uint64_t P, uint64_t S, int64_t AHL) {
- AHL = llvm::SignExtend32<16>(AHL);
- int32_t result = S + AHL - P;
- return result;
+static int64_t getHighest16(int64_t value) {
+ return ((value + 0x800080008000ull) >> 48) & 0xffff;
}
-/// \brief R_MIPS_GOT16, R_MIPS_CALL16, R_MICROMIPS_GOT16, R_MICROMIPS_CALL16
-/// rel16 G (verify)
-static uint64_t relocGOT(uint64_t S, uint64_t GP) {
- int64_t G = (int64_t)(S - GP);
- return G;
+static int64_t maskLow16(int64_t value) {
+ return (value + 0x8000) & ~0xffff;
}
-/// R_MIPS_GOT_OFST
+/// R_MIPS_GOT_OFST, R_MICROMIPS_GOT_OFST
/// rel16 offset of (S+A) from the page pointer (verify)
-static uint32_t relocGOTOfst(uint64_t S, int64_t A) {
- uint64_t page = (S + A + 0x8000) & ~0xffff;
+static int32_t relocGOTOfst(uint64_t S, int64_t A) {
+ int64_t page = maskLow16(S + A);
return S + A - page;
}
-/// \brief R_MIPS_GPREL16
-/// local: sign-extend(A) + S + GP0 - GP
-/// external: sign-extend(A) + S - GP
-static uint64_t relocGPRel16(uint64_t S, int64_t A, uint64_t GP) {
- // We added GP0 to addendum for a local symbol during a Relocation pass.
- return llvm::SignExtend32<16>(A) + S - GP;
-}
-
-/// \brief R_MIPS_GPREL32
-/// local: rel32 A + S + GP0 - GP (truncate)
-static uint64_t relocGPRel32(uint64_t S, int64_t A, uint64_t GP) {
- // We added GP0 to addendum for a local symbol during a Relocation pass.
- return A + S - GP;
-}
-
-/// \brief R_MIPS_PC18_S3
-/// local/external: (S + A - P) >> 3 (P with cleared 3 less significant bits)
-static uint32_t relocPc18(uint64_t P, uint64_t S, int64_t A) {
- A = llvm::SignExtend32<21>(A);
- // FIXME (simon): Check that S + A has 8-byte alignment
- int32_t result = S + A - ((P | 7) ^ 7);
- return result >> 3;
-}
-
-/// \brief R_MIPS_PC19_S2
+/// \brief R_MIPS_PC16
/// local/external: (S + A - P) >> 2
-static uint32_t relocPc19(uint64_t P, uint64_t S, int64_t A) {
- A = llvm::SignExtend32<21>(A);
- // FIXME (simon): Check that S + A has 4-byte alignment
- int32_t result = S + A - P;
- return result >> 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_PC21_S2
-/// local/external: (S + A - P) >> 2
-static uint32_t relocPc21(uint64_t P, uint64_t S, int64_t A) {
- A = llvm::SignExtend32<23>(A);
- // FIXME (simon): Check that S + A has 4-byte alignment
- int32_t result = S + A - P;
- return result >> 2;
+/// \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_PC26_S2
+/// \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 uint32_t relocPc26(uint64_t P, uint64_t S, int64_t A) {
- A = llvm::SignExtend32<28>(A);
- // FIXME (simon): Check that S + A has 4-byte alignment
- int32_t result = S + A - P;
- return result >> 2;
-}
-
-/// \brief R_MICROMIPS_PC7_S1
-static uint32_t relocPc7(uint64_t P, uint64_t S, int64_t A) {
- A = llvm::SignExtend32<8>(A);
- int32_t result = S + A - P;
- return result >> 1;
-}
-
-/// \brief R_MICROMIPS_PC10_S1
-static uint32_t relocPc10(uint64_t P, uint64_t S, int64_t A) {
- A = llvm::SignExtend32<11>(A);
- int32_t result = S + A - P;
- return result >> 1;
-}
-
-/// \brief R_MICROMIPS_PC16_S1
-static uint32_t relocPc16(uint64_t P, uint64_t S, int64_t A) {
- A = llvm::SignExtend32<17>(A);
- int32_t result = S + A - P;
- return result >> 1;
-}
-
-/// \brief R_MICROMIPS_PC23_S2
-static uint32_t relocPc23(uint64_t P, uint64_t S, int64_t A) {
- A = llvm::SignExtend32<25>(A);
- int32_t result = S + A - P;
-
- // Check addiupc 16MB range.
- if (result + 0x1000000 >= 0x2000000)
- llvm::errs() << "The addiupc instruction immediate "
- << llvm::format_hex(result, 10) << " is out of range.\n";
-
- return result >> 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;
}
-/// \brief LLD_R_MIPS_32_HI16, LLD_R_MIPS_64_HI16
-static uint64_t relocMaskLow16(uint64_t S, int64_t A) {
- return S + A + 0x8000;
+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)
+ if (mode == CrossJumpMode::None || mode == CrossJumpMode::ToMicroJalr)
return std::error_code();
bool toMicro = mode == CrossJumpMode::ToMicro;
@@ -327,8 +287,7 @@ static std::error_code adjustJumpOpCode(uint64_t &ins, uint64_t tgt,
uint32_t opCross = toMicro ? 0x1d : 0x3c;
if ((tgt & 1) != toMicro)
- return make_dynamic_error_code(
- Twine("Incorrect bit 0 for the jalx target"));
+ 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") +
@@ -356,6 +315,8 @@ static CrossJumpMode getCrossJumpMode(const Reference &ref) {
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;
@@ -367,44 +328,64 @@ static CrossJumpMode getCrossJumpMode(const Reference &ref) {
}
}
-static uint32_t microShuffle(uint32_t ins) {
- return ((ins & 0xffff) << 16) | ((ins & 0xffff0000) >> 16);
-}
-
-static ErrorOr<uint64_t> calculateRelocation(Reference::KindValue kind,
- Reference::Addend addend,
- uint64_t tgtAddr, uint64_t relAddr,
- uint64_t gpAddr, bool isGP,
- CrossJumpMode jumpMode) {
- bool isCrossJump = jumpMode != 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:
- return reloc32(tgtAddr, addend);
case R_MIPS_64:
- return reloc64(tgtAddr, addend);
+ 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:
- return relocSub(tgtAddr, addend);
+ case R_MICROMIPS_SUB:
+ return tgtAddr - addend;
case R_MIPS_26:
- return reloc26loc(relAddr, tgtAddr, addend, 2);
+ return tgtAddr + (addend | (relAddr & 0xf0000000));
case R_MICROMIPS_26_S1:
- return reloc26loc(relAddr, tgtAddr, addend, isCrossJump ? 2 : 1);
+ return tgtAddr + (addend | (relAddr & 0xf8000000));
case R_MIPS_HI16:
case R_MICROMIPS_HI16:
- return relocHi16(relAddr, tgtAddr, addend, isGP);
+ return getHi16(tgtAddr + addend - (isGP ? relAddr : 0));
case R_MIPS_PCHI16:
- return relocPcHi16(relAddr, tgtAddr, addend);
+ return getHi16(tgtAddr + addend - relAddr);
case R_MIPS_LO16:
- return relocLo16(relAddr, tgtAddr, addend, isGP, false);
- case R_MIPS_PCLO16:
- return relocPcLo16(relAddr, tgtAddr, addend);
+ return tgtAddr + addend - (isGP ? relAddr - 4 : 0);
case R_MICROMIPS_LO16:
- return relocLo16(relAddr, tgtAddr, addend, isGP, true);
+ 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:
@@ -413,71 +394,66 @@ static ErrorOr<uint64_t> calculateRelocation(Reference::KindValue kind,
case R_MICROMIPS_TLS_GD:
case R_MICROMIPS_TLS_LDM:
case R_MICROMIPS_TLS_GOTTPREL:
- return relocGOT(tgtAddr, gpAddr);
+ 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:
- return relocPc19(relAddr, tgtAddr, addend);
+ case R_MICROMIPS_PC19_S2:
case R_MIPS_PC21_S2:
- return relocPc21(relAddr, tgtAddr, addend);
+ case R_MICROMIPS_PC21_S2:
case R_MIPS_PC26_S2:
- return relocPc26(relAddr, tgtAddr, addend);
+ case R_MICROMIPS_PC26_S2:
+ return relocPcS2(relAddr, tgtAddr, addend);
+ case R_MIPS_PC32:
+ case R_MIPS_PCLO16:
case R_MICROMIPS_PC7_S1:
- return relocPc7(relAddr, tgtAddr, addend);
case R_MICROMIPS_PC10_S1:
- return relocPc10(relAddr, tgtAddr, addend);
case R_MICROMIPS_PC16_S1:
- return relocPc16(relAddr, tgtAddr, addend);
case R_MICROMIPS_PC23_S2:
- return relocPc23(relAddr, tgtAddr, addend);
+ 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 relocHi16(0, tgtAddr, addend, false);
- case R_MIPS_TLS_DTPREL_LO16:
- case R_MIPS_TLS_TPREL_LO16:
- return relocLo16(0, tgtAddr, addend, false, false);
- case R_MICROMIPS_TLS_DTPREL_LO16:
- case R_MICROMIPS_TLS_TPREL_LO16:
- return relocLo16(0, tgtAddr, addend, false, true);
- case R_MIPS_GPREL16:
- return relocGPRel16(tgtAddr, addend, gpAddr);
- case R_MIPS_GPREL32:
- return relocGPRel32(tgtAddr, addend, gpAddr);
+ 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_DTPREL32:
- case R_MIPS_TLS_TPREL32:
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:
- // Ignore runtime relocations.
- return 0;
- case R_MIPS_PC32:
- return relocpc32(relAddr, tgtAddr, addend);
- case LLD_R_MIPS_GLOBAL_GOT:
- // Do nothing.
+ return isDynamic ? 0 : tgtAddr + addend - 0x7000;
case LLD_R_MIPS_32_HI16:
case LLD_R_MIPS_64_HI16:
- return relocMaskLow16(tgtAddr, addend);
- case LLD_R_MIPS_GLOBAL_26:
- return reloc26ext(tgtAddr, addend, 2);
- case LLD_R_MICROMIPS_GLOBAL_26_S1:
- return reloc26ext(tgtAddr, addend, isCrossJump ? 2 : 1);
- case LLD_R_MIPS_HI16:
- return relocHi16(0, tgtAddr, 0, false);
- case LLD_R_MIPS_LO16:
- return relocLo16(0, tgtAddr, 0, false, false);
+ return maskLow16(tgtAddr + addend);
case LLD_R_MIPS_STO_PLT:
+ case LLD_R_MIPS_GLOBAL_GOT:
// Do nothing.
return 0;
default:
@@ -488,27 +464,29 @@ static ErrorOr<uint64_t> calculateRelocation(Reference::KindValue kind,
template <class ELFT>
static uint64_t relocRead(const MipsRelocationParams &params,
const uint8_t *loc) {
- uint64_t data;
+ 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:
- data = endian::read<uint32_t, ELFT::TargetEndianness, unaligned>(loc);
- break;
+ return endian::read<uint32_t, ELFT::TargetEndianness, unaligned>(&data);
case 8:
- data = endian::read<uint64_t, ELFT::TargetEndianness, unaligned>(loc);
- break;
+ return endian::read<uint64_t, ELFT::TargetEndianness, unaligned>(&data);
default:
llvm_unreachable("Unexpected size");
}
- if (params._shuffle)
- data = microShuffle(data);
- return data;
}
template <class ELFT>
static void relocWrite(uint64_t data, const MipsRelocationParams &params,
uint8_t *loc) {
- if (params._shuffle)
- data = microShuffle(data);
switch (params._size) {
case 4:
endian::write<uint32_t, ELFT::TargetEndianness, unaligned>(loc, data);
@@ -519,24 +497,50 @@ static void relocWrite(uint64_t data, const MipsRelocationParams &params,
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 lld::AtomLayout &atom,
+ ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
const Reference &ref) const {
- if (ref.kindNamespace() != lld::Reference::KindNamespace::ELF)
+ if (ref.kindNamespace() != Reference::KindNamespace::ELF)
return std::error_code();
assert(ref.kindArch() == Reference::KindArch::Mips);
- auto &targetLayout = static_cast<MipsTargetLayout<ELFT> &>(
- _ctx.getTargetHandler<ELFT>().getTargetLayout());
-
- AtomLayout *gpAtom = targetLayout.getGP();
- uint64_t gpAddr = gpAtom ? gpAtom->_virtualAddr : 0;
-
- AtomLayout *gpDispAtom = targetLayout.getGPDisp();
- bool isGpDisp = gpDispAtom && ref.target() == gpDispAtom->_atom;
+ 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();
@@ -547,26 +551,37 @@ std::error_code RelocationHandler<ELFT>::applyRelocation(
tgtAddr |= 1;
CrossJumpMode jumpMode = getCrossJumpMode(ref);
-
- ErrorOr<uint64_t> res =
- calculateRelocation(ref.kindValue(), ref.addend(), tgtAddr, relAddr,
- gpAddr, isGpDisp, jumpMode);
- if (auto ec = res.getError())
- return ec;
-
- Reference::KindValue op = ref.kindValue();
-
- // FIXME (simon): Handle r_ssym value.
- for (auto tag = (ref.tag() & 0xffff); tag & 0xff; tag >>= 8) {
- op = tag & 0xff;
- res = calculateRelocation(op, *res, 0, relAddr, gpAddr, isGpDisp, jumpMode);
+ 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(op);
+ auto params = getRelocationParams(lastRel);
uint64_t ins = relocRead<ELFT>(params, location);
-
if (auto ec = adjustJumpOpCode(ins, tgtAddr, jumpMode))
return ec;
@@ -576,31 +591,97 @@ std::error_code RelocationHandler<ELFT>::applyRelocation(
return std::error_code();
}
-template <class ELFT>
-Reference::Addend
-RelocationHandler<ELFT>::readAddend(Reference::KindValue kind,
- const uint8_t *content) const {
- auto params = getRelocationParams(kind);
- uint64_t ins = relocRead<ELFT>(params, content);
- return (ins & params._mask) << params._shift;
-}
-
namespace lld {
namespace elf {
template <>
std::unique_ptr<TargetRelocationHandler>
-createMipsRelocationHandler<Mips32ELType>(MipsLinkingContext &ctx) {
- return std::unique_ptr<TargetRelocationHandler>(
- new RelocationHandler<Mips32ELType>(ctx));
+createMipsRelocationHandler<ELF32BE>(MipsLinkingContext &ctx,
+ MipsTargetLayout<ELF32BE> &layout) {
+ return llvm::make_unique<RelocationHandler<ELF32BE>>(ctx, layout);
}
template <>
std::unique_ptr<TargetRelocationHandler>
-createMipsRelocationHandler<Mips64ELType>(MipsLinkingContext &ctx) {
- return std::unique_ptr<TargetRelocationHandler>(
- new RelocationHandler<Mips64ELType>(ctx));
+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
index 87066b2b5c10..62a7aee34496 100644
--- a/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h
+++ b/lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h
@@ -9,22 +9,22 @@
#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_RELOCATION_HANDLER_H
#define LLD_READER_WRITER_ELF_MIPS_MIPS_RELOCATION_HANDLER_H
-#include "TargetHandler.h"
#include "lld/Core/Reference.h"
namespace lld {
namespace elf {
-class MipsRelocationHandler : public TargetRelocationHandler {
-public:
- virtual Reference::Addend readAddend(Reference::KindValue kind,
- const uint8_t *content) const = 0;
-};
+class MipsLinkingContext;
+template<typename ELFT> class MipsTargetLayout;
template <class ELFT>
std::unique_ptr<TargetRelocationHandler>
-createMipsRelocationHandler(MipsLinkingContext &ctx);
+createMipsRelocationHandler(MipsLinkingContext &ctx,
+ MipsTargetLayout<ELFT> &layout);
+template <class ELFT>
+Reference::Addend readMipsRelocAddend(Reference::KindValue kind,
+ const uint8_t *content);
} // elf
} // lld
diff --git a/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp b/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
index a1b3530dfcdf..b47c7d2210db 100644
--- a/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
+++ b/lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp
@@ -37,20 +37,69 @@ static const uint8_t mipsGotTlsGdAtomContent[] = {
0x00, 0x00, 0x00, 0x00
};
-// Regular PLT0 entry
-static const uint8_t mipsPlt0AtomContent[] = {
+// 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
- 0x21, 0x78, 0xe0, 0x03, // move $15, $31
+ 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 PLT0 entry
-static const uint8_t micromipsPlt0AtomContent[] = {
+// 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
@@ -62,40 +111,80 @@ static const uint8_t micromipsPlt0AtomContent[] = {
0x00, 0x0c // nop
};
-// Regular PLT entry
-static const uint8_t mipsPltAAtomContent[] = {
+// 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 PLT entry
-static const uint8_t micromipsPltAtomContent[] = {
+// 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 PLT entry
-static const uint8_t mipsR6PltAAtomContent[] = {
+// 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 stub entry
-static const uint8_t mipsLA25AtomContent[] = {
+// 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 stub entry
-static const uint8_t micromipsLA25AtomContent[] = {
+// 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)
@@ -109,7 +198,7 @@ class MipsGOTAtom : public GOTAtom {
public:
MipsGOTAtom(const File &f) : GOTAtom(f, ".got") {}
- Alignment alignment() const override { return Alignment(2); }
+ Alignment alignment() const override { return 4; }
};
/// \brief MIPS GOT entry initialized by zero.
@@ -120,10 +209,16 @@ public:
ArrayRef<uint8_t> rawContent() const override;
};
-template <> ArrayRef<uint8_t> GOT0Atom<Mips32ELType>::rawContent() const {
+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<Mips64ELType>::rawContent() const {
+template <> ArrayRef<uint8_t> GOT0Atom<ELF64BE>::rawContent() const {
+ return llvm::makeArrayRef(mipsGot0AtomContent);
+}
+template <> ArrayRef<uint8_t> GOT0Atom<ELF64LE>::rawContent() const {
return llvm::makeArrayRef(mipsGot0AtomContent);
}
@@ -136,11 +231,19 @@ public:
};
template <>
-ArrayRef<uint8_t> GOTModulePointerAtom<Mips32ELType>::rawContent() const {
+ArrayRef<uint8_t> GOTModulePointerAtom<ELF32BE>::rawContent() const {
return llvm::makeArrayRef(mipsGotModulePointerAtomContent).slice(4);
}
template <>
-ArrayRef<uint8_t> GOTModulePointerAtom<Mips64ELType>::rawContent() const {
+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);
}
@@ -152,12 +255,17 @@ public:
ArrayRef<uint8_t> rawContent() const override;
};
-template <> ArrayRef<uint8_t> GOTTLSGdAtom<Mips32ELType>::rawContent() const {
- return llvm::makeArrayRef(mipsGotTlsGdAtomContent).slice(8);
+template <> ArrayRef<uint8_t> GOTTLSGdAtom<ELF32BE>::rawContent() const {
+ return llvm::makeArrayRef(mipsGotTlsGdAtomContent).slice(8);
}
-
-template <> ArrayRef<uint8_t> GOTTLSGdAtom<Mips64ELType>::rawContent() const {
- return llvm::makeArrayRef(mipsGotTlsGdAtomContent);
+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 {
@@ -173,28 +281,56 @@ public:
addReferenceELF_Mips(R_MIPS_32, 0, plt0, 0);
}
- Alignment alignment() const override { return Alignment(2); }
+ Alignment alignment() const override { return 4; }
ArrayRef<uint8_t> rawContent() const override {
return llvm::makeArrayRef(mipsGot0AtomContent).slice(4);
}
};
-class PLT0Atom : public PLTAtom {
+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(LLD_R_MIPS_HI16, 0, got, 0);
- addReferenceELF_Mips(LLD_R_MIPS_LO16, 4, got, 0);
- addReferenceELF_Mips(LLD_R_MIPS_LO16, 8, got, 0);
+ 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 {
- return llvm::makeArrayRef(mipsPlt0AtomContent);
+ llvm_unreachable("PLT0 is not applicable for this target");
}
};
-class PLT0MicroAtom : public PLTAtom {
+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.
@@ -204,54 +340,87 @@ public:
CodeModel codeModel() const override { return codeMipsMicro; }
ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(micromipsPlt0AtomContent);
+ 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(LLD_R_MIPS_HI16, 0, got, 0);
- addReferenceELF_Mips(LLD_R_MIPS_LO16, 4, got, 0);
- addReferenceELF_Mips(LLD_R_MIPS_LO16, 12, got, 0);
+ 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 {
- return llvm::makeArrayRef(mipsPltAAtomContent);
+ llvm_unreachable("PLT is not applicable for this target");
}
};
-class PLTR6Atom : public PLTAAtom {
+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 {
- return llvm::makeArrayRef(mipsR6PltAAtomContent);
+ llvm_unreachable("PLT is not applicable for this target");
}
};
-class PLTMicroAtom : public PLTAtom {
+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 Alignment(1); }
+ Alignment alignment() const override { return 2; }
CodeModel codeModel() const override { return codeMipsMicro; }
ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(micromipsPltAtomContent);
+ 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") {}
};
-class LA25RegAtom : public LA25Atom {
+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.
@@ -261,11 +430,18 @@ public:
}
ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(mipsLA25AtomContent);
+ llvm_unreachable("LA25 stubs are not applicable for this target");
}
};
-class LA25MicroAtom : public LA25Atom {
+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.
@@ -277,7 +453,39 @@ public:
CodeModel codeModel() const override { return codeMipsMicro; }
ArrayRef<uint8_t> rawContent() const override {
- return llvm::makeArrayRef(micromipsLA25AtomContent);
+ 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);
}
};
@@ -295,7 +503,7 @@ template <typename ELFT> class RelocationPass : public Pass {
public:
RelocationPass(MipsLinkingContext &ctx);
- void perform(std::unique_ptr<MutableFile> &mf) override;
+ std::error_code perform(SimpleFile &mf) override;
private:
/// \brief Reference to the linking context.
@@ -319,7 +527,7 @@ private:
llvm::DenseMap<const Atom *, GOTAtom *> _gotTLSGdMap;
/// \brief GOT entry for the R_xxxMIPS_TLS_LDM relocations.
- GOTTLSGdAtom<ELFT> *_gotLDMEntry;
+ GOTTLSGdAtom<ELFT> *_gotLDMEntry = nullptr;
/// \brief the list of local GOT atoms.
std::vector<GOTAtom *> _localGotVector;
@@ -335,14 +543,14 @@ private:
/// \brief Map Atoms to their PLT entries.
llvm::DenseMap<const Atom *, PLTAAtom *> _pltRegMap;
- llvm::DenseMap<const Atom *, PLTMicroAtom *> _pltMicroMap;
+ 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 *, LA25RegAtom *> _la25RegMap;
- llvm::DenseMap<const Atom *, LA25MicroAtom *> _la25MicroMap;
+ llvm::DenseMap<const Atom *, LA25Atom *> _la25RegMap;
+ llvm::DenseMap<const Atom *, LA25Atom *> _la25MicroMap;
/// \brief Atoms referenced by static relocations.
llvm::DenseSet<const Atom *> _hasStaticRelocations;
@@ -372,24 +580,27 @@ private:
/// \brief Collect information about the reference to use it
/// later in the handleReference() routine.
- void collectReferenceInfo(const MipsELFDefinedAtom<ELFT> &atom,
- Reference &ref);
+ 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 handle26(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);
- const GOTAtom *getTLSGdGOTEntry(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 *getLA25Entry(const Atom *target, bool isMicroMips);
const LA25Atom *getLA25RegEntry(const Atom *a);
const LA25Atom *getLA25MicroEntry(const Atom *a);
const ObjectAtom *getObjectEntry(const SharedLibraryAtom *a);
@@ -399,40 +610,47 @@ private:
bool isLocal(const Atom *a) const;
bool isLocalCall(const Atom *a) const;
bool isDynamic(const Atom *atom) const;
- bool requireLA25Stub(const Atom *a) 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;
- bool isR6Target() 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), _gotLDMEntry(nullptr) {
+ : _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>
-void RelocationPass<ELFT>::perform(std::unique_ptr<MutableFile> &mf) {
- for (const auto &atom : mf->defined())
- for (const auto &ref : *atom)
- collectReferenceInfo(*cast<MipsELFDefinedAtom<ELFT>>(atom),
- const_cast<Reference &>(*ref));
+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 &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) {
- if (!isDynamic(ref->target()) || hasPLTEntry(ref->target()))
+ 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)
@@ -443,19 +661,32 @@ void RelocationPass<ELFT>::perform(std::unique_ptr<MutableFile> &mf) {
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);
+ mf.addAtom(*got);
}
for (auto &got : _globalGotVector) {
got->setOrdinal(ordinal++);
- mf->addAtom(*got);
+ mf.addAtom(*got);
}
for (auto &got : _tlsGotVector) {
got->setOrdinal(ordinal++);
- mf->addAtom(*got);
+ mf.addAtom(*got);
}
// Create and emit PLT0 entry.
@@ -467,19 +698,19 @@ void RelocationPass<ELFT>::perform(std::unique_ptr<MutableFile> &mf) {
if (plt0Atom) {
plt0Atom->setOrdinal(ordinal++);
- mf->addAtom(*plt0Atom);
+ mf.addAtom(*plt0Atom);
}
// Emit regular PLT entries firts.
for (auto &plt : _pltRegVector) {
plt->setOrdinal(ordinal++);
- mf->addAtom(*plt);
+ mf.addAtom(*plt);
}
// microMIPS PLT entries come after regular ones.
for (auto &plt : _pltMicroVector) {
plt->setOrdinal(ordinal++);
- mf->addAtom(*plt);
+ mf.addAtom(*plt);
}
// Assign PLT0 to GOTPLT entries.
@@ -489,18 +720,96 @@ void RelocationPass<ELFT>::perform(std::unique_ptr<MutableFile> &mf) {
for (auto &gotplt : _gotpltVector) {
gotplt->setOrdinal(ordinal++);
- mf->addAtom(*gotplt);
+ mf.addAtom(*gotplt);
}
for (auto obj : _objectVector) {
obj->setOrdinal(ordinal++);
- mf->addAtom(*obj);
+ mf.addAtom(*obj);
}
for (auto la25 : _la25Vector) {
la25->setOrdinal(ordinal++);
- mf->addAtom(*la25);
+ 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>
@@ -508,67 +817,33 @@ void RelocationPass<ELFT>::handleReference(const MipsELFDefinedAtom<ELFT> &atom,
Reference &ref) {
if (!ref.target())
return;
- if (ref.kindNamespace() != lld::Reference::KindNamespace::ELF)
+ if (ref.kindNamespace() != Reference::KindNamespace::ELF)
return;
+
assert(ref.kindArch() == Reference::KindArch::Mips);
- switch (ref.kindValue()) {
- case R_MIPS_32:
- case R_MIPS_PC32:
- case R_MIPS_HI16:
- case R_MIPS_LO16:
- case R_MIPS_PCHI16:
- case R_MIPS_PCLO16:
- case R_MICROMIPS_HI16:
- case R_MICROMIPS_LO16:
- // FIXME (simon): Handle dynamic/static linking differently.
+ Reference::KindValue kind = ref.kindValue();
+ if (isHiLo16Reloc(kind) || kind == R_MIPS_32 || kind == R_MIPS_PC32)
handlePlain(atom, ref);
- break;
- case R_MIPS_26:
- case R_MICROMIPS_26_S1:
- handle26(atom, ref);
- break;
- case R_MIPS_GOT16:
- case R_MIPS_CALL16:
- case R_MICROMIPS_GOT16:
- case R_MICROMIPS_CALL16:
- case R_MIPS_GOT_DISP:
- case R_MIPS_GOT_PAGE:
+ else if (isBranchReloc(kind))
+ handleBranch(atom, ref);
+ else if (isAllGotReloc(kind) || isAllCallReloc(kind) ||
+ isGotDispReloc(kind) || isGotPageReloc(kind) || kind == R_MIPS_EH)
handleGOT(ref);
- break;
- case R_MIPS_GOT_OFST:
- // Nothing to do. We create GOT page entry in the R_MIPS_GOT_PAGE handler.
- break;
- case R_MIPS_GPREL16:
- if (isLocal(ref.target()))
- ref.setAddend(ref.addend() + atom.file().getGP0());
- break;
- case R_MIPS_GPREL32:
- ref.setAddend(ref.addend() + atom.file().getGP0());
- break;
- case R_MIPS_TLS_DTPREL_HI16:
- case R_MIPS_TLS_DTPREL_LO16:
- case R_MICROMIPS_TLS_DTPREL_HI16:
- case R_MICROMIPS_TLS_DTPREL_LO16:
+ else if (isTlsDtpReloc(kind))
ref.setAddend(ref.addend() - atom.file().getDTPOffset());
- break;
- case R_MIPS_TLS_TPREL_HI16:
- case R_MIPS_TLS_TPREL_LO16:
- case R_MICROMIPS_TLS_TPREL_HI16:
- case R_MICROMIPS_TLS_TPREL_LO16:
+ else if (isTlsTpReloc(kind))
ref.setAddend(ref.addend() - atom.file().getTPOffset());
- break;
- case R_MIPS_TLS_GD:
- case R_MICROMIPS_TLS_GD:
- ref.setTarget(getTLSGdGOTEntry(ref.target()));
- break;
- case R_MIPS_TLS_LDM:
- case R_MICROMIPS_TLS_LDM:
+ else if (isTlsGdReloc(kind))
+ ref.setTarget(getTLSGdGOTEntry(ref.target(), ref.addend()));
+ else if (isTlsLdmReloc(kind))
ref.setTarget(getTLSLdmGOTEntry(ref.target()));
- break;
- case R_MIPS_TLS_GOTTPREL:
- case R_MICROMIPS_TLS_GOTTPREL:
- ref.setTarget(getTLSGOTEntry(ref.target()));
- break;
+ 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);
}
}
@@ -583,6 +858,10 @@ static bool isConstrainSym(const MipsELFDefinedAtom<ELFT> &atom,
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;
@@ -590,25 +869,96 @@ static bool isConstrainSym(const MipsELFDefinedAtom<ELFT> &atom,
}
template <typename ELFT>
-void RelocationPass<ELFT>::collectReferenceInfo(
- const MipsELFDefinedAtom<ELFT> &atom, Reference &ref) {
+std::error_code
+RelocationPass<ELFT>::collectReferenceInfo(const MipsELFDefinedAtom<ELFT> &atom,
+ Reference &ref) {
if (!ref.target())
- return;
- if (ref.kindNamespace() != lld::Reference::KindNamespace::ELF)
- return;
+ 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;
+ return std::error_code();
- if (mightBeDynamic(atom, refKind))
- _rel32Candidates.push_back(&ref);
- else
+ if (!mightBeDynamic(atom, refKind))
_hasStaticRelocations.insert(ref.target());
+ else if (refKind == R_MIPS_32 || refKind == R_MIPS_64)
+ _rel32Candidates.push_back(&ref);
- if (refKind != R_MIPS_CALL16 && refKind != R_MICROMIPS_CALL16 &&
- refKind != R_MIPS_26 && refKind != R_MICROMIPS_26_S1)
+ 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>
@@ -635,8 +985,7 @@ static bool isMipsReadonly(const MipsELFDefinedAtom<ELFT> &atom) {
template <typename ELFT>
bool RelocationPass<ELFT>::mightBeDynamic(const MipsELFDefinedAtom<ELFT> &atom,
Reference::KindValue refKind) const {
- if (refKind == R_MIPS_CALL16 || refKind == R_MIPS_GOT16 ||
- refKind == R_MICROMIPS_CALL16 || refKind == R_MICROMIPS_GOT16)
+ if (isAllGotReloc(refKind) || isAllCallReloc(refKind))
return true;
if (refKind != R_MIPS_32 && refKind != R_MIPS_64)
@@ -648,7 +997,7 @@ bool RelocationPass<ELFT>::mightBeDynamic(const MipsELFDefinedAtom<ELFT> &atom,
return true;
if (!isMipsReadonly(atom))
return true;
- if (atom.file().isPIC())
+ if (atom.isPIC())
return true;
return false;
@@ -659,14 +1008,18 @@ bool RelocationPass<ELFT>::hasPLTEntry(const Atom *atom) const {
return _pltRegMap.count(atom) || _pltMicroMap.count(atom);
}
-template <typename ELFT> bool RelocationPass<ELFT>::isR6Target() const {
- switch (_ctx.getMergedELFFlags() & EF_MIPS_ARCH) {
- case EF_MIPS_ARCH_32R6:
- case EF_MIPS_ARCH_64R6:
- return true;
- default:
- return false;
- }
+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>
@@ -697,21 +1050,13 @@ bool RelocationPass<ELFT>::isDynamic(const Atom *atom) const {
const auto *da = dyn_cast<const DefinedAtom>(atom);
if (da && da->dynamicExport() == DefinedAtom::dynamicExportAlways)
return true;
-
- const auto *sa = dyn_cast<SharedLibraryAtom>(atom);
- if (sa)
+ if (isa<SharedLibraryAtom>(atom))
return true;
-
- if (_ctx.getOutputELFType() == ET_DYN) {
- if (da && da->scope() != DefinedAtom::scopeTranslationUnit)
- return true;
-
- const auto *ua = dyn_cast<UndefinedAtom>(atom);
- if (ua)
- return true;
- }
-
- return false;
+ if (_ctx.getOutputELFType() != ET_DYN)
+ return false;
+ if (da && da->scope() != DefinedAtom::scopeTranslationUnit)
+ return true;
+ return isa<UndefinedAtom>(atom);
}
template <typename ELFT>
@@ -721,17 +1066,9 @@ static bool isMicroMips(const MipsELFDefinedAtom<ELFT> &atom) {
}
template <typename ELFT>
-const LA25Atom *RelocationPass<ELFT>::getLA25Entry(const Atom *target,
- bool isMicroMips) {
- return isMicroMips ? getLA25MicroEntry(target) : getLA25RegEntry(target);
-}
-
-template <typename ELFT>
const PLTAtom *RelocationPass<ELFT>::getPLTEntry(const Atom *a) {
- bool hasMicroCode = _ctx.getMergedELFFlags() & EF_MIPS_MICROMIPS;
-
// If file contains microMIPS code try to reuse compressed PLT entry...
- if (hasMicroCode) {
+ if (isMicroMips()) {
auto microPLT = _pltMicroMap.find(a);
if (microPLT != _pltMicroMap.end())
return microPLT->second;
@@ -743,7 +1080,7 @@ const PLTAtom *RelocationPass<ELFT>::getPLTEntry(const Atom *a) {
return regPLT->second;
// ... and finally prefer to create new compressed PLT entry.
- return hasMicroCode ? getPLTMicroEntry(a) : getPLTRegEntry(a);
+ return isMicroMips() ? getPLTMicroEntry(a) : getPLTRegEntry(a);
}
template <typename ELFT>
@@ -759,37 +1096,34 @@ void RelocationPass<ELFT>::handlePlain(const MipsELFDefinedAtom<ELFT> &atom,
}
template <typename ELFT>
-void RelocationPass<ELFT>::handle26(const MipsELFDefinedAtom<ELFT> &atom,
- Reference &ref) {
- bool isMicro = ref.kindValue() == R_MICROMIPS_26_S1;
- assert((isMicro || ref.kindValue() == R_MIPS_26) && "Unexpected relocation");
-
- const auto *sla = dyn_cast<SharedLibraryAtom>(ref.target());
- if (sla && sla->type() == SharedLibraryAtom::Type::Code)
- ref.setTarget(isMicro ? getPLTMicroEntry(sla) : getPLTRegEntry(sla));
-
- if (requireLA25Stub(ref.target()))
- ref.setTarget(getLA25Entry(ref.target(), isMicro));
+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 (isMicro)
+ if (ref.kindValue() == R_MICROMIPS_26_S1)
ref.setKindValue(LLD_R_MICROMIPS_GLOBAL_26_S1);
- else
+ 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())) {
+ if (!isLocalCall(ref.target()))
ref.setTarget(getGlobalGOTEntry(ref.target()));
- return;
- }
-
- if (ref.kindValue() == R_MIPS_GOT_PAGE)
+ else if (isGotPageReloc(ref.kindValue()))
ref.setTarget(getLocalGOTPageEntry(ref));
- else if (ref.kindValue() == R_MIPS_GOT_DISP)
- ref.setTarget(getLocalGOTEntry(ref));
- else if (isLocal(ref.target()))
+ else if (isLocal(ref.target()) &&
+ (isCallReloc(ref.kindValue()) || isGotReloc(ref.kindValue())))
ref.setTarget(getLocalGOTPageEntry(ref));
else
ref.setTarget(getLocalGOTEntry(ref));
@@ -817,11 +1151,12 @@ bool RelocationPass<ELFT>::isLocalCall(const Atom *a) const {
}
template <typename ELFT>
-bool RelocationPass<ELFT>::requireLA25Stub(const Atom *a) const {
- if (isLocal(a))
+bool RelocationPass<ELFT>::requireLA25Stub(const MipsELFDefinedAtom<ELFT> &atom,
+ const Reference &ref) const {
+ if (atom.file().isPIC())
return false;
- if (auto *da = dyn_cast<DefinedAtom>(a))
- return static_cast<const MipsELFDefinedAtom<ELFT> *>(da)->file().isPIC();
+ if (auto *da = dyn_cast<DefinedAtom>(ref.target()))
+ return static_cast<const MipsELFDefinedAtom<ELFT> *>(da)->isPIC();
return false;
}
@@ -886,7 +1221,8 @@ const GOTAtom *RelocationPass<ELFT>::getGlobalGOTEntry(const Atom *a) {
}
template <typename ELFT>
-const GOTAtom *RelocationPass<ELFT>::getTLSGOTEntry(const Atom *a) {
+const GOTAtom *RelocationPass<ELFT>::getTLSGOTEntry(const Atom *a,
+ Reference::Addend addend) {
auto got = _gotTLSMap.find(a);
if (got != _gotTLSMap.end())
return got->second;
@@ -897,13 +1233,15 @@ const GOTAtom *RelocationPass<ELFT>::getTLSGOTEntry(const Atom *a) {
_tlsGotVector.push_back(ga);
Reference::KindValue relKind =
ELFT::Is64Bits ? R_MIPS_TLS_TPREL64 : R_MIPS_TLS_TPREL32;
- ga->addReferenceELF_Mips(relKind, 0, a, 0);
+ ga->addReferenceELF_Mips(relKind, 0, a, addend);
return ga;
}
template <typename ELFT>
-const GOTAtom *RelocationPass<ELFT>::getTLSGdGOTEntry(const Atom *a) {
+const GOTAtom *
+RelocationPass<ELFT>::getTLSGdGOTEntry(const Atom *a,
+ Reference::Addend addend) {
auto got = _gotTLSGdMap.find(a);
if (got != _gotTLSGdMap.end())
return got->second;
@@ -913,11 +1251,11 @@ const GOTAtom *RelocationPass<ELFT>::getTLSGdGOTEntry(const Atom *a) {
_tlsGotVector.push_back(ga);
if (ELFT::Is64Bits) {
- ga->addReferenceELF_Mips(R_MIPS_TLS_DTPMOD64, 0, a, 0);
- ga->addReferenceELF_Mips(R_MIPS_TLS_DTPREL64, 8, a, 0);
+ 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, 0);
- ga->addReferenceELF_Mips(R_MIPS_TLS_DTPREL32, 4, a, 0);
+ ga->addReferenceELF_Mips(R_MIPS_TLS_DTPMOD32, 0, a, addend);
+ ga->addReferenceELF_Mips(R_MIPS_TLS_DTPREL32, 4, a, addend);
}
return ga;
@@ -946,9 +1284,10 @@ PLTAtom *RelocationPass<ELFT>::createPLTHeader(bool isMicroMips) {
_gotpltVector.insert(_gotpltVector.begin(), ga0);
if (isMicroMips)
- return new (_file._alloc) PLT0MicroAtom(ga0, _file);
- else
- return new (_file._alloc) PLT0Atom(ga0, _file);
+ 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>
@@ -969,9 +1308,11 @@ const PLTAtom *RelocationPass<ELFT>::getPLTRegEntry(const Atom *a) {
if (plt != _pltRegMap.end())
return plt->second;
- PLTAAtom *pa = isR6Target()
- ? new (_file._alloc) PLTR6Atom(getGOTPLTEntry(a), _file)
- : new (_file._alloc) PLTAAtom(getGOTPLTEntry(a), _file);
+ 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);
@@ -988,7 +1329,7 @@ const PLTAtom *RelocationPass<ELFT>::getPLTMicroEntry(const Atom *a) {
if (plt != _pltMicroMap.end())
return plt->second;
- auto pa = new (_file._alloc) PLTMicroAtom(getGOTPLTEntry(a), _file);
+ auto pa = new (_file._alloc) PLTMicroAtom<ELFT>(getGOTPLTEntry(a), _file);
_pltMicroMap[a] = pa;
_pltMicroVector.push_back(pa);
@@ -1005,7 +1346,7 @@ const LA25Atom *RelocationPass<ELFT>::getLA25RegEntry(const Atom *a) {
if (la25 != _la25RegMap.end())
return la25->second;
- auto sa = new (_file._alloc) LA25RegAtom(a, _file);
+ auto sa = new (_file._alloc) LA25RegAtom<ELFT>(a, _file);
_la25RegMap[a] = sa;
_la25Vector.push_back(sa);
@@ -1018,7 +1359,7 @@ const LA25Atom *RelocationPass<ELFT>::getLA25MicroEntry(const Atom *a) {
if (la25 != _la25MicroMap.end())
return la25->second;
- auto sa = new (_file._alloc) LA25MicroAtom(a, _file);
+ auto sa = new (_file._alloc) LA25MicroAtom<ELFT>(a, _file);
_la25MicroMap[a] = sa;
_la25Vector.push_back(sa);
@@ -1047,10 +1388,14 @@ RelocationPass<ELFT>::getObjectEntry(const SharedLibraryAtom *a) {
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<Mips32ELType>>(ctx);
+ 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<Mips64ELType>>(ctx);
+ return llvm::make_unique<RelocationPass<ELF64LE>>(ctx);
default:
llvm_unreachable("Unhandled arch");
}
diff --git a/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp b/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp
new file mode 100644
index 000000000000..98cc059787ef
--- /dev/null
+++ b/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp
@@ -0,0 +1,264 @@
+//===- 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
index de9390f2b307..e545f65dc419 100644
--- a/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h
+++ b/lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h
@@ -9,23 +9,81 @@
#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 ELFType> class MipsGOTSection : public AtomSection<ELFType> {
+template <class ELFT> class MipsGOTSection : public AtomSection<ELFT> {
public:
- MipsGOTSection(const MipsLinkingContext &ctx)
- : AtomSection<ELFType>(ctx, ".got", DefinedAtom::typeGOT,
- DefinedAtom::permRW_,
- MipsTargetLayout<ELFType>::ORDER_GOT),
- _hasNonLocal(false), _localCount(0) {
- this->_flags |= SHF_MIPS_GPREL;
- this->_alignment = 4;
- }
+ MipsGOTSection(const MipsLinkingContext &ctx);
/// \brief Number of local GOT entries.
std::size_t getLocalCount() const { return _localCount; }
@@ -39,47 +97,9 @@ public:
}
/// \brief Compare two atoms accordingly theirs positions in the GOT.
- bool compare(const Atom *a, const Atom *b) const {
- auto ia = _posMap.find(a);
- auto ib = _posMap.find(b);
+ bool compare(const Atom *a, const Atom *b) const;
- if (ia != _posMap.end() && ib != _posMap.end())
- return ia->second < ib->second;
-
- return ia == _posMap.end() && ib != _posMap.end();
- }
-
- const lld::AtomLayout *appendAtom(const Atom *atom) override {
- const DefinedAtom *da = dyn_cast<DefinedAtom>(atom);
-
- for (const auto &r : *da) {
- if (r->kindNamespace() != lld::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<ELFType>::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<ELFType>::appendAtom(atom);
- case R_MIPS_TLS_DTPMOD32:
- case R_MIPS_TLS_DTPMOD64:
- _hasNonLocal = true;
- break;
- }
- }
-
- if (!_hasNonLocal)
- ++_localCount;
-
- return AtomSection<ELFType>::appendAtom(atom);
- }
+ const AtomLayout *appendAtom(const Atom *atom) override;
private:
/// \brief True if the GOT contains non-local entries.
@@ -96,35 +116,13 @@ private:
};
/// \brief Handle Mips PLT section
-template <class ELFType> class MipsPLTSection : public AtomSection<ELFType> {
+template <class ELFT> class MipsPLTSection : public AtomSection<ELFT> {
public:
- MipsPLTSection(const MipsLinkingContext &ctx)
- : AtomSection<ELFType>(ctx, ".plt", DefinedAtom::typeGOT,
- DefinedAtom::permR_X,
- MipsTargetLayout<ELFType>::ORDER_PLT) {}
-
- const AtomLayout *findPLTLayout(const Atom *plt) const {
- auto it = _pltLayoutMap.find(plt);
- return it != _pltLayoutMap.end() ? it->second : nullptr;
- }
-
- const lld::AtomLayout *appendAtom(const Atom *atom) override {
- const auto *layout = AtomSection<ELFType>::appendAtom(atom);
+ MipsPLTSection(const MipsLinkingContext &ctx);
- const DefinedAtom *da = cast<DefinedAtom>(atom);
+ const AtomLayout *findPLTLayout(const Atom *plt) const;
- for (const auto &r : *da) {
- if (r->kindNamespace() != lld::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;
- }
+ const AtomLayout *appendAtom(const Atom *atom) override;
private:
/// \brief Map PLT Atoms to their layouts.
@@ -135,33 +133,15 @@ 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;
- static const bool _isMips64EL =
- ELFT::Is64Bits && ELFT::TargetEndianness == llvm::support::little;
-
public:
- MipsRelocationTable(const ELFLinkingContext &context, StringRef str,
- int32_t order)
- : RelocationTable<ELFT>(context, str, order) {}
+ MipsRelocationTable(const ELFLinkingContext &ctx, StringRef str,
+ int32_t order);
protected:
void writeRela(ELFWriter *writer, Elf_Rela &r, const DefinedAtom &atom,
- const Reference &ref) override {
- uint32_t rType = ref.kindValue() | (ref.tag() << 8);
- r.setSymbolAndType(this->getSymbolIndex(ref.target()), rType, _isMips64EL);
- r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom();
- // The addend is used only by relative relocations
- if (this->_context.isRelativeReloc(ref))
- r.r_addend = writer->addressOfAtom(ref.target()) + ref.addend();
- else
- r.r_addend = 0;
- }
-
+ const Reference &ref) override;
void writeRel(ELFWriter *writer, Elf_Rel &r, const DefinedAtom &atom,
- const Reference &ref) override {
- uint32_t rType = ref.kindValue() | (ref.tag() << 8);
- r.setSymbolAndType(this->getSymbolIndex(ref.target()), rType, _isMips64EL);
- r.r_offset = writer->addressOfAtom(&atom) + ref.offsetInAtom();
- }
+ const Reference &ref) override;
};
} // elf
diff --git a/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp b/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
index f60ab63c6af7..817e29444666 100644
--- a/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
+++ b/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp
@@ -1,4 +1,4 @@
-//===- lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp --------------------===//
+//===- lib/ReaderWriter/ELF/Mips/MipsTargetHandler32EL.cpp ----------------===//
//
// The LLVM Linker
//
@@ -7,29 +7,160 @@
//
//===----------------------------------------------------------------------===//
+#include "ELFReader.h"
+#include "MipsELFFile.h"
+#include "MipsELFWriters.h"
#include "MipsTargetHandler.h"
-using namespace lld;
-using namespace elf;
+namespace lld {
+namespace elf {
-void MipsRelocationStringTable::registerTable(Registry &registry) {
- registry.addKindTable(Reference::KindNamespace::ELF,
- Reference::KindArch::Mips, kindStrings);
+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;
+ }
}
-#define ELF_RELOC(name, value) LLD_KIND_STRING_ENTRY(name),
+template <class ELFT> void MipsSymbolTable<ELFT>::finalize(bool sort) {
+ SymbolTable<ELFT>::finalize(sort);
-const Registry::KindStrings MipsRelocationStringTable::kindStrings[] = {
-#include "llvm/Support/ELFRelocs/Mips.def"
- 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_HI16),
- LLD_KIND_STRING_ENTRY(LLD_R_MIPS_LO16),
- LLD_KIND_STRING_ENTRY(LLD_R_MIPS_STO_PLT),
- LLD_KIND_STRING_ENTRY(LLD_R_MICROMIPS_GLOBAL_26_S1),
- LLD_KIND_STRING_END
-};
+ 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();
-#undef ELF_RELOC
+ 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
index 79509addf40b..e4a35bdd323d 100644
--- a/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
+++ b/lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h
@@ -9,146 +9,36 @@
#ifndef LLD_READER_WRITER_ELF_MIPS_MIPS_TARGET_HANDLER_H
#define LLD_READER_WRITER_ELF_MIPS_MIPS_TARGET_HANDLER_H
-#include "DefaultTargetHandler.h"
-#include "MipsDynamicLibraryWriter.h"
-#include "MipsELFReader.h"
-#include "MipsExecutableWriter.h"
+#include "MipsAbiInfoHandler.h"
#include "MipsLinkingContext.h"
-#include "MipsRelocationHandler.h"
-#include "MipsSectionChunks.h"
-#include "TargetLayout.h"
-#include "llvm/ADT/DenseSet.h"
+#include "MipsTargetLayout.h"
+#include "TargetHandler.h"
namespace lld {
namespace elf {
-/// \brief TargetLayout for Mips
-template <class ELFT> class MipsTargetLayout final : public TargetLayout<ELFT> {
+class MipsBaseTargetHandler : public TargetHandler {
public:
- MipsTargetLayout(MipsLinkingContext &ctx)
- : TargetLayout<ELFT>(ctx),
- _gotSection(new (this->_allocator) MipsGOTSection<ELFT>(ctx)),
- _pltSection(new (this->_allocator) MipsPLTSection<ELFT>(ctx)) {}
-
- 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,
- Layout::SectionOrder order) override {
- if (type == DefinedAtom::typeGOT && name == ".got")
- return _gotSection;
- if (type == DefinedAtom::typeStub && name == ".plt")
- return _pltSection;
- return DefaultLayout<ELFT>::createSection(name, type, permissions, order);
- }
-
- /// \brief GP offset relative to .got section.
- uint64_t getGPOffset() const { return 0x7FF0; }
-
- /// \brief Get '_gp' symbol atom layout.
- AtomLayout *getGP() {
- if (!_gpAtom.hasValue()) {
- auto atom = this->findAbsoluteAtom("_gp");
- _gpAtom = atom != this->absoluteAtoms().end() ? *atom : nullptr;
- }
- return *_gpAtom;
- }
-
- /// \brief Get '_gp_disp' symbol atom layout.
- AtomLayout *getGPDisp() {
- if (!_gpDispAtom.hasValue()) {
- auto atom = this->findAbsoluteAtom("_gp_disp");
- _gpDispAtom = atom != this->absoluteAtoms().end() ? *atom : nullptr;
- }
- return *_gpDispAtom;
- }
-
- /// \brief Return the section order for a input section
- Layout::SectionOrder getSectionOrder(StringRef name, int32_t contentType,
- int32_t contentPermissions) override {
- if ((contentType == DefinedAtom::typeStub) && (name.startswith(".text")))
- return DefaultLayout<ELFT>::ORDER_TEXT;
-
- return DefaultLayout<ELFT>::getSectionOrder(name, contentType,
- contentPermissions);
- }
-
-protected:
- unique_bump_ptr<RelocationTable<ELFT>>
- createRelocationTable(StringRef name, int32_t order) override {
- return unique_bump_ptr<RelocationTable<ELFT>>(
- new (this->_allocator)
- MipsRelocationTable<ELFT>(this->_context, name, order));
- }
-
-private:
- MipsGOTSection<ELFT> *_gotSection;
- MipsPLTSection<ELFT> *_pltSection;
- llvm::Optional<AtomLayout *> _gpAtom;
- llvm::Optional<AtomLayout *> _gpDispAtom;
-};
-
-/// \brief Mips Runtime file.
-template <class ELFT> class MipsRuntimeFile final : public RuntimeFile<ELFT> {
-public:
- MipsRuntimeFile(MipsLinkingContext &ctx)
- : RuntimeFile<ELFT>(ctx, "Mips runtime file") {}
-};
-
-/// \brief Auxiliary class holds relocation's names table.
-class MipsRelocationStringTable {
- static const Registry::KindStrings kindStrings[];
-
-public:
- static void registerTable(Registry &registry);
+ virtual MipsAbi getAbi() const = 0;
};
/// \brief TargetHandler for Mips
template <class ELFT>
-class MipsTargetHandler final : public DefaultTargetHandler<ELFT> {
+class MipsTargetHandler final : public MipsBaseTargetHandler {
public:
- MipsTargetHandler(MipsLinkingContext &ctx)
- : _ctx(ctx), _runtimeFile(new MipsRuntimeFile<ELFT>(ctx)),
- _targetLayout(new MipsTargetLayout<ELFT>(ctx)),
- _relocationHandler(createMipsRelocationHandler<ELFT>(ctx)) {}
-
- MipsTargetLayout<ELFT> &getTargetLayout() override { return *_targetLayout; }
-
- std::unique_ptr<Reader> getObjReader() override {
- return std::unique_ptr<Reader>(new MipsELFObjectReader<ELFT>(_ctx));
- }
+ MipsTargetHandler(MipsLinkingContext &ctx);
- std::unique_ptr<Reader> getDSOReader() override {
- return std::unique_ptr<Reader>(new MipsELFDSOReader<ELFT>(_ctx));
- }
+ MipsAbiInfoHandler<ELFT> &getAbiInfoHandler() { return _abiInfoHandler; }
- const TargetRelocationHandler &getRelocationHandler() const override {
- return *_relocationHandler;
- }
-
- std::unique_ptr<Writer> getWriter() override {
- switch (_ctx.getOutputELFType()) {
- case llvm::ELF::ET_EXEC:
- return std::unique_ptr<Writer>(
- new MipsExecutableWriter<ELFT>(_ctx, *_targetLayout));
- case llvm::ELF::ET_DYN:
- return std::unique_ptr<Writer>(
- new MipsDynamicLibraryWriter<ELFT>(_ctx, *_targetLayout));
- case llvm::ELF::ET_REL:
- llvm_unreachable("TODO: support -r mode");
- default:
- llvm_unreachable("unsupported output type");
- }
- }
-
- void registerRelocationNames(Registry &registry) override {
- MipsRelocationStringTable::registerTable(registry);
- }
+ 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;
- std::unique_ptr<MipsRuntimeFile<ELFT>> _runtimeFile;
+ MipsAbiInfoHandler<ELFT> _abiInfoHandler;
std::unique_ptr<MipsTargetLayout<ELFT>> _targetLayout;
std::unique_ptr<TargetRelocationHandler> _relocationHandler;
};
@@ -157,95 +47,21 @@ template <class ELFT> class MipsSymbolTable : public SymbolTable<ELFT> {
public:
typedef llvm::object::Elf_Sym_Impl<ELFT> Elf_Sym;
- MipsSymbolTable(const ELFLinkingContext &ctx)
- : SymbolTable<ELFT>(ctx, ".symtab",
- DefaultLayout<ELFT>::ORDER_SYMBOL_TABLE) {}
+ MipsSymbolTable(const ELFLinkingContext &ctx);
void addDefinedAtom(Elf_Sym &sym, const DefinedAtom *da,
- int64_t addr) override {
- 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;
- }
- }
-
- void finalize(bool sort) override {
- 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;
- }
- }
- }
- }
+ 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)
- : DynamicSymbolTable<ELFT>(ctx, layout, ".dynsym",
- DefaultLayout<ELFT>::ORDER_DYNAMIC_SYMBOLS),
- _targetLayout(layout) {}
-
- void sortSymbols() override {
- 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);
- });
- }
-
- void finalize() override {
- 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;
- }
+ MipsTargetLayout<ELFT> &layout);
- 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;
- }
- }
- }
- }
+ void sortSymbols() override;
+ void finalize() override;
private:
MipsTargetLayout<ELFT> &_targetLayout;
diff --git a/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp b/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp
new file mode 100644
index 000000000000..710f8320a8b9
--- /dev/null
+++ b/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp
@@ -0,0 +1,111 @@
+//===- 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
new file mode 100644
index 000000000000..08855438d20e
--- /dev/null
+++ b/lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h
@@ -0,0 +1,71 @@
+//===- 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
index d126b830db96..11f88056c8c4 100644
--- a/lib/ReaderWriter/ELF/OrderPass.h
+++ b/lib/ReaderWriter/ELF/OrderPass.h
@@ -19,9 +19,10 @@ namespace elf {
/// \brief This pass sorts atoms by file and atom ordinals.
class OrderPass : public Pass {
public:
- void perform(std::unique_ptr<MutableFile> &file) override {
- parallel_sort(file->definedAtoms().begin(), file->definedAtoms().end(),
+ std::error_code perform(SimpleFile &file) override {
+ parallel_sort(file.definedAtoms().begin(), file.definedAtoms().end(),
DefinedAtom::compareByPosition);
+ return std::error_code();
}
};
}
diff --git a/lib/ReaderWriter/ELF/OutputELFWriter.cpp b/lib/ReaderWriter/ELF/OutputELFWriter.cpp
new file mode 100644
index 000000000000..4f8b0eac655f
--- /dev/null
+++ b/lib/ReaderWriter/ELF/OutputELFWriter.cpp
@@ -0,0 +1,514 @@
+//===- 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
index c137905b936b..bb3901010634 100644
--- a/lib/ReaderWriter/ELF/OutputELFWriter.h
+++ b/lib/ReaderWriter/ELF/OutputELFWriter.h
@@ -6,88 +6,24 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
+
#ifndef LLD_READER_WRITER_ELF_OUTPUT_WRITER_H
#define LLD_READER_WRITER_ELF_OUTPUT_WRITER_H
-#include "DefaultLayout.h"
#include "ELFFile.h"
#include "TargetLayout.h"
-#include "lld/Core/Instrumentation.h"
-#include "lld/Core/Parallel.h"
-#include "lld/Core/SharedLibraryFile.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "lld/Core/Simple.h"
#include "lld/Core/Writer.h"
-#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringSet.h"
-#include "llvm/Support/Path.h"
namespace lld {
+class ELFLinkingContext;
+
namespace elf {
using namespace llvm;
using namespace llvm::object;
-template <class ELFT> class OutputELFWriter;
-template <class ELFT> class TargetLayout;
-
-namespace {
-
-template<class ELFT>
-class SymbolFile : public RuntimeFile<ELFT> {
-public:
- SymbolFile(ELFLinkingContext &context)
- : RuntimeFile<ELFT>(context, "Dynamic absolute symbols"),
- _atomsAdded(false) {}
-
- Atom *addAbsoluteAtom(StringRef symbolName) override {
- auto *a = RuntimeFile<ELFT>::addAbsoluteAtom(symbolName);
- if (a) _atomsAdded = true;
- return a;
- }
-
- Atom *addUndefinedAtom(StringRef) override {
- llvm_unreachable("Cannot add undefined atoms to resolve undefined symbols");
- }
-
- bool hasAtoms() const { return _atomsAdded; }
-
-private:
- bool _atomsAdded;
-};
-
-template<class ELFT>
-class DynamicSymbolFile : public SimpleArchiveLibraryFile {
- typedef std::function<void(StringRef, RuntimeFile<ELFT> &)> Resolver;
-public:
- DynamicSymbolFile(ELFLinkingContext &context, Resolver resolver)
- : SimpleArchiveLibraryFile("Dynamically added runtime symbols"),
- _context(context), _resolver(resolver) {}
-
- File *find(StringRef sym, bool dataSymbolOnly) override {
- if (!_file)
- _file.reset(new (_alloc) SymbolFile<ELFT>(_context));
-
- assert(!_file->hasAtoms() && "The file shouldn't have atoms yet");
- _resolver(sym, *_file);
- // If atoms were added - release the file to the caller.
- return _file->hasAtoms() ? _file.release() : nullptr;
- }
-
-private:
- ELFLinkingContext &_context;
- Resolver _resolver;
-
- // The allocator should go before bump pointers because of
- // reversed destruction order.
- llvm::BumpPtrAllocator _alloc;
- unique_bump_ptr<SymbolFile<ELFT>> _file;
-};
-
-} // end anon namespace
-
-//===----------------------------------------------------------------------===//
// 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
@@ -99,7 +35,7 @@ public:
typedef Elf_Sym_Impl<ELFT> Elf_Sym;
typedef Elf_Dyn_Impl<ELFT> Elf_Dyn;
- OutputELFWriter(ELFLinkingContext &context, TargetLayout<ELFT> &layout);
+ OutputELFWriter(ELFLinkingContext &ctx, TargetLayout<ELFT> &layout);
protected:
// build the sections that need to be created
@@ -140,11 +76,8 @@ protected:
// section header table, string table etc
virtual void assignSectionsWithNoSegments();
- // Add default atoms that need to be present in the output file
- virtual void addDefaultAtoms();
-
// Add any runtime files and their atoms to the output
- bool createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
+ void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
// Finalize the default atom values
virtual void finalizeDefaultAtomValues();
@@ -180,12 +113,15 @@ protected:
/// \brief Process undefined symbols that left after resolution step.
virtual void processUndefinedSymbol(StringRef symName,
- RuntimeFile<ELFT> &file) const {}
+ 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 &_context;
- TargetHandler<ELFT> &_targetHandler;
+ ELFLinkingContext &_ctx;
+ TargetHandler &_targetHandler;
typedef llvm::DenseMap<const Atom *, uint64_t> AtomToAddress;
AtomToAddress _atomToAddressMap;
@@ -205,410 +141,12 @@ protected:
unique_bump_ptr<HashSection<ELFT>> _hashTable;
llvm::StringSet<> _soNeeded;
/// @}
- std::unique_ptr<RuntimeFile<ELFT>> _scriptFile;
private:
static StringRef maybeGetSOName(Node *node);
+ void updateScopeAtomValues(StringRef start, StringRef end, StringRef sec);
};
-//===----------------------------------------------------------------------===//
-// OutputELFWriter
-//===----------------------------------------------------------------------===//
-template <class ELFT>
-OutputELFWriter<ELFT>::OutputELFWriter(ELFLinkingContext &context,
- TargetLayout<ELFT> &layout)
- : _context(context), _targetHandler(context.getTargetHandler<ELFT>()),
- _layout(layout),
- _scriptFile(new RuntimeFile<ELFT>(context, "Linker script runtime")) {}
-
-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 : _context.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(_context.getInterpreter()));
- for (const auto &loadName : _soNeeded) {
- Elf_Dyn dyn;
- dyn.d_tag = DT_NEEDED;
- dyn.d_un.d_val = _dynamicStringTable->addString(loadName.getKey());
- _dynamicTable->addEntry(dyn);
- }
- const auto &rpathList = _context.getRpathList();
- if (!rpathList.empty()) {
- auto rpath = new (_alloc) std::string(join(rpathList.begin(),
- rpathList.end(), ":"));
- Elf_Dyn dyn;
- dyn.d_tag = DT_RPATH;
- dyn.d_un.d_val = _dynamicStringTable->addString(*rpath);
- _dynamicTable->addEntry(dyn);
- }
- StringRef soname = _context.sharedObjectName();
- if (!soname.empty() && _context.getOutputELFType() == llvm::ELF::ET_DYN) {
- Elf_Dyn dyn;
- dyn.d_tag = DT_SONAME;
- dyn.d_un.d_val = _dynamicStringTable->addString(soname);
- _dynamicTable->addEntry(dyn);
- }
- // 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
- _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 (!DefaultLayout<ELFT>::hasOutputSegment(section))
- _shdrtab->updateSection(section);
-}
-
-template <class ELFT> void OutputELFWriter<ELFT>::addDefaultAtoms() {
- const llvm::StringSet<> &symbols =
- _context.linkerScriptSema().getScriptDefinedSymbols();
- for (auto &sym : symbols)
- _scriptFile->addAbsoluteAtom(sym.getKey());
-}
-
-template <class ELFT>
-bool 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);
- };
- auto &ctx = const_cast<ELFLinkingContext &>(_context);
- ctx.setUndefinesResolver(
- llvm::make_unique<DynamicSymbolFile<ELFT>>(ctx, std::move(callback)));
- // Add script defined symbols
- result.push_back(std::move(_scriptFile));
- return true;
-}
-
-template <class ELFT>
-void OutputELFWriter<ELFT>::finalizeDefaultAtomValues() {
- const llvm::StringSet<> &symbols =
- _context.linkerScriptSema().getScriptDefinedSymbols();
- for (auto &sym : symbols) {
- uint64_t res =
- _context.linkerScriptSema().getLinkerScriptExprValue(sym.getKey());
- auto a = _layout.findAbsoluteAtom(sym.getKey());
- (*a)->_virtualAddr = res;
- }
-}
-
-template <class ELFT> void OutputELFWriter<ELFT>::createDefaultSections() {
- _elfHeader.reset(new (_alloc) ELFHeader<ELFT>(_context));
- _programHeader.reset(new (_alloc) ProgramHeader<ELFT>(_context));
- _layout.setHeader(_elfHeader.get());
- _layout.setProgramHeader(_programHeader.get());
-
- _symtab = std::move(this->createSymbolTable());
- _strtab.reset(new (_alloc) StringTable<ELFT>(
- _context, ".strtab", DefaultLayout<ELFT>::ORDER_STRING_TABLE));
- _shstrtab.reset(new (_alloc) StringTable<ELFT>(
- _context, ".shstrtab", DefaultLayout<ELFT>::ORDER_SECTION_STRINGS));
- _shdrtab.reset(new (_alloc) SectionHeader<ELFT>(
- _context, DefaultLayout<ELFT>::ORDER_SECTION_HEADERS));
- _layout.addSection(_symtab.get());
- _layout.addSection(_strtab.get());
- _layout.addSection(_shstrtab.get());
- _shdrtab->setStringSection(_shstrtab.get());
- _symtab->setStringSection(_strtab.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>(
- _context, ".eh_frame_hdr", _layout,
- DefaultLayout<ELFT>::ORDER_EH_FRAMEHDR));
- _layout.addSection(_ehFrameHeader.get());
- break;
- }
-
- if (_context.isDynamic()) {
- _dynamicTable = std::move(createDynamicTable());
- _dynamicStringTable.reset(new (_alloc) StringTable<ELFT>(
- _context, ".dynstr", DefaultLayout<ELFT>::ORDER_DYNAMIC_STRINGS, true));
- _dynamicSymbolTable = std::move(createDynamicSymbolTable());
- _hashTable.reset(new (_alloc) HashSection<ELFT>(
- _context, ".hash", DefaultLayout<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->_context, ".symtab", DefaultLayout<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->_context, _layout, ".dynamic", DefaultLayout<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->_context, _layout, ".dynsym",
- DefaultLayout<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 (_context.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 (!_context.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 (_context.isDynamic())
- _dynamicTable->updateDynamicTable();
-
- return std::error_code();
-}
-
-template <class ELFT> std::error_code OutputELFWriter<ELFT>::setELFHeader() {
- _elfHeader->e_type(_context.getOutputELFType());
- _elfHeader->e_machine(_context.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(_context.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) {
- std::unique_ptr<FileOutputBuffer> buffer;
- ScopedTask createOutputTask(getDefaultDomain(), "ELF Writer Create Output");
- std::error_code ec = FileOutputBuffer::create(path, outputFileSize(), buffer,
- FileOutputBuffer::F_executable);
- createOutputTask.end();
-
- if (ec)
- return ec;
-
- 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) {
- std::error_code ec = buildOutput(file);
- if (ec)
- return ec;
-
- ec = setELFHeader();
- if (ec)
- return ec;
-
- return writeOutput(file, path);
-}
} // namespace elf
} // namespace lld
diff --git a/lib/ReaderWriter/ELF/Reader.cpp b/lib/ReaderWriter/ELF/Reader.cpp
index fc113d478913..801f1abaed7a 100644
--- a/lib/ReaderWriter/ELF/Reader.cpp
+++ b/lib/ReaderWriter/ELF/Reader.cpp
@@ -29,15 +29,15 @@ namespace lld {
void Registry::addSupportELFObjects(ELFLinkingContext &ctx) {
// Tell registry about the ELF object file parser.
- add(std::move(ctx.targetHandler()->getObjReader()));
+ add(ctx.getTargetHandler().getObjReader());
// Tell registry about the relocation name to number mapping for this arch.
- ctx.targetHandler()->registerRelocationNames(*this);
+ ctx.registerRelocationNames(*this);
}
void Registry::addSupportELFDynamicSharedObjects(ELFLinkingContext &ctx) {
// Tell registry about the ELF dynamic shared library file parser.
- add(ctx.targetHandler()->getDSOReader());
+ add(ctx.getTargetHandler().getDSOReader());
}
} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/SectionChunks.cpp b/lib/ReaderWriter/ELF/SectionChunks.cpp
new file mode 100644
index 000000000000..520fbe24af3b
--- /dev/null
+++ b/lib/ReaderWriter/ELF/SectionChunks.cpp
@@ -0,0 +1,996 @@
+//===- 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
index 03bdb59e6568..b10ba05237ff 100644
--- a/lib/ReaderWriter/ELF/SectionChunks.h
+++ b/lib/ReaderWriter/ELF/SectionChunks.h
@@ -11,19 +11,16 @@
#define LLD_READER_WRITER_ELF_SECTION_CHUNKS_H
#include "Chunk.h"
-#include "Layout.h"
#include "TargetHandler.h"
#include "Writer.h"
#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/Parallel.h"
#include "lld/Core/range.h"
-#include "llvm/ADT/ArrayRef.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/Debug.h"
-#include "llvm/Support/Dwarf.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/ErrorHandling.h"
#include "llvm/Support/FileOutputBuffer.h"
@@ -35,29 +32,22 @@ 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 &context, StringRef sectionName,
+ Section(const ELFLinkingContext &ctx, StringRef sectionName,
StringRef chunkName,
- typename Chunk<ELFT>::Kind k = Chunk<ELFT>::Kind::ELFSection)
- : Chunk<ELFT>(chunkName, k, context), _outputSection(nullptr), _flags(0),
- _entSize(0), _type(0), _link(0), _info(0),
- _isFirstSectionInOutputSection(false), _segmentType(SHT_NULL),
- _inputSectionName(sectionName), _outputSectionName(sectionName) {}
+ typename Chunk<ELFT>::Kind k = Chunk<ELFT>::Kind::ELFSection);
/// \brief Modify the section contents before assigning virtual addresses
// or assigning file offsets
- void doPreFlight() override {}
/// \brief Finalize the section contents before writing
- void finalize() override {}
/// \brief Does this section have an output segment.
- virtual bool hasOutputSegment() {
- return false;
- }
+ virtual bool hasOutputSegment() const { return false; }
/// Return if the section is a loadable section that occupies memory
virtual bool isLoadableSection() const { return false; }
@@ -73,26 +63,21 @@ public:
uint32_t getType() const { return _type; }
uint32_t getLink() const { return _link; }
uint32_t getInfo() const { return _info; }
- Layout::SegmentType getSegmentType() const { return _segmentType; }
- /// \brief Return the type of content that the section contains
- virtual int getContentType() const override {
- 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;
+ 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
- StringRef segmentKindToStr() const;
+ virtual StringRef segmentKindToStr() const;
/// \brief Records the segmentType, that this section belongs to
- void setSegmentType(const Layout::SegmentType segmentType) {
+ void
+ setSegmentType(const typename TargetLayout<ELFT>::SegmentType segmentType) {
this->_segmentType = segmentType;
}
@@ -100,6 +85,10 @@ public:
return nullptr;
}
+ const OutputSection<ELFT> *getOutputSection() const {
+ return _outputSection;
+ }
+
void setOutputSection(OutputSection<ELFT> *os, bool isFirst = false) {
_outputSection = os;
_isFirstSectionInOutputSection = isFirst;
@@ -133,21 +122,21 @@ public:
protected:
/// \brief OutputSection this Section is a member of, or nullptr.
- OutputSection<ELFT> *_outputSection;
+ OutputSection<ELFT> *_outputSection = nullptr;
/// \brief ELF SHF_* flags.
- uint64_t _flags;
+ uint64_t _flags = 0;
/// \brief The size of each entity.
- uint64_t _entSize;
+ uint64_t _entSize = 0;
/// \brief ELF SHT_* type.
- uint32_t _type;
+ uint32_t _type = 0;
/// \brief sh_link field.
- uint32_t _link;
+ uint32_t _link = 0;
/// \brief the sh_info field.
- uint32_t _info;
+ uint32_t _info = 0;
/// \brief Is this the first section in the output section.
- bool _isFirstSectionInOutputSection;
+ bool _isFirstSectionInOutputSection = false;
/// \brief the output ELF segment type of this section.
- Layout::SegmentType _segmentType;
+ typename TargetLayout<ELFT>::SegmentType _segmentType = SHT_NULL;
/// \brief Input section name.
StringRef _inputSectionName;
/// \brief Output section name.
@@ -159,65 +148,8 @@ protected:
/// \brief A section containing atoms.
template <class ELFT> class AtomSection : public Section<ELFT> {
public:
- AtomSection(const ELFLinkingContext &context, StringRef sectionName,
- int32_t contentType, int32_t permissions, int32_t order)
- : Section<ELFT>(context, sectionName, "AtomSection",
- Chunk<ELFT>::Kind::AtomSection),
- _contentType(contentType), _contentPermissions(permissions),
- _isLoadedInMemory(true) {
- 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;
- }
- }
+ 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);
@@ -228,40 +160,27 @@ public:
// \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 lld::AtomLayout *appendAtom(const Atom *atom);
+ 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
- virtual void assignVirtualAddress(uint64_t addr) override {
- parallel_for_each(_atoms.begin(), _atoms.end(), [&](AtomLayout *ai) {
- ai->_virtualAddr = addr + ai->_fileOffset;
- });
- }
+ 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 {
- parallel_for_each(_atoms.begin(), _atoms.end(), [&](AtomLayout *ai) {
- ai->_fileOffset = offset + ai->_fileOffset;
- });
- }
+ 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 {
- for (auto ai : _atoms)
- if (ai->_atom->name() == name)
- return ai;
- return nullptr;
- }
+ 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<lld::AtomLayout *>::iterator atom_iter;
+ typedef typename std::vector<AtomLayout *>::iterator atom_iter;
range<atom_iter> atoms() { return _atoms; }
@@ -276,185 +195,27 @@ protected:
llvm::BumpPtrAllocator _alloc;
int32_t _contentType;
int32_t _contentPermissions;
- bool _isLoadedInMemory;
- std::vector<lld::AtomLayout *> _atoms;
+ bool _isLoadedInMemory = true;
+ std::vector<AtomLayout *> _atoms;
mutable std::mutex _outputMutex;
- void printError(const std::string &errorStr, const AtomLayout &atom,
- const Reference &ref) const {
- StringRef kindValStr;
- if (!this->_context.registry().referenceKindToString(ref.kindNamespace(),
- ref.kindArch(),
- ref.kindValue(),
- kindValStr)) {
- kindValStr = "unknown";
- }
-
- std::string errStr = (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();
-
- // Take the lock to prevent output getting interleaved between threads
- std::lock_guard<std::mutex> lock(_outputMutex);
- llvm::errs() << errStr;
- }
+ std::string formatError(const std::string &errorStr, const AtomLayout &atom,
+ const Reference &ref) const;
};
-/// 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 = 1u << atomAlign.powerOf2;
- 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 lld::AtomLayout *AtomSection<ELFT>::appendAtom(const Atom *atom) {
- const DefinedAtom *definedAtom = cast<DefinedAtom>(atom);
-
- DefinedAtom::Alignment atomAlign = definedAtom->alignment();
- uint64_t alignment = 1u << atomAlign.powerOf2;
- // 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) lld::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) lld::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) lld::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(_atoms.begin(), _atoms.end(), [&](lld::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->_context.template getTargetHandler<ELFT>().getRelocationHandler();
- for (const auto ref : *definedAtom) {
- if (std::error_code ec = relHandler.applyRelocation(*writer, buffer,
- *ai, *ref)) {
- printError(ec.message(), *ai, *ref);
- success = false;
- }
- }
- });
- if (!success)
- llvm::report_fatal_error("relocating output");
-}
-
/// \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<Chunk<ELFT> *>::iterator ChunkIter;
+ typedef typename std::vector<Section<ELFT> *>::iterator SectionIter;
- OutputSection(StringRef name);
+ OutputSection(StringRef name) : _name(name) {}
// Appends a section into the list of sections that are part of this Output
// Section
- void appendSection(Chunk<ELFT> *c);
+ void appendSection(Section<ELFT> *c);
// Set the OutputSection is associated with a segment
void setHasSegment() { _hasSegment = true; }
@@ -484,90 +245,48 @@ public:
}
void setLink(uint64_t link) { _link = link; }
-
void setInfo(uint64_t info) { _shInfo = info; }
-
void setFlag(uint64_t flags) { _flags = flags; }
-
- void setType(int16_t type) { _type = type; }
-
- range<ChunkIter> sections() { return _sections; }
+ 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; }
-
- int64_t flags() const { return _flags; }
-
- uint64_t memSize() { return _memSize; }
+ uint64_t flags() const { return _flags; }
+ uint64_t memSize() const { return _memSize; }
private:
StringRef _name;
- bool _hasSegment;
- uint64_t _ordinal;
- uint64_t _flags;
- uint64_t _size;
- uint64_t _memSize;
- uint64_t _fileOffset;
- uint64_t _virtualAddr;
- int64_t _shInfo;
- int64_t _entSize;
- int64_t _link;
- uint64_t _alignment;
- int64_t _kind;
- int64_t _type;
- bool _isLoadableSection;
- std::vector<Chunk<ELFT> *> _sections;
+ 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;
};
-/// OutputSection
-template <class ELFT>
-OutputSection<ELFT>::OutputSection(StringRef name)
- : _name(name), _hasSegment(false), _ordinal(0), _flags(0), _size(0),
- _memSize(0), _fileOffset(0), _virtualAddr(0), _shInfo(0), _entSize(0),
- _link(0), _alignment(0), _kind(0), _type(0), _isLoadableSection(false) {}
-
-template <class ELFT> void OutputSection<ELFT>::appendSection(Chunk<ELFT> *c) {
- if (c->alignment() > _alignment)
- _alignment = c->alignment();
- if (const auto section = dyn_cast<Section<ELFT>>(c)) {
- 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 = c->kind();
- _sections.push_back(c);
-}
-
/// \brief The class represents the ELF String Table
-template<class ELFT>
-class StringTable : public Section<ELFT> {
+template <class ELFT> class StringTable : public Section<ELFT> {
public:
StringTable(const ELFLinkingContext &, const char *str, int32_t order,
bool dynamic = false);
@@ -592,68 +311,21 @@ private:
return lhs.equals(rhs);
}
};
- typedef typename llvm::DenseMap<StringRef, uint64_t,
- StringRefMappingInfo> StringMapT;
+ typedef typename llvm::DenseMap<StringRef, uint64_t, StringRefMappingInfo>
+ StringMapT;
typedef typename StringMapT::iterator StringMapTIter;
StringMapT _stringMap;
};
-template <class ELFT>
-StringTable<ELFT>::StringTable(const ELFLinkingContext &context,
- const char *str, int32_t order, bool dynamic)
- : Section<ELFT>(context, 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;
- }
-}
-
/// \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;
+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 &context, const char *str, int32_t order);
+ 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
@@ -666,7 +338,7 @@ public:
std::size_t size() const { return _symbolTable.size(); }
void addSymbol(const Atom *atom, int32_t sectionIndex, uint64_t addr = 0,
- const lld::AtomLayout *layout = nullptr);
+ const AtomLayout *layout = nullptr);
/// \brief Get the symbol table index for an Atom. If it's not in the symbol
/// table, return STN_UNDEF.
@@ -681,9 +353,9 @@ public:
virtual void sortSymbols() {
std::stable_sort(_symbolTable.begin(), _symbolTable.end(),
- [](const SymbolEntry & A, const SymbolEntry & B) {
- return A._symbol.getBinding() < B._symbol.getBinding();
- });
+ [](const SymbolEntry &A, const SymbolEntry &B) {
+ return A._symbol.getBinding() < B._symbol.getBinding();
+ });
}
virtual void addAbsoluteAtom(Elf_Sym &sym, const AbsoluteAtom *aa,
@@ -707,12 +379,11 @@ public:
protected:
struct SymbolEntry {
- SymbolEntry(const Atom *a, const Elf_Sym &sym,
- const lld::AtomLayout *layout)
+ SymbolEntry(const Atom *a, const Elf_Sym &sym, const AtomLayout *layout)
: _atom(a), _atomLayout(layout), _symbol(sym) {}
const Atom *_atom;
- const lld::AtomLayout *_atomLayout;
+ const AtomLayout *_atomLayout;
Elf_Sym _symbol;
};
@@ -721,233 +392,23 @@ protected:
std::vector<SymbolEntry> _symbolTable;
};
-/// ELF Symbol Table
-template <class ELFT>
-SymbolTable<ELFT>::SymbolTable(const ELFLinkingContext &context,
- const char *str, int32_t order)
- : Section<ELFT>(context, 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 lld::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));
-
- _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> class HashSection;
template <class ELFT> class DynamicSymbolTable : public SymbolTable<ELFT> {
public:
- DynamicSymbolTable(const ELFLinkingContext &context,
- TargetLayout<ELFT> &layout, const char *str, int32_t order)
- : SymbolTable<ELFT>(context, str, order), _hashTable(nullptr),
- _layout(layout) {
- this->_type = SHT_DYNSYM;
- this->_flags = SHF_ALLOC;
- this->_msize = this->_fsize;
- }
+ 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() {
- int index = 0;
- for (auto &ste : this->_symbolTable) {
- if (!ste._atom)
- _hashTable->addSymbol("", index);
- else
- _hashTable->addSymbol(ste._atom->name(), index);
- ++index;
- }
- }
+ void addSymbolsToHashTable();
- void finalize() override {
- // 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 lld::AtomLayout *atomLayout = ste._atomLayout;
- if (!atomLayout)
- continue;
- ste._symbol.st_value = atomLayout->_virtualAddr;
- }
-
- // Don't sort the symbols
- SymbolTable<ELFT>::finalize(false);
- }
+ void finalize() override;
protected:
- HashSection<ELFT> *_hashTable;
+ HashSection<ELFT> *_hashTable = nullptr;
TargetLayout<ELFT> &_layout;
};
@@ -956,118 +417,36 @@ public:
typedef llvm::object::Elf_Rel_Impl<ELFT, false> Elf_Rel;
typedef llvm::object::Elf_Rel_Impl<ELFT, true> Elf_Rela;
- RelocationTable(const ELFLinkingContext &context, StringRef str,
- int32_t order)
- : Section<ELFT>(context, str, "RelocationTable"), _symbolTable(nullptr) {
- this->setOrder(order);
- this->_flags = SHF_ALLOC;
- // Set the alignment properly depending on the target architecture
- this->_alignment = ELFT::Is64Bits ? 8 : 4;
- if (context.isRelaOutputFormat()) {
- this->_entSize = sizeof(Elf_Rela);
- this->_type = SHT_RELA;
- } else {
- this->_entSize = sizeof(Elf_Rel);
- this->_type = SHT_REL;
- }
- }
+ 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) {
- _relocs.emplace_back(&da, &r);
- this->_fsize = _relocs.size() * this->_entSize;
- this->_msize = this->_fsize;
- return _relocs.size() - 1;
- }
+ uint32_t addRelocation(const DefinedAtom &da, const Reference &r);
- bool 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;
- }
+ 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 {
- for (const auto &rel : _relocs) {
- const DefinedAtom *atom = rel.first;
- if ((atom->permissions() & DefinedAtom::permRW_) != DefinedAtom::permRW_)
- return true;
- }
- return false;
- }
+ bool canModifyReadonlySection() const;
- void finalize() override {
- this->_link = _symbolTable ? _symbolTable->ordinal() : 0;
- if (this->_outputSection)
- this->_outputSection->setLink(this->_link);
- }
+ void finalize() override;
void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override {
- uint8_t *chunkBuffer = buffer.getBufferStart();
- uint8_t *dest = chunkBuffer + this->fileOffset();
- for (const auto &rel : _relocs) {
- if (this->_context.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;
- }
- }
+ llvm::FileOutputBuffer &buffer) override;
protected:
- const DynamicSymbolTable<ELFT> *_symbolTable;
+ const DynamicSymbolTable<ELFT> *_symbolTable = nullptr;
virtual void 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->_context.isRelativeReloc(ref))
- r.r_addend = writer->addressOfAtom(ref.target()) + ref.addend();
- else
- r.r_addend = 0;
- }
-
+ const DefinedAtom &atom, const Reference &ref);
virtual void 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();
- }
-
- uint32_t getSymbolIndex(const Atom *a) {
- return _symbolTable ? _symbolTable->getSymbolTableIndex(a)
- : (uint32_t)STN_UNDEF;
- }
+ const Reference &ref);
+ uint32_t getSymbolIndex(const Atom *a);
private:
- std::vector<std::pair<const DefinedAtom *, const Reference *> > _relocs;
+ std::vector<std::pair<const DefinedAtom *, const Reference *>> _relocs;
};
template <class ELFT> class HashSection;
@@ -1077,125 +456,25 @@ public:
typedef llvm::object::Elf_Dyn_Impl<ELFT> Elf_Dyn;
typedef std::vector<Elf_Dyn> EntriesT;
- DynamicTable(const ELFLinkingContext &context, TargetLayout<ELFT> &layout,
- StringRef str, int32_t order)
- : Section<ELFT>(context, 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;
- }
+ 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(Elf_Dyn e) {
- _entries.push_back(e);
- this->_fsize = (_entries.size() * sizeof(Elf_Dyn)) + sizeof(Elf_Dyn);
- this->_msize = this->_fsize;
- return _entries.size() - 1;
- }
+ std::size_t addEntry(int64_t tag, uint64_t val);
void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override {
- 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);
- }
-
- virtual void createDefaultEntries() {
- bool isRela = this->_context.isRelaOutputFormat();
-
- Elf_Dyn dyn;
- dyn.d_un.d_val = 0;
-
- dyn.d_tag = DT_HASH;
- _dt_hash = addEntry(dyn);
- dyn.d_tag = DT_STRTAB;
- _dt_strtab = addEntry(dyn);
- dyn.d_tag = DT_SYMTAB;
- _dt_symtab = addEntry(dyn);
- dyn.d_tag = DT_STRSZ;
- _dt_strsz = addEntry(dyn);
- dyn.d_tag = DT_SYMENT;
- _dt_syment = addEntry(dyn);
- if (_layout.hasDynamicRelocationTable()) {
- dyn.d_tag = isRela ? DT_RELA : DT_REL;
- _dt_rela = addEntry(dyn);
- dyn.d_tag = isRela ? DT_RELASZ : DT_RELSZ;
- _dt_relasz = addEntry(dyn);
- dyn.d_tag = isRela ? DT_RELAENT : DT_RELENT;
- _dt_relaent = addEntry(dyn);
-
- if (_layout.getDynamicRelocationTable()->canModifyReadonlySection()) {
- dyn.d_tag = DT_TEXTREL;
- _dt_textrel = addEntry(dyn);
- }
- }
- if (_layout.hasPLTRelocationTable()) {
- dyn.d_tag = DT_PLTRELSZ;
- _dt_pltrelsz = addEntry(dyn);
- dyn.d_tag = getGotPltTag();
- _dt_pltgot = addEntry(dyn);
- dyn.d_tag = DT_PLTREL;
- dyn.d_un.d_val = isRela ? DT_RELA : DT_REL;
- _dt_pltrel = addEntry(dyn);
- dyn.d_un.d_val = 0;
- dyn.d_tag = DT_JMPREL;
- _dt_jmprel = addEntry(dyn);
- }
- }
+ llvm::FileOutputBuffer &buffer) override;
- void doPreFlight() override {
- Elf_Dyn dyn;
- dyn.d_un.d_val = 0;
- auto initArray = _layout.findOutputSection(".init_array");
- auto finiArray = _layout.findOutputSection(".fini_array");
- if (initArray) {
- dyn.d_tag = DT_INIT_ARRAY;
- _dt_init_array = addEntry(dyn);
- dyn.d_tag = DT_INIT_ARRAYSZ;
- _dt_init_arraysz = addEntry(dyn);
- }
- if (finiArray) {
- dyn.d_tag = DT_FINI_ARRAY;
- _dt_fini_array = addEntry(dyn);
- dyn.d_tag = DT_FINI_ARRAYSZ;
- _dt_fini_arraysz = addEntry(dyn);
- }
- if (getInitAtomLayout()) {
- dyn.d_tag = DT_INIT;
- _dt_init = addEntry(dyn);
- }
- if (getFiniAtomLayout()) {
- dyn.d_tag = DT_FINI;
- _dt_fini = addEntry(dyn);
- }
- }
+ 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 {
- 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);
- }
- }
+ void finalize() override;
void setSymbolTable(DynamicSymbolTable<ELFT> *dynsym) {
_dynamicSymbolTable = dynsym;
@@ -1207,42 +486,7 @@ public:
void setHashTable(HashSection<ELFT> *hsh) { _hashTable = hsh; }
- virtual void 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();
- }
- }
+ virtual void updateDynamicTable();
protected:
EntriesT _entries;
@@ -1279,41 +523,18 @@ private:
DynamicSymbolTable<ELFT> *_dynamicSymbolTable;
HashSection<ELFT> *_hashTable;
- const AtomLayout *getInitAtomLayout() {
- auto al = _layout.findAtomLayoutByName(this->_context.initFunction());
- if (al && isa<DefinedAtom>(al->_atom))
- return al;
- return nullptr;
- }
+ const AtomLayout *getInitAtomLayout();
- const AtomLayout *getFiniAtomLayout() {
- auto al = _layout.findAtomLayoutByName(this->_context.finiFunction());
- if (al && isa<DefinedAtom>(al->_atom))
- return al;
- return nullptr;
- }
+ const AtomLayout *getFiniAtomLayout();
};
template <class ELFT> class InterpSection : public Section<ELFT> {
public:
- InterpSection(const ELFLinkingContext &context, StringRef str, int32_t order,
- StringRef interp)
- : Section<ELFT>(context, 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;
- }
+ InterpSection(const ELFLinkingContext &ctx, StringRef str, int32_t order,
+ StringRef interp);
void 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());
- }
+ llvm::FileOutputBuffer &buffer) override;
private:
StringRef _interp;
@@ -1338,7 +559,6 @@ private:
/// * 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;
@@ -1346,153 +566,51 @@ template <class ELFT> class HashSection : public Section<ELFT> {
};
public:
- HashSection(const ELFLinkingContext &context, StringRef name, int32_t order)
- : Section<ELFT>(context, name, "Dynamic:Hash"), _symbolTable(nullptr) {
- 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;
- }
+ 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) {
- SymbolTableEntry ste;
- ste._name = name;
- ste._index = index;
- _entries.push_back(ste);
- }
+ void addSymbol(StringRef name, uint32_t index);
/// \brief Set the dynamic symbol table
- void setSymbolTable(const DynamicSymbolTable<ELFT> *symbolTable) {
- _symbolTable = symbolTable;
- }
+ 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 {
- // 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;
- }
+ void doPreFlight() override;
- this->_fsize = (2 + _chains.size() + _buckets.size()) * sizeof(uint32_t);
- this->_msize = this->_fsize;
- }
-
- void finalize() override {
- this->_link = _symbolTable ? _symbolTable->ordinal() : 0;
- if (this->_outputSection)
- this->_outputSection->setLink(this->_link);
- }
+ void finalize() override;
void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer) override {
- uint8_t *chunkBuffer = buffer.getBufferStart();
- uint8_t *dest = chunkBuffer + this->fileOffset();
- uint32_t bucketChainCounts[2];
- bucketChainCounts[0] = _buckets.size();
- bucketChainCounts[1] = _chains.size();
- std::memcpy(dest, (char *)bucketChainCounts, sizeof(bucketChainCounts));
- dest += sizeof(bucketChainCounts);
- // write bucket values
- for (auto bi : _buckets) {
- uint32_t val = (bi);
- std::memcpy(dest, &val, sizeof(uint32_t));
- dest += sizeof(uint32_t);
- }
- // write chain values
- for (auto ci : _chains) {
- uint32_t val = (ci);
- std::memcpy(dest, &val, sizeof(uint32_t));
- dest += sizeof(uint32_t);
- }
- }
+ llvm::FileOutputBuffer &buffer) override;
private:
+ typedef
+ typename llvm::object::ELFDataTypeTypedefHelper<ELFT>::Elf_Word Elf_Word;
+
std::vector<SymbolTableEntry> _entries;
- std::vector<uint32_t> _buckets;
- std::vector<uint32_t> _chains;
- const DynamicSymbolTable<ELFT> *_symbolTable;
+ 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 &context, StringRef name,
- TargetLayout<ELFT> &layout, int32_t order)
- : Section<ELFT>(context, name, "EHFrameHeader"), _ehFrameOffset(0),
- _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;
- }
-
- void doPreFlight() override {
- // TODO: Generate a proper binary search table.
- }
-
- void finalize() override {
- OutputSection<ELFT> *s = _layout.findOutputSection(".eh_frame");
- OutputSection<ELFT> *h = _layout.findOutputSection(".eh_frame_hdr");
- if (s && h)
- _ehFrameOffset = s->virtualAddr() - (h->virtualAddr() + 4);
- }
-
+ 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 {
- 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;
- }
+ llvm::FileOutputBuffer &buffer) override;
private:
- int32_t _ehFrameOffset;
+ int32_t _ehFrameOffset = 0;
TargetLayout<ELFT> &_layout;
};
+
} // end namespace elf
} // end namespace lld
-#endif
+#endif // LLD_READER_WRITER_ELF_SECTION_CHUNKS_H
diff --git a/lib/ReaderWriter/ELF/SegmentChunks.cpp b/lib/ReaderWriter/ELF/SegmentChunks.cpp
new file mode 100644
index 000000000000..99449f7d45aa
--- /dev/null
+++ b/lib/ReaderWriter/ELF/SegmentChunks.cpp
@@ -0,0 +1,519 @@
+//===- 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
index f2a975aaeed0..b444f44c04eb 100644
--- a/lib/ReaderWriter/ELF/SegmentChunks.h
+++ b/lib/ReaderWriter/ELF/SegmentChunks.h
@@ -11,16 +11,13 @@
#define LLD_READER_WRITER_ELF_SEGMENT_CHUNKS_H
#include "Chunk.h"
-#include "Layout.h"
#include "SectionChunks.h"
#include "Writer.h"
#include "lld/Core/range.h"
#include "lld/Core/Writer.h"
-#include "llvm/ADT/ArrayRef.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"
@@ -29,7 +26,7 @@
namespace lld {
namespace elf {
-template <typename ELFT> class DefaultLayout;
+template <typename ELFT> class TargetLayout;
/// \brief A segment can be divided into segment slices
/// depending on how the segments can be split
@@ -38,8 +35,6 @@ class SegmentSlice {
public:
typedef typename std::vector<Chunk<ELFT> *>::iterator SectionIter;
- SegmentSlice() { }
-
/// Set the start of the slice.
void setStart(int32_t s) { _startSection = s; }
@@ -49,12 +44,10 @@ public:
// 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
@@ -75,9 +68,7 @@ public:
void setAlign(uint64_t align) { _alignment = align; }
- static bool compare_slices(SegmentSlice<ELFT> *a, SegmentSlice<ELFT> *b) {
- return a->startSection() < b->startSection();
- }
+ static bool compare_slices(SegmentSlice<ELFT> *a, SegmentSlice<ELFT> *b);
range<SectionIter> sections() { return _sections; }
@@ -100,8 +91,8 @@ public:
typedef typename std::vector<SegmentSlice<ELFT> *>::iterator SliceIter;
typedef typename std::vector<Chunk<ELFT> *>::iterator SectionIter;
- Segment(const ELFLinkingContext &context, StringRef name,
- const Layout::SegmentType type);
+ 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 {
@@ -144,37 +135,21 @@ public:
// Write the Segment
void write(ELFWriter *writer, TargetLayout<ELFT> &layout,
- llvm::FileOutputBuffer &buffer);
+ 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 assigning File Offsets / Virtual addresses
- void doPreFlight() {}
-
/// Finalize the segment, before we want to write the segment header
/// information
- void 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;
- }
- }
+ void finalize() override;
// For LLVM RTTI
static bool classof(const Chunk<ELFT> *c) {
@@ -185,76 +160,26 @@ public:
int32_t sectionCount() const { return _sections.size(); }
/// \brief, this function returns the type of segment (PT_*)
- Layout::SegmentType segmentType() { return _segmentType; }
+ 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
- virtual int 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;
- }
- }
-
- int pageSize() const { return this->_context.getPageSize(); }
+ int getContentType() const override;
+ int pageSize() const { return this->_ctx.getPageSize(); }
int rawflags() const { return _atomflags; }
-
- int64_t 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;
- }
- }
-
+ 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 {
- if (chunk->getContentType() == Chunk<ELFT>::ContentType::Data &&
- _outputMagic == ELFLinkingContext::OutputMagic::NMAGIC)
- return true;
- return false;
- }
+ bool needAlign(Chunk<ELFT> *chunk) const;
// Cached value of outputMagic
ELFLinkingContext::OutputMagic _outputMagic;
@@ -263,9 +188,10 @@ protected:
/// \brief Section or some other chunk type.
std::vector<Chunk<ELFT> *> _sections;
std::vector<SegmentSlice<ELFT> *> _segmentSlices;
- Layout::SegmentType _segmentType;
+ typename TargetLayout<ELFT>::SegmentType _segmentType;
uint64_t _flags;
int64_t _atomflags;
+ bool _segmentFlags;
llvm::BumpPtrAllocator _segmentAllocate;
};
@@ -286,10 +212,9 @@ public:
int getContentType() const override {
return Chunk<ELFT>::ContentType::Unknown;
}
+
void write(ELFWriter *, TargetLayout<ELFT> &,
llvm::FileOutputBuffer &) override {}
- void doPreFlight() override {}
- void finalize() override {}
std::error_code evalExpr(uint64_t &curPos) {
return _linkerScriptSema.evalExpr(_expr, curPos);
@@ -304,383 +229,18 @@ private:
/// The segment doesn't contain any slice
template <class ELFT> class ProgramHeaderSegment : public Segment<ELFT> {
public:
- ProgramHeaderSegment(const ELFLinkingContext &context)
- : Segment<ELFT>(context, "PHDR", llvm::ELF::PT_PHDR) {
+ 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() {
- // 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();
- }
-
+ void finalize() override;
};
-template <class ELFT>
-Segment<ELFT>::Segment(const ELFLinkingContext &context, StringRef name,
- const Layout::SegmentType type)
- : Chunk<ELFT>(name, Chunk<ELFT>::Kind::ELFSegment, context),
- _segmentType(type), _flags(0), _atomflags(0) {
- this->_alignment = 0;
- this->_fsize = 0;
- _outputMagic = context.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;
- }
-}
-
-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 (_flags < section->getFlags())
- _flags |= section->getFlags();
- if (_atomflags < toAtomPerms(_flags))
- _atomflags = toAtomPerms(_flags);
- if (this->_alignment < section->alignment())
- this->_alignment = section->alignment();
-}
-
-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->_context.alignSegments();
- uint64_t p_align = this->_context.getPageSize();
- uint64_t lastVirtualAddress = 0;
-
- this->setFileOffset(startOffset);
- for (auto &slice : slices()) {
- bool isFirstSection = true;
- for (auto section : slice->sections()) {
- // Handle linker script expressions, which may change the offset
- if (!isFirstSection)
- if (auto expr = dyn_cast<ExpressionChunk<ELFT>>(section))
- fileOffset += expr->virtualAddr() - lastVirtualAddress;
- // 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);
- else {
- // 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->_context.getPageSize());
- isDataPageAlignedForNMagic = true;
- }
- if (isFirstSection) {
- slice->setFileOffset(fileOffset);
- isFirstSection = false;
- curSliceFileOffset = fileOffset;
- }
- section->setFileOffset(fileOffset);
- fileOffset += section->fileSize();
- lastVirtualAddress = section->virtualAddr() + section->memSize();
- }
- 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 isFirstSection = true;
- bool isDataPageAlignedForNMagic = false;
- uint64_t startAddr = addr;
- SegmentSlice<ELFT> *slice = nullptr;
- uint64_t tlsStartAddr = 0;
- bool alignSegments = this->_context.alignSegments();
- StringRef prevOutputSectionName = StringRef();
-
- for (auto si = _sections.begin(); si != _sections.end(); ++si) {
- // 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.
- if (isFirstSection) {
- isFirstSection = false;
- 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->_context.getPageSize());
- else if (!isDataPageAlignedForNMagic && needAlign(*si)) {
- // If the linker outputmagic is set to OutputMagic::NMAGIC, align the
- // Data to a page boundary.
- startAddr =
- llvm::RoundUpToAlignment(startAddr, this->_context.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() != DefaultLayout<ELFT>::ORDER_TBSS)
- curSliceSize = (*si)->memSize();
- } else {
- 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->_context.getPageSize());
- isDataPageAlignedForNMagic = true;
- }
- uint64_t newAddr = llvm::RoundUpToAlignment(curAddr, (*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);
- Section<ELFT> *sec = dyn_cast<Section<ELFT>>(*si);
- StringRef curOutputSectionName;
- if (sec)
- curOutputSectionName = sec->outputSectionName();
- else {
- // If this is a linker script expression, propagate the name of the
- // previous section instead
- if (isa<ExpressionChunk<ELFT>>(*si))
- curOutputSectionName = prevOutputSectionName;
- else
- curOutputSectionName = (*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->_context.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;
- (*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();
- (*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() != DefaultLayout<ELFT>::ORDER_TBSS)
- curSliceSize = newAddr - curSliceAddress + (*si)->memSize();
- else
- curSliceSize = newAddr - curSliceAddress;
- }
- 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(curSliceAddress);
- 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 {
- 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;
-}
} // end namespace elf
} // end namespace lld
-#endif
+#endif // LLD_READER_WRITER_ELF_SEGMENT_CHUNKS_H
diff --git a/lib/ReaderWriter/ELF/TargetHandler.h b/lib/ReaderWriter/ELF/TargetHandler.h
index ca7a442276d1..406ac670fc83 100644
--- a/lib/ReaderWriter/ELF/TargetHandler.h
+++ b/lib/ReaderWriter/ELF/TargetHandler.h
@@ -6,78 +6,27 @@
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief These interfaces provide target specific hooks to change the linker's
-/// behaivor.
-///
-//===----------------------------------------------------------------------===//
#ifndef LLD_READER_WRITER_ELF_TARGET_HANDLER_H
#define LLD_READER_WRITER_ELF_TARGET_HANDLER_H
-#include "Layout.h"
-#include "lld/Core/Atom.h"
-#include "lld/Core/LLVM.h"
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/STDExtras.h"
-#include "lld/ReaderWriter/ELFLinkingContext.h"
-#include "llvm/ADT/Hashing.h"
-#include "llvm/ADT/StringRef.h"
+#include "lld/Core/Error.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include <memory>
-#include <vector>
namespace lld {
namespace elf {
-template <class ELFT> class DynamicTable;
-template <class ELFT> class DynamicSymbolTable;
-template <class ELFT> class ELFDefinedAtom;
-template <class ELFT> class ELFReference;
-class ELFWriter;
-template <class ELFT> class ELFHeader;
-template <class ELFT> class Section;
-template <class ELFT> class TargetLayout;
-
-class TargetRelocationHandler {
-public:
- /// Constructor
- TargetRelocationHandler() {}
- virtual ~TargetRelocationHandler() {}
-
- virtual std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
- const lld::AtomLayout &,
- const Reference &) const = 0;
-};
-
-/// \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.
-template <class ELFT> class TargetHandler : public TargetHandlerBase {
-public:
- /// The layout determined completely by the Target.
- virtual TargetLayout<ELFT> &getTargetLayout() = 0;
-
- /// Determine how relocations need to be applied.
- virtual const TargetRelocationHandler &getRelocationHandler() const = 0;
-
- /// How does the target deal with reading input files.
- virtual std::unique_ptr<Reader> getObjReader() = 0;
-
- /// How does the target deal with reading dynamic libraries.
- virtual std::unique_ptr<Reader> getDSOReader() = 0;
-
- /// How does the target deal with writing ELF output.
- virtual std::unique_ptr<Writer> getWriter() = 0;
-};
inline std::error_code make_unhandled_reloc_error() {
- return make_dynamic_error_code(Twine("Unhandled reference type"));
+ return make_dynamic_error_code("Unhandled reference type");
}
inline std::error_code make_out_of_range_reloc_error() {
- return make_dynamic_error_code(Twine("Relocation out of range"));
+ 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
diff --git a/lib/ReaderWriter/ELF/TargetLayout.cpp b/lib/ReaderWriter/ELF/TargetLayout.cpp
new file mode 100644
index 000000000000..09c49f62d64f
--- /dev/null
+++ b/lib/ReaderWriter/ELF/TargetLayout.cpp
@@ -0,0 +1,747 @@
+//===- 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
index ab7a7890a274..52512f8e279e 100644
--- a/lib/ReaderWriter/ELF/TargetLayout.h
+++ b/lib/ReaderWriter/ELF/TargetLayout.h
@@ -7,21 +7,320 @@
//
//===----------------------------------------------------------------------===//
-#ifndef LLD_READER_WRITER_ELF_TARGET_LAYOUT_H
-#define LLD_READER_WRITER_ELF_TARGET_LAYOUT_H
+#ifndef LLD_READER_WRITER_ELF_DEFAULT_LAYOUT_H
+#define LLD_READER_WRITER_ELF_DEFAULT_LAYOUT_H
-#include "DefaultLayout.h"
-#include "lld/Core/LLVM.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 target can override certain functions in the DefaultLayout
-/// class so that the order, the name of the section and the segment type could
-/// be changed in the final layout
-template <class ELFT> class TargetLayout : public DefaultLayout<ELFT> {
+
+/// \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:
- TargetLayout(ELFLinkingContext &context) : DefaultLayout<ELFT>(context) {}
+
+ // 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
diff --git a/lib/ReaderWriter/ELF/Writer.cpp b/lib/ReaderWriter/ELF/Writer.cpp
index 3071827e07d0..1c5d9766e9c5 100644
--- a/lib/ReaderWriter/ELF/Writer.cpp
+++ b/lib/ReaderWriter/ELF/Writer.cpp
@@ -16,8 +16,8 @@ using namespace llvm::object;
namespace lld {
-std::unique_ptr<Writer> createWriterELF(TargetHandlerBase *handler) {
- return std::move(handler->getWriter());
+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
index 1e819467c558..8b3e8f90638a 100644
--- a/lib/ReaderWriter/ELF/Writer.h
+++ b/lib/ReaderWriter/ELF/Writer.h
@@ -19,15 +19,12 @@ namespace elf {
/// various kinds of ELF files.
class ELFWriter : public Writer {
public:
- ELFWriter() { }
-
-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
- virtual std::error_code writeFile(const File &file, StringRef path) = 0;
+ 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;
@@ -35,4 +32,4 @@ public:
} // end namespace elf
} // end namespace lld
-#endif
+#endif // LLD_READER_WRITER_ELF_WRITER_H
diff --git a/lib/ReaderWriter/ELF/X86/Makefile b/lib/ReaderWriter/ELF/X86/Makefile
deleted file mode 100644
index 058d5133eaba..000000000000
--- a/lib/ReaderWriter/ELF/X86/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-##===- lld/lib/ReaderWriter/ELF/X86/Makefile ----------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL := ../../../..
-LIBRARYNAME := lldX86ELFTarget
-USEDLIBS = lldCore.a
-CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF
-
-include $(LLD_LEVEL)/Makefile
diff --git a/lib/ReaderWriter/ELF/X86/X86DynamicLibraryWriter.h b/lib/ReaderWriter/ELF/X86/X86DynamicLibraryWriter.h
index 86376295bec4..dd2184d7201e 100644
--- a/lib/ReaderWriter/ELF/X86/X86DynamicLibraryWriter.h
+++ b/lib/ReaderWriter/ELF/X86/X86DynamicLibraryWriter.h
@@ -15,50 +15,27 @@
namespace lld {
namespace elf {
-template <class ELFT>
-class X86DynamicLibraryWriter : public DynamicLibraryWriter<ELFT> {
+class X86DynamicLibraryWriter : public DynamicLibraryWriter<ELF32LE> {
public:
- X86DynamicLibraryWriter(X86LinkingContext &context,
- X86TargetLayout<ELFT> &layout);
+ X86DynamicLibraryWriter(X86LinkingContext &ctx,
+ TargetLayout<ELF32LE> &layout);
protected:
// Add any runtime files and their atoms to the output
- virtual bool createImplicitFiles(std::vector<std::unique_ptr<File>> &);
-
- virtual void finalizeDefaultAtomValues() {
- return DynamicLibraryWriter<ELFT>::finalizeDefaultAtomValues();
- }
-
- virtual void addDefaultAtoms() {
- return DynamicLibraryWriter<ELFT>::addDefaultAtoms();
- }
-
-private:
- class GOTFile : public SimpleFile {
- public:
- GOTFile(const ELFLinkingContext &eti) : SimpleFile("GOTFile") {}
- llvm::BumpPtrAllocator _alloc;
- };
-
- std::unique_ptr<GOTFile> _gotFile;
- X86LinkingContext &_context;
- X86TargetLayout<ELFT> &_x86Layout;
+ void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
};
-template <class ELFT>
-X86DynamicLibraryWriter<ELFT>::X86DynamicLibraryWriter(
- X86LinkingContext &context, X86TargetLayout<ELFT> &layout)
- : DynamicLibraryWriter<ELFT>(context, layout),
- _gotFile(new GOTFile(context)), _context(context), _x86Layout(layout) {}
+X86DynamicLibraryWriter::X86DynamicLibraryWriter(X86LinkingContext &ctx,
+ TargetLayout<ELF32LE> &layout)
+ : DynamicLibraryWriter(ctx, layout) {}
-template <class ELFT>
-bool X86DynamicLibraryWriter<ELFT>::createImplicitFiles(
+void X86DynamicLibraryWriter::createImplicitFiles(
std::vector<std::unique_ptr<File>> &result) {
- DynamicLibraryWriter<ELFT>::createImplicitFiles(result);
- _gotFile->addAtom(*new (_gotFile->_alloc) GLOBAL_OFFSET_TABLEAtom(*_gotFile));
- _gotFile->addAtom(*new (_gotFile->_alloc) DYNAMICAtom(*_gotFile));
- result.push_back(std::move(_gotFile));
- return true;
+ 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
diff --git a/lib/ReaderWriter/ELF/X86/X86ELFFile.h b/lib/ReaderWriter/ELF/X86/X86ELFFile.h
deleted file mode 100644
index 621c38c43505..000000000000
--- a/lib/ReaderWriter/ELF/X86/X86ELFFile.h
+++ /dev/null
@@ -1,41 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86/X86ELFFile.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_X86_ELF_FILE_H
-#define LLD_READER_WRITER_ELF_X86_X86_ELF_FILE_H
-
-#include "ELFReader.h"
-
-namespace lld {
-namespace elf {
-
-class X86LinkingContext;
-
-template <class ELFT> class X86ELFFile : public ELFFile<ELFT> {
-public:
- X86ELFFile(std::unique_ptr<MemoryBuffer> mb, X86LinkingContext &ctx)
- : ELFFile<ELFT>(std::move(mb), ctx) {}
-
- static ErrorOr<std::unique_ptr<X86ELFFile>>
- create(std::unique_ptr<MemoryBuffer> mb, X86LinkingContext &ctx) {
- return std::unique_ptr<X86ELFFile<ELFT>>(
- new X86ELFFile<ELFT>(std::move(mb), ctx));
- }
-};
-
-template <class ELFT> class X86DynamicFile : public DynamicFile<ELFT> {
-public:
- X86DynamicFile(const X86LinkingContext &context, StringRef name)
- : DynamicFile<ELFT>(context, name) {}
-};
-
-} // elf
-} // lld
-
-#endif // LLD_READER_WRITER_ELF_X86_X86_ELF_FILE_H
diff --git a/lib/ReaderWriter/ELF/X86/X86ELFReader.h b/lib/ReaderWriter/ELF/X86/X86ELFReader.h
deleted file mode 100644
index 96186c5eb024..000000000000
--- a/lib/ReaderWriter/ELF/X86/X86ELFReader.h
+++ /dev/null
@@ -1,62 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86/X86ELFReader.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_X86_X86_ELF_READER_H
-#define LLD_READER_WRITER_X86_X86_ELF_READER_H
-
-#include "ELFReader.h"
-#include "X86ELFFile.h"
-
-namespace lld {
-namespace elf {
-
-typedef llvm::object::ELFType<llvm::support::little, 2, false> X86ELFType;
-
-struct X86DynamicFileCreateELFTraits {
- typedef llvm::ErrorOr<std::unique_ptr<lld::SharedLibraryFile>> result_type;
-
- template <class ELFT>
- static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb,
- X86LinkingContext &ctx) {
- return lld::elf::X86DynamicFile<ELFT>::create(std::move(mb), ctx);
- }
-};
-
-struct X86ELFFileCreateELFTraits {
- typedef llvm::ErrorOr<std::unique_ptr<lld::File>> result_type;
-
- template <class ELFT>
- static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb,
- X86LinkingContext &ctx) {
- return lld::elf::X86ELFFile<ELFT>::create(std::move(mb), ctx);
- }
-};
-
-class X86ELFObjectReader
- : public ELFObjectReader<X86ELFType, X86ELFFileCreateELFTraits,
- X86LinkingContext> {
-public:
- X86ELFObjectReader(X86LinkingContext &ctx)
- : ELFObjectReader<X86ELFType, X86ELFFileCreateELFTraits,
- X86LinkingContext>(ctx, llvm::ELF::EM_386) {}
-};
-
-class X86ELFDSOReader
- : public ELFDSOReader<X86ELFType, X86DynamicFileCreateELFTraits,
- X86LinkingContext> {
-public:
- X86ELFDSOReader(X86LinkingContext &ctx)
- : ELFDSOReader<X86ELFType, X86DynamicFileCreateELFTraits,
- X86LinkingContext>(ctx, llvm::ELF::EM_386) {}
-};
-
-} // namespace elf
-} // namespace lld
-
-#endif // LLD_READER_WRITER_X86_X86_ELF_READER_H
diff --git a/lib/ReaderWriter/ELF/X86/X86ExecutableWriter.h b/lib/ReaderWriter/ELF/X86/X86ExecutableWriter.h
index 68acc06c2261..70aabde3ad2c 100644
--- a/lib/ReaderWriter/ELF/X86/X86ExecutableWriter.h
+++ b/lib/ReaderWriter/ELF/X86/X86ExecutableWriter.h
@@ -15,40 +15,22 @@
namespace lld {
namespace elf {
-template <class ELFT>
-class X86ExecutableWriter : public ExecutableWriter<ELFT> {
+class X86ExecutableWriter : public ExecutableWriter<ELF32LE> {
public:
- X86ExecutableWriter(X86LinkingContext &context,
- X86TargetLayout<ELFT> &layout);
+ X86ExecutableWriter(X86LinkingContext &ctx, TargetLayout<ELF32LE> &layout);
protected:
// Add any runtime files and their atoms to the output
- virtual bool createImplicitFiles(std::vector<std::unique_ptr<File>> &);
-
- virtual void finalizeDefaultAtomValues() {
- return ExecutableWriter<ELFT>::finalizeDefaultAtomValues();
- }
-
- virtual void addDefaultAtoms() {
- return ExecutableWriter<ELFT>::addDefaultAtoms();
- }
-
-private:
- X86LinkingContext &_context;
- X86TargetLayout<ELFT> &_x86Layout;
+ void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
};
-template <class ELFT>
-X86ExecutableWriter<ELFT>::X86ExecutableWriter(X86LinkingContext &context,
- X86TargetLayout<ELFT> &layout)
- : ExecutableWriter<ELFT>(context, layout), _context(context),
- _x86Layout(layout) {}
+X86ExecutableWriter::X86ExecutableWriter(X86LinkingContext &ctx,
+ TargetLayout<ELF32LE> &layout)
+ : ExecutableWriter(ctx, layout) {}
-template <class ELFT>
-bool X86ExecutableWriter<ELFT>::createImplicitFiles(
+void X86ExecutableWriter::createImplicitFiles(
std::vector<std::unique_ptr<File>> &result) {
- ExecutableWriter<ELFT>::createImplicitFiles(result);
- return true;
+ ExecutableWriter::createImplicitFiles(result);
}
} // namespace elf
diff --git a/lib/ReaderWriter/ELF/X86/X86LinkingContext.cpp b/lib/ReaderWriter/ELF/X86/X86LinkingContext.cpp
index 26d715cf2953..dc45efc390fd 100644
--- a/lib/ReaderWriter/ELF/X86/X86LinkingContext.cpp
+++ b/lib/ReaderWriter/ELF/X86/X86LinkingContext.cpp
@@ -14,15 +14,26 @@
#include "llvm/Support/ErrorOr.h"
using namespace lld;
+using namespace lld::elf;
std::unique_ptr<ELFLinkingContext>
-elf::X86LinkingContext::create(llvm::Triple triple) {
+elf::createX86LinkingContext(llvm::Triple triple) {
if (triple.getArch() == llvm::Triple::x86)
- return std::unique_ptr<ELFLinkingContext>(
- new elf::X86LinkingContext(triple));
+ return llvm::make_unique<X86LinkingContext>(triple);
return nullptr;
}
-elf::X86LinkingContext::X86LinkingContext(llvm::Triple triple)
- : ELFLinkingContext(triple, std::unique_ptr<TargetHandlerBase>(
- new X86TargetHandler(*this))) {}
+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
index ff424f411aae..f6ab3e980d7d 100644
--- a/lib/ReaderWriter/ELF/X86/X86LinkingContext.h
+++ b/lib/ReaderWriter/ELF/X86/X86LinkingContext.h
@@ -19,7 +19,9 @@ 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
diff --git a/lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp b/lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp
index da5a24c6ec37..15774bc33123 100644
--- a/lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp
+++ b/lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp
@@ -15,7 +15,6 @@ using namespace lld;
using namespace lld::elf;
using namespace llvm::support::endian;
-namespace {
/// \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);
@@ -25,33 +24,31 @@ static int reloc32(uint8_t *location, uint64_t P, uint64_t S, uint64_t A) {
/// \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);
+ 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 lld::AtomLayout &atom,
+ ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
const Reference &ref) const {
uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
- uint8_t *location = atomContent + ref.offsetInAtom();
- uint64_t targetVAddress = writer.addressOfAtom(ref.target());
- uint64_t relocVAddress = atom._virtualAddr + ref.offsetInAtom();
+ 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(location, relocVAddress, targetVAddress, ref.addend());
+ reloc32(loc, reloc, target, ref.addend());
break;
case R_386_PC32:
- relocPC32(location, relocVAddress, targetVAddress, ref.addend());
+ 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
index f161cdd55983..1131635c6735 100644
--- a/lib/ReaderWriter/ELF/X86/X86RelocationHandler.h
+++ b/lib/ReaderWriter/ELF/X86/X86RelocationHandler.h
@@ -10,16 +10,15 @@
#ifndef X86_X86_RELOCATION_HANDLER_H
#define X86_X86_RELOCATION_HANDLER_H
-#include "X86TargetHandler.h"
+#include "lld/ReaderWriter/ELFLinkingContext.h"
namespace lld {
namespace elf {
-typedef llvm::object::ELFType<llvm::support::little, 2, false> X86ELFType;
class X86TargetRelocationHandler final : public TargetRelocationHandler {
public:
std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
- const lld::AtomLayout &,
+ const AtomLayout &,
const Reference &) const override;
};
diff --git a/lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp b/lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp
index 22d918231424..c01ed7258f1c 100644
--- a/lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp
+++ b/lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp
@@ -19,13 +19,11 @@ using namespace elf;
using namespace llvm::ELF;
std::unique_ptr<Writer> X86TargetHandler::getWriter() {
- switch (_x86LinkingContext.getOutputELFType()) {
+ switch (_ctx.getOutputELFType()) {
case llvm::ELF::ET_EXEC:
- return std::unique_ptr<Writer>(new X86ExecutableWriter<X86ELFType>(
- _x86LinkingContext, *_x86TargetLayout.get()));
+ return llvm::make_unique<X86ExecutableWriter>(_ctx, *_targetLayout);
case llvm::ELF::ET_DYN:
- return std::unique_ptr<Writer>(new X86DynamicLibraryWriter<X86ELFType>(
- _x86LinkingContext, *_x86TargetLayout.get()));
+ return llvm::make_unique<X86DynamicLibraryWriter>(_ctx, *_targetLayout);
case llvm::ELF::ET_REL:
llvm_unreachable("TODO: support -r mode");
default:
@@ -33,21 +31,6 @@ std::unique_ptr<Writer> X86TargetHandler::getWriter() {
}
}
-#define ELF_RELOC(name, value) LLD_KIND_STRING_ENTRY(name),
-
-const Registry::KindStrings X86TargetHandler::kindStrings[] = {
-#include "llvm/Support/ELFRelocs/i386.def"
- LLD_KIND_STRING_END
-};
-
-#undef ELF_RELOC
-
-void X86TargetHandler::registerRelocationNames(Registry &registry) {
- registry.addKindTable(Reference::KindNamespace::ELF, Reference::KindArch::x86,
- kindStrings);
-}
-
-X86TargetHandler::X86TargetHandler(X86LinkingContext &context)
- : _x86LinkingContext(context),
- _x86TargetLayout(new X86TargetLayout<X86ELFType>(context)),
- _x86RelocationHandler(new X86TargetRelocationHandler()) {}
+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
index 6c4026735419..fecf9abfc678 100644
--- a/lib/ReaderWriter/ELF/X86/X86TargetHandler.h
+++ b/lib/ReaderWriter/ELF/X86/X86TargetHandler.h
@@ -10,10 +10,8 @@
#ifndef LLD_READER_WRITER_ELF_X86_TARGET_HANDLER_H
#define LLD_READER_WRITER_ELF_X86_TARGET_HANDLER_H
-#include "DefaultTargetHandler.h"
#include "TargetLayout.h"
-#include "X86ELFFile.h"
-#include "X86ELFReader.h"
+#include "ELFReader.h"
#include "X86RelocationHandler.h"
namespace lld {
@@ -21,41 +19,28 @@ namespace elf {
class X86LinkingContext;
-template <class ELFT> class X86TargetLayout : public TargetLayout<ELFT> {
+class X86TargetHandler final : public TargetHandler {
public:
- X86TargetLayout(X86LinkingContext &context) : TargetLayout<ELFT>(context) {}
-};
-
-class X86TargetHandler final
- : public DefaultTargetHandler<X86ELFType> {
-public:
- X86TargetHandler(X86LinkingContext &context);
-
- X86TargetLayout<X86ELFType> &getTargetLayout() override {
- return *(_x86TargetLayout.get());
- }
-
- void registerRelocationNames(Registry &registry) override;
+ X86TargetHandler(X86LinkingContext &ctx);
- const X86TargetRelocationHandler &getRelocationHandler() const override {
- return *(_x86RelocationHandler.get());
+ const TargetRelocationHandler &getRelocationHandler() const override {
+ return *_relocationHandler;
}
std::unique_ptr<Reader> getObjReader() override {
- return std::unique_ptr<Reader>(new X86ELFObjectReader(_x86LinkingContext));
+ return llvm::make_unique<ELFReader<ELFFile<ELF32LE>>>(_ctx);
}
std::unique_ptr<Reader> getDSOReader() override {
- return std::unique_ptr<Reader>(new X86ELFDSOReader(_x86LinkingContext));
+ return llvm::make_unique<ELFReader<DynamicFile<ELF32LE>>>(_ctx);
}
std::unique_ptr<Writer> getWriter() override;
protected:
- static const Registry::KindStrings kindStrings[];
- X86LinkingContext &_x86LinkingContext;
- std::unique_ptr<X86TargetLayout<X86ELFType>> _x86TargetLayout;
- std::unique_ptr<X86TargetRelocationHandler> _x86RelocationHandler;
+ X86LinkingContext &_ctx;
+ std::unique_ptr<TargetLayout<ELF32LE>> _targetLayout;
+ std::unique_ptr<X86TargetRelocationHandler> _relocationHandler;
};
} // end namespace elf
} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt b/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt
index a85d2b504630..36ea839aa674 100644
--- a/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt
+++ b/lib/ReaderWriter/ELF/X86_64/CMakeLists.txt
@@ -3,6 +3,7 @@ add_llvm_library(lldX86_64ELFTarget
X86_64TargetHandler.cpp
X86_64RelocationHandler.cpp
X86_64RelocationPass.cpp
+ X86_64SectionChunks.cpp
LINK_LIBS
lldELF
lldReaderWriter
diff --git a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.cpp b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.cpp
index dbbb3ad3bc90..cb3e819aff6b 100644
--- a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.cpp
+++ b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.cpp
@@ -14,14 +14,14 @@ using namespace lld;
using namespace elf;
std::unique_ptr<ELFLinkingContext>
-ExampleLinkingContext::create(llvm::Triple triple) {
+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<TargetHandlerBase>(
+ : X86_64LinkingContext(triple, std::unique_ptr<TargetHandler>(
new ExampleTargetHandler(*this))) {
_outputELFType = llvm::ELF::ET_LOPROC;
}
diff --git a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.cpp b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.cpp
index b66b0d903f6a..89ec6671f3a0 100644
--- a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.cpp
+++ b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.cpp
@@ -15,9 +15,8 @@ using namespace lld;
using namespace elf;
ExampleTargetHandler::ExampleTargetHandler(ExampleLinkingContext &c)
- : X86_64TargetHandler(c), _exampleContext(c) {}
+ : X86_64TargetHandler(c), _ctx(c) {}
std::unique_ptr<Writer> ExampleTargetHandler::getWriter() {
- return std::unique_ptr<Writer>(
- new X86_64ExecutableWriter(_exampleContext, *_x86_64TargetLayout));
+ 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
index 19a642113359..46eade5864f9 100644
--- a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.h
+++ b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.h
@@ -23,7 +23,7 @@ public:
std::unique_ptr<Writer> getWriter() override;
private:
- ExampleLinkingContext &_exampleContext;
+ ExampleLinkingContext &_ctx;
};
} // end namespace elf
} // end namespace lld
diff --git a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/Makefile b/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/Makefile
deleted file mode 100644
index 8f0b0fead1f6..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-##===- lld/lib/ReaderWriter/ELF/X86_64/Makefile ----------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL := ../../../../..
-LIBRARYNAME := lldExampleSubTarget
-USEDLIBS = lldX86_64ELFTarget.a
-CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF
-
-include $(LLD_LEVEL)/Makefile
diff --git a/lib/ReaderWriter/ELF/X86_64/Makefile b/lib/ReaderWriter/ELF/X86_64/Makefile
deleted file mode 100644
index dbeb4d227050..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/Makefile
+++ /dev/null
@@ -1,19 +0,0 @@
-##===- lld/lib/ReaderWriter/ELF/X86_64/Makefile ----------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL := ../../../..
-LIBRARYNAME := lldX86_64ELFTarget
-USEDLIBS = lldCore.a
-
-CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF
-CPP.Flags += -I$(PROJ_SRC_DIR)/$(LLD_LEVEL)/lib/ReaderWriter/ELF/X86_64/
-
-PARALLEL_DIRS := ExampleSubTarget
-
-include $(LLD_LEVEL)/Makefile
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h b/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h
index b996186115b6..f84f85223bfb 100644
--- a/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h
+++ b/lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h
@@ -10,51 +10,33 @@
#define X86_64_DYNAMIC_LIBRARY_WRITER_H
#include "DynamicLibraryWriter.h"
-#include "X86_64ElfType.h"
#include "X86_64LinkingContext.h"
#include "X86_64TargetHandler.h"
namespace lld {
namespace elf {
-class X86_64DynamicLibraryWriter : public DynamicLibraryWriter<X86_64ELFType> {
+class X86_64DynamicLibraryWriter : public DynamicLibraryWriter<ELF64LE> {
public:
- X86_64DynamicLibraryWriter(X86_64LinkingContext &context,
+ X86_64DynamicLibraryWriter(X86_64LinkingContext &ctx,
X86_64TargetLayout &layout);
protected:
// Add any runtime files and their atoms to the output
- virtual bool createImplicitFiles(std::vector<std::unique_ptr<File>> &);
-
- virtual void finalizeDefaultAtomValues() {
- return DynamicLibraryWriter::finalizeDefaultAtomValues();
- }
-
- virtual void addDefaultAtoms() {
- return DynamicLibraryWriter::addDefaultAtoms();
- }
-
-private:
- class GOTFile : public SimpleFile {
- public:
- GOTFile(const ELFLinkingContext &eti) : SimpleFile("GOTFile") {}
- llvm::BumpPtrAllocator _alloc;
- };
-
- std::unique_ptr<GOTFile> _gotFile;
+ void createImplicitFiles(std::vector<std::unique_ptr<File>> &) override;
};
X86_64DynamicLibraryWriter::X86_64DynamicLibraryWriter(
- X86_64LinkingContext &context, X86_64TargetLayout &layout)
- : DynamicLibraryWriter(context, layout), _gotFile(new GOTFile(context)) {}
+ X86_64LinkingContext &ctx, X86_64TargetLayout &layout)
+ : DynamicLibraryWriter(ctx, layout) {}
-bool X86_64DynamicLibraryWriter::createImplicitFiles(
+void X86_64DynamicLibraryWriter::createImplicitFiles(
std::vector<std::unique_ptr<File>> &result) {
DynamicLibraryWriter::createImplicitFiles(result);
- _gotFile->addAtom(*new (_gotFile->_alloc) GLOBAL_OFFSET_TABLEAtom(*_gotFile));
- _gotFile->addAtom(*new (_gotFile->_alloc) DYNAMICAtom(*_gotFile));
- result.push_back(std::move(_gotFile));
- return true;
+ 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
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64ELFFile.h b/lib/ReaderWriter/ELF/X86_64/X86_64ELFFile.h
deleted file mode 100644
index d43840a63e7e..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/X86_64ELFFile.h
+++ /dev/null
@@ -1,41 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86_64/X86_64ELFFile.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_ELF_FILE_H
-#define LLD_READER_WRITER_ELF_X86_64_ELF_FILE_H
-
-#include "ELFReader.h"
-
-namespace lld {
-namespace elf {
-
-class X86_64LinkingContext;
-
-template <class ELFT> class X86_64ELFFile : public ELFFile<ELFT> {
-public:
- X86_64ELFFile(std::unique_ptr<MemoryBuffer> mb, X86_64LinkingContext &ctx)
- : ELFFile<ELFT>(std::move(mb), ctx) {}
-
- static ErrorOr<std::unique_ptr<X86_64ELFFile>>
- create(std::unique_ptr<MemoryBuffer> mb, X86_64LinkingContext &ctx) {
- return std::unique_ptr<X86_64ELFFile<ELFT>>(
- new X86_64ELFFile<ELFT>(std::move(mb), ctx));
- }
-};
-
-template <class ELFT> class X86_64DynamicFile : public DynamicFile<ELFT> {
-public:
- X86_64DynamicFile(const X86_64LinkingContext &context, StringRef name)
- : DynamicFile<ELFT>(context, name) {}
-};
-
-} // elf
-} // lld
-
-#endif // LLD_READER_WRITER_ELF_X86_64_ELF_FILE_H
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64ELFReader.h b/lib/ReaderWriter/ELF/X86_64/X86_64ELFReader.h
deleted file mode 100644
index 9b1284c6dfa8..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/X86_64ELFReader.h
+++ /dev/null
@@ -1,62 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86_64/X86_64ELFReader.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_X86_64_X86_64_ELF_READER_H
-#define LLD_READER_WRITER_X86_64_X86_64_ELF_READER_H
-
-#include "ELFReader.h"
-#include "X86_64ELFFile.h"
-
-namespace lld {
-namespace elf {
-
-typedef llvm::object::ELFType<llvm::support::little, 2, true> X86_64ELFType;
-
-struct X86_64DynamicFileCreateELFTraits {
- typedef llvm::ErrorOr<std::unique_ptr<lld::SharedLibraryFile>> result_type;
-
- template <class ELFT>
- static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb,
- X86_64LinkingContext &ctx) {
- return lld::elf::X86_64DynamicFile<ELFT>::create(std::move(mb), ctx);
- }
-};
-
-struct X86_64ELFFileCreateELFTraits {
- typedef llvm::ErrorOr<std::unique_ptr<lld::File>> result_type;
-
- template <class ELFT>
- static result_type create(std::unique_ptr<llvm::MemoryBuffer> mb,
- X86_64LinkingContext &ctx) {
- return lld::elf::X86_64ELFFile<ELFT>::create(std::move(mb), ctx);
- }
-};
-
-class X86_64ELFObjectReader
- : public ELFObjectReader<X86_64ELFType, X86_64ELFFileCreateELFTraits,
- X86_64LinkingContext> {
-public:
- X86_64ELFObjectReader(X86_64LinkingContext &ctx)
- : ELFObjectReader<X86_64ELFType, X86_64ELFFileCreateELFTraits,
- X86_64LinkingContext>(ctx, llvm::ELF::EM_X86_64) {}
-};
-
-class X86_64ELFDSOReader
- : public ELFDSOReader<X86_64ELFType, X86_64DynamicFileCreateELFTraits,
- X86_64LinkingContext> {
-public:
- X86_64ELFDSOReader(X86_64LinkingContext &ctx)
- : ELFDSOReader<X86_64ELFType, X86_64DynamicFileCreateELFTraits,
- X86_64LinkingContext>(ctx, llvm::ELF::EM_X86_64) {}
-};
-
-} // namespace elf
-} // namespace lld
-
-#endif // LLD_READER_WRITER_ELF_X86_64_X86_64_READER_H
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64ElfType.h b/lib/ReaderWriter/ELF/X86_64/X86_64ElfType.h
deleted file mode 100644
index 0b982e7754e2..000000000000
--- a/lib/ReaderWriter/ELF/X86_64/X86_64ElfType.h
+++ /dev/null
@@ -1,21 +0,0 @@
-//===- lib/ReaderWriter/ELF/X86_64/X86_64ElfType.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_ELF_TYPE_H
-#define LLD_READER_WRITER_ELF_X86_64_X86_64_ELF_TYPE_H
-
-#include "llvm/Object/ELF.h"
-
-namespace lld {
-namespace elf {
-typedef llvm::object::ELFType<llvm::support::little, 2, true> X86_64ELFType;
-}
-}
-
-#endif
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h b/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h
index f549ed6dcfcb..930a2de2a9e8 100644
--- a/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h
+++ b/lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h
@@ -10,49 +10,45 @@
#define X86_64_EXECUTABLE_WRITER_H
#include "ExecutableWriter.h"
-#include "X86_64ElfType.h"
#include "X86_64LinkingContext.h"
namespace lld {
namespace elf {
-class X86_64ExecutableWriter : public ExecutableWriter<X86_64ELFType> {
+class X86_64ExecutableWriter : public ExecutableWriter<ELF64LE> {
public:
- X86_64ExecutableWriter(X86_64LinkingContext &context,
- X86_64TargetLayout &layout)
- : ExecutableWriter(context, layout), _gotFile(new GOTFile(context)),
- _context(context) {}
+ X86_64ExecutableWriter(X86_64LinkingContext &ctx, X86_64TargetLayout &layout)
+ : ExecutableWriter(ctx, layout), _targetLayout(layout) {}
protected:
// Add any runtime files and their atoms to the output
- virtual bool
- createImplicitFiles(std::vector<std::unique_ptr<File>> &result) {
+ void
+ createImplicitFiles(std::vector<std::unique_ptr<File>> &result) override {
ExecutableWriter::createImplicitFiles(result);
- _gotFile->addAtom(*new (_gotFile->_alloc)
- GLOBAL_OFFSET_TABLEAtom(*_gotFile));
- if (_context.isDynamic())
- _gotFile->addAtom(*new (_gotFile->_alloc) DYNAMICAtom(*_gotFile));
- result.push_back(std::move(_gotFile));
- return true;
+ 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));
}
- virtual void finalizeDefaultAtomValues() {
- return ExecutableWriter::finalizeDefaultAtomValues();
+ 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);
}
- virtual void addDefaultAtoms() {
- return ExecutableWriter::addDefaultAtoms();
- }
-
-private:
- class GOTFile : public SimpleFile {
- public:
- GOTFile(const ELFLinkingContext &eti) : SimpleFile("GOTFile") {}
- llvm::BumpPtrAllocator _alloc;
- };
-
- std::unique_ptr<GOTFile> _gotFile;
- X86_64LinkingContext &_context;
+ X86_64TargetLayout &_targetLayout;
};
} // namespace elf
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp b/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp
index 6a8ce8bd6496..0dcd6ac6fbed 100644
--- a/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp
+++ b/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp
@@ -12,10 +12,10 @@
#include "X86_64TargetHandler.h"
using namespace lld;
-using namespace elf;
+using namespace lld::elf;
X86_64LinkingContext::X86_64LinkingContext(
- llvm::Triple triple, std::unique_ptr<TargetHandlerBase> handler)
+ llvm::Triple triple, std::unique_ptr<TargetHandler> handler)
: ELFLinkingContext(triple, std::move(handler)) {}
X86_64LinkingContext::X86_64LinkingContext(llvm::Triple triple)
@@ -30,9 +30,21 @@ void X86_64LinkingContext::addPasses(PassManager &pm) {
}
std::unique_ptr<ELFLinkingContext>
-X86_64LinkingContext::create(llvm::Triple triple) {
+elf::createX86_64LinkingContext(llvm::Triple triple) {
if (triple.getArch() == llvm::Triple::x86_64)
- return std::unique_ptr<ELFLinkingContext>(
- new elf::X86_64LinkingContext(triple));
+ 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
index 2cc799a9c810..a5a7b3d21f4e 100644
--- a/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h
+++ b/lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h
@@ -26,12 +26,15 @@ enum {
class X86_64LinkingContext : public ELFLinkingContext {
protected:
- X86_64LinkingContext(llvm::Triple, std::unique_ptr<TargetHandlerBase>);
+ 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)
@@ -65,7 +68,7 @@ public:
return false;
}
- virtual bool isPLTRelocation(const Reference &r) const override {
+ bool isPLTRelocation(const Reference &r) const override {
if (r.kindNamespace() != Reference::KindNamespace::ELF)
return false;
assert(r.kindArch() == Reference::KindArch::x86_64);
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp b/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp
index 8fd74f43bbd2..d56983d1e382 100644
--- a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp
+++ b/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp
@@ -23,7 +23,7 @@ static void reloc64(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
/// \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);
+ uint32_t result = (uint32_t)(S + A - P);
write32le(location, result + read32le(location));
}
@@ -50,24 +50,24 @@ static void reloc16(uint8_t *location, uint64_t P, uint64_t S, int64_t A) {
/// \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);
+ 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);
+ 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 lld::AtomLayout &atom,
+ ELFWriter &writer, llvm::FileOutputBuffer &buf, const AtomLayout &atom,
const Reference &ref) const {
uint8_t *atomContent = buf.getBufferStart() + atom._fileOffset;
- uint8_t *location = atomContent + ref.offsetInAtom();
- uint64_t targetVAddress = writer.addressOfAtom(ref.target());
- uint64_t relocVAddress = atom._virtualAddr + ref.offsetInAtom();
+ 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();
@@ -76,38 +76,34 @@ std::error_code X86_64TargetRelocationHandler::applyRelocation(
case R_X86_64_NONE:
break;
case R_X86_64_64:
- reloc64(location, relocVAddress, targetVAddress, ref.addend());
+ reloc64(loc, reloc, target, ref.addend());
break;
case R_X86_64_PC32:
case R_X86_64_GOTPCREL:
- relocPC32(location, relocVAddress, targetVAddress, ref.addend());
+ relocPC32(loc, reloc, target, ref.addend());
break;
case R_X86_64_32:
- reloc32(location, relocVAddress, targetVAddress, ref.addend());
+ reloc32(loc, reloc, target, ref.addend());
break;
case R_X86_64_32S:
- reloc32S(location, relocVAddress, targetVAddress, ref.addend());
+ reloc32S(loc, reloc, target, ref.addend());
break;
case R_X86_64_16:
- reloc16(location, relocVAddress, targetVAddress, ref.addend());
+ reloc16(loc, reloc, target, ref.addend());
break;
case R_X86_64_PC16:
- relocPC16(location, relocVAddress, targetVAddress, ref.addend());
+ relocPC16(loc, reloc, target, ref.addend());
break;
- case R_X86_64_TPOFF64:
case R_X86_64_DTPOFF32:
- case R_X86_64_TPOFF32: {
- _tlsSize = _x86_64Layout.getTLSSize();
- if (ref.kindValue() == R_X86_64_TPOFF32 ||
- ref.kindValue() == R_X86_64_DTPOFF32) {
- write32le(location, targetVAddress - _tlsSize);
- } else {
- write64le(location, targetVAddress - _tlsSize);
- }
+ 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(location, relocVAddress, targetVAddress, ref.addend());
+ relocPC32(loc, reloc, target, ref.addend());
break;
}
case R_X86_64_TLSLD: {
@@ -115,21 +111,20 @@ std::error_code X86_64TargetRelocationHandler::applyRelocation(
// 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(location - 3, instr, sizeof(instr));
+ std::memcpy(loc - 3, instr, sizeof(instr));
break;
}
case R_X86_64_PC64:
- relocPC64(location, relocVAddress, targetVAddress, ref.addend());
+ 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 (!_x86_64Layout.getPLTRelocationTable()->getRelocationIndex(*r,
- index))
+ if (!_layout.getPLTRelocationTable()->getRelocationIndex(*r, index))
llvm_unreachable("Relocation doesn't exist");
- reloc32(location, 0, index, 0);
+ reloc32(loc, 0, index, 0);
break;
}
}
@@ -142,6 +137,7 @@ std::error_code X86_64TargetRelocationHandler::applyRelocation(
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();
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h b/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h
index 9e2c2171015d..26382804549b 100644
--- a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h
+++ b/lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h
@@ -10,27 +10,25 @@
#ifndef X86_64_RELOCATION_HANDLER_H
#define X86_64_RELOCATION_HANDLER_H
-#include "X86_64TargetHandler.h"
+#include "lld/ReaderWriter/ELFLinkingContext.h"
namespace lld {
namespace elf {
-typedef llvm::object::ELFType<llvm::support::little, 2, true> X86_64ELFType;
-
class X86_64TargetLayout;
class X86_64TargetRelocationHandler final : public TargetRelocationHandler {
public:
X86_64TargetRelocationHandler(X86_64TargetLayout &layout)
- : _tlsSize(0), _x86_64Layout(layout) {}
+ : _tlsSize(0), _layout(layout) {}
std::error_code applyRelocation(ELFWriter &, llvm::FileOutputBuffer &,
- const lld::AtomLayout &,
+ const AtomLayout &,
const Reference &) const override;
private:
// Cached size of the TLS segment.
mutable uint64_t _tlsSize;
- X86_64TargetLayout &_x86_64Layout;
+ X86_64TargetLayout &_layout;
};
} // end namespace elf
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp b/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp
index 0703927fd56c..a2f10dc08a4e 100644
--- a/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp
+++ b/lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp
@@ -188,11 +188,12 @@ protected:
return got->second;
}
- /// \brief Create a TPOFF64 GOT entry and change the relocation to a PC32 to
- /// the GOT.
- void handleGOTTPOFF(const Reference &ref) {
- const_cast<Reference &>(ref).setTarget(getGOTTPOFF(ref.target()));
- const_cast<Reference &>(ref).setKindValue(R_X86_64_PC32);
+ /// \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.
@@ -243,9 +244,7 @@ protected:
}
public:
- RelocationPass(const ELFLinkingContext &ctx)
- : _file(ctx), _ctx(ctx), _null(nullptr), _PLT0(nullptr), _got0(nullptr),
- _got1(nullptr) {}
+ RelocationPass(const ELFLinkingContext &ctx) : _file(ctx), _ctx(ctx) {}
/// \brief Do the pass.
///
@@ -255,45 +254,46 @@ public:
///
/// After all references are handled, the atoms created during that are all
/// added to mf.
- void perform(std::unique_ptr<MutableFile> &mf) override {
+ 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 &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);
+ if (_plt0) {
+ _plt0->setOrdinal(ordinal++);
+ mf.addAtom(*_plt0);
}
for (auto &plt : _pltVector) {
plt->setOrdinal(ordinal++);
- mf->addAtom(*plt);
+ mf.addAtom(*plt);
}
if (_null) {
_null->setOrdinal(ordinal++);
- mf->addAtom(*_null);
+ mf.addAtom(*_null);
}
- if (_PLT0) {
+ if (_plt0) {
_got0->setOrdinal(ordinal++);
_got1->setOrdinal(ordinal++);
- mf->addAtom(*_got0);
- mf->addAtom(*_got1);
+ mf.addAtom(*_got0);
+ mf.addAtom(*_got1);
}
for (auto &got : _gotVector) {
got->setOrdinal(ordinal++);
- mf->addAtom(*got);
+ mf.addAtom(*got);
}
for (auto &got : _tlsGotVector) {
got->setOrdinal(ordinal++);
- mf->addAtom(*got);
+ mf.addAtom(*got);
}
for (auto obj : _objectVector) {
obj->setOrdinal(ordinal++);
- mf->addAtom(*obj);
+ mf.addAtom(*obj);
}
+ return std::error_code();
}
protected:
@@ -322,14 +322,14 @@ protected:
std::vector<GOTAtom *> _tlsGotVector;
/// \brief GOT entry that is always 0. Used for undefined weaks.
- GOTAtom *_null;
+ 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;
- GOTAtom *_got0;
- GOTAtom *_got1;
+ PLT0Atom *_plt0 = nullptr;
+ GOTAtom *_got0 = nullptr;
+ GOTAtom *_got1 = nullptr;
/// @}
};
@@ -379,20 +379,20 @@ public:
: RelocationPass(ctx) {}
const PLT0Atom *getPLT0() {
- if (_PLT0)
- return _PLT0;
+ if (_plt0)
+ return _plt0;
// Fill in the null entry.
getNullGOT();
- _PLT0 = new (_file._alloc) X86_64PLT0Atom(_file);
+ _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);
+ _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;
+ return _plt0;
}
const PLTAtom *getPLTEntry(const Atom *a) {
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp b/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp
new file mode 100644
index 000000000000..28eb3e4244b6
--- /dev/null
+++ b/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp
@@ -0,0 +1,37 @@
+//===- 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
new file mode 100644
index 000000000000..5208491eee55
--- /dev/null
+++ b/lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h
@@ -0,0 +1,36 @@
+//===- 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
index f35330eb25c0..599077ac33c5 100644
--- a/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp
+++ b/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp
@@ -16,37 +16,19 @@
using namespace lld;
using namespace elf;
-X86_64TargetHandler::X86_64TargetHandler(X86_64LinkingContext &context)
- : _context(context), _x86_64TargetLayout(new X86_64TargetLayout(context)),
- _x86_64RelocationHandler(
- new X86_64TargetRelocationHandler(*_x86_64TargetLayout.get())) {}
-
-void X86_64TargetHandler::registerRelocationNames(Registry &registry) {
- registry.addKindTable(Reference::KindNamespace::ELF,
- Reference::KindArch::x86_64, kindStrings);
-}
+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->_context.getOutputELFType()) {
+ switch (this->_ctx.getOutputELFType()) {
case llvm::ELF::ET_EXEC:
- return std::unique_ptr<Writer>(
- new X86_64ExecutableWriter(_context, *_x86_64TargetLayout.get()));
+ return llvm::make_unique<X86_64ExecutableWriter>(_ctx, *_targetLayout);
case llvm::ELF::ET_DYN:
- return std::unique_ptr<Writer>(
- new X86_64DynamicLibraryWriter(_context, *_x86_64TargetLayout.get()));
+ 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");
}
}
-
-#define ELF_RELOC(name, value) LLD_KIND_STRING_ENTRY(name),
-
-const Registry::KindStrings X86_64TargetHandler::kindStrings[] = {
-#include "llvm/Support/ELFRelocs/x86_64.def"
- LLD_KIND_STRING_ENTRY(LLD_R_X86_64_GOTRELINDEX),
- LLD_KIND_STRING_END
-};
-
-#undef ELF_RELOC
diff --git a/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h b/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h
index 57da7bca01e6..6e3e58f8aed6 100644
--- a/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h
+++ b/lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h
@@ -10,57 +10,92 @@
#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 "DefaultTargetHandler.h"
+#include "ELFReader.h"
#include "TargetLayout.h"
-#include "X86_64ELFFile.h"
-#include "X86_64ELFReader.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<X86_64ELFType> {
+
+
+class X86_64TargetLayout : public TargetLayout<ELF64LE> {
public:
- X86_64TargetLayout(X86_64LinkingContext &context)
- : TargetLayout(context) {}
+ 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(".init_array", ".init_array");
- sortOutputSectionByPriority(".fini_array", ".fini_array");
+ sortOutputSectionByPriority<ELF64LE>(".init_array");
+ sortOutputSectionByPriority<ELF64LE>(".fini_array");
}
-};
-class X86_64TargetHandler
- : public DefaultTargetHandler<X86_64ELFType> {
-public:
- X86_64TargetHandler(X86_64LinkingContext &context);
+ const X86_64GOTSection &getGOTSection() const { return *_gotSection; }
- X86_64TargetLayout &getTargetLayout() override {
- return *(_x86_64TargetLayout.get());
+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;
}
- void registerRelocationNames(Registry &registry) override;
+ 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 X86_64TargetRelocationHandler &getRelocationHandler() const override {
- return *(_x86_64RelocationHandler.get());
+ const TargetRelocationHandler &getRelocationHandler() const override {
+ return *_relocationHandler;
}
std::unique_ptr<Reader> getObjReader() override {
- return std::unique_ptr<Reader>(new X86_64ELFObjectReader(_context));
+ return llvm::make_unique<ELFReader<ELFFile<ELF64LE>>>(_ctx);
}
std::unique_ptr<Reader> getDSOReader() override {
- return std::unique_ptr<Reader>(new X86_64ELFDSOReader(_context));
+ return llvm::make_unique<ELFReader<DynamicFile<ELF64LE>>>(_ctx);
}
std::unique_ptr<Writer> getWriter() override;
protected:
- static const Registry::KindStrings kindStrings[];
- X86_64LinkingContext &_context;
- std::unique_ptr<X86_64TargetLayout> _x86_64TargetLayout;
- std::unique_ptr<X86_64TargetRelocationHandler> _x86_64RelocationHandler;
+ X86_64LinkingContext &_ctx;
+ std::unique_ptr<X86_64TargetLayout> _targetLayout;
+ std::unique_ptr<X86_64TargetRelocationHandler> _relocationHandler;
};
} // end namespace elf
diff --git a/lib/ReaderWriter/FileArchive.cpp b/lib/ReaderWriter/FileArchive.cpp
index 3f38814ae18e..a09923f57d07 100644
--- a/lib/ReaderWriter/FileArchive.cpp
+++ b/lib/ReaderWriter/FileArchive.cpp
@@ -11,6 +11,7 @@
#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 "llvm/ADT/StringRef.h"
#include "llvm/Object/Archive.h"
@@ -48,9 +49,14 @@ public:
if (member == _symbolMemberMap.end())
return nullptr;
Archive::child_iterator ci = member->second;
+ if (ci->getError())
+ return nullptr;
// Don't return a member already returned
- const char *memberStart = ci->getBuffer().data();
+ ErrorOr<StringRef> buf = (*ci)->getBuffer();
+ if (!buf)
+ return nullptr;
+ const char *memberStart = buf->data();
if (_membersInstantiated.count(memberStart))
return nullptr;
if (dataSymbolOnly && !isDataSymbol(ci, name))
@@ -73,8 +79,11 @@ public:
if (instantiateMember(ci, result))
return nullptr;
- // give up the pointer so that this object no longer manages it
- return result.release();
+ File *file = result.get();
+ _filesReturned.push_back(std::move(result));
+
+ // Give up the file pointer. It was stored and will be destroyed with destruction of FileArchive
+ return file;
}
// Instantiate a member file containing a given symbol name.
@@ -83,9 +92,14 @@ public:
if (member == _symbolMemberMap.end())
return;
Archive::child_iterator ci = member->second;
+ if (ci->getError())
+ return;
// Do nothing if a member is already instantiated.
- const char *memberStart = ci->getBuffer().data();
+ ErrorOr<StringRef> buf = (*ci)->getBuffer();
+ if (!buf)
+ return;
+ const char *memberStart = buf->data();
if (_membersInstantiated.count(memberStart))
return;
@@ -119,20 +133,20 @@ public:
return std::error_code();
}
- const atom_collection<DefinedAtom> &defined() const override {
- return _definedAtoms;
+ const AtomVector<DefinedAtom> &defined() const override {
+ return _noDefinedAtoms;
}
- const atom_collection<UndefinedAtom> &undefined() const override {
- return _undefinedAtoms;
+ const AtomVector<UndefinedAtom> &undefined() const override {
+ return _noUndefinedAtoms;
}
- const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
- return _sharedLibraryAtoms;
+ const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ return _noSharedLibraryAtoms;
}
- const atom_collection<AbsoluteAtom> &absolute() const override {
- return _absoluteAtoms;
+ const AtomVector<AbsoluteAtom> &absolute() const override {
+ return _noAbsoluteAtoms;
}
/// Returns a set of all defined symbols in the archive.
@@ -157,10 +171,12 @@ protected:
}
private:
- std::error_code
- instantiateMember(Archive::child_iterator member,
- std::unique_ptr<File> &result) const {
- ErrorOr<llvm::MemoryBufferRef> mbOrErr = member->getMemoryBufferRef();
+ std::error_code instantiateMember(Archive::child_iterator cOrErr,
+ 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();
if (std::error_code ec = mbOrErr.getError())
return ec;
llvm::MemoryBufferRef mb = mbOrErr.get();
@@ -173,11 +189,11 @@ private:
std::unique_ptr<MemoryBuffer> memberMB(MemoryBuffer::getMemBuffer(
mb.getBuffer(), mb.getBufferIdentifier(), false));
- std::vector<std::unique_ptr<File>> files;
- if (std::error_code ec = _registry.loadFile(std::move(memberMB), files))
+ ErrorOr<std::unique_ptr<File>> fileOrErr =
+ _registry.loadFile(std::move(memberMB));
+ if (std::error_code ec = fileOrErr.getError())
return ec;
- assert(files.size() == 1);
- result = std::move(files[0]);
+ result = std::move(fileOrErr.get());
if (std::error_code ec = result->parse())
return ec;
result->setArchivePath(_archive->getFileName());
@@ -191,8 +207,11 @@ private:
// 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 member, StringRef symbol) const {
- ErrorOr<llvm::MemoryBufferRef> buf = member->getMemoryBufferRef();
+ 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(
@@ -205,19 +224,17 @@ private:
for (SymbolRef sym : obj->symbols()) {
// Skip until we find the symbol.
- StringRef name;
- if (sym.getName(name))
+ ErrorOr<StringRef> name = sym.getName();
+ if (!name)
return false;
- if (name != symbol)
+ 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;
- if (sym.getType(type))
- return false;
+ SymbolRef::Type type = sym.getType();
if (type == SymbolRef::ST_Data)
return true;
}
@@ -234,11 +251,12 @@ private:
if (std::error_code ec = memberOrErr.getError())
return ec;
Archive::child_iterator member = memberOrErr.get();
- DEBUG_WITH_TYPE(
- "FileArchive",
- llvm::dbgs() << llvm::format("0x%08llX ", member->getBuffer().data())
- << "'" << name << "'\n");
- _symbolMemberMap[name] = member;
+ DEBUG_WITH_TYPE("FileArchive",
+ llvm::dbgs()
+ << llvm::format("0x%08llX ",
+ (*member)->getBuffer()->data())
+ << "'" << name << "'\n");
+ _symbolMemberMap.insert(std::make_pair(name, member));
}
return std::error_code();
}
@@ -251,33 +269,27 @@ private:
std::unique_ptr<Archive> _archive;
MemberMap _symbolMemberMap;
InstantiatedSet _membersInstantiated;
- atom_collection_vector<DefinedAtom> _definedAtoms;
- atom_collection_vector<UndefinedAtom> _undefinedAtoms;
- atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
- atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
bool _logLoading;
std::vector<std::unique_ptr<MemoryBuffer>> _memberBuffers;
std::map<const char *, std::unique_ptr<Future<File *>>> _preloaded;
std::mutex _mutex;
+ FileVector _filesReturned;
};
class ArchiveReader : public Reader {
public:
ArchiveReader(bool logLoading) : _logLoading(logLoading) {}
- bool canParse(file_magic magic, StringRef,
- const MemoryBuffer &) const override {
- return (magic == llvm::sys::fs::file_magic::archive);
+ bool canParse(file_magic magic, MemoryBufferRef) const override {
+ return magic == llvm::sys::fs::file_magic::archive;
}
- std::error_code
- loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry &reg,
- std::vector<std::unique_ptr<File>> &result) const override {
+ ErrorOr<std::unique_ptr<File>> loadFile(std::unique_ptr<MemoryBuffer> mb,
+ const Registry &reg) const override {
StringRef path = mb->getBufferIdentifier();
- std::unique_ptr<FileArchive> file(
- new FileArchive(std::move(mb), reg, path, _logLoading));
- result.push_back(std::move(file));
- return std::error_code();
+ std::unique_ptr<File> ret =
+ llvm::make_unique<FileArchive>(std::move(mb), reg, path, _logLoading);
+ return std::move(ret);
}
private:
diff --git a/lib/ReaderWriter/LinkerScript.cpp b/lib/ReaderWriter/LinkerScript.cpp
index 56194cae5e72..67822dc48fe6 100644
--- a/lib/ReaderWriter/LinkerScript.cpp
+++ b/lib/ReaderWriter/LinkerScript.cpp
@@ -1,4 +1,4 @@
-//===- ReaderWriter/LinkerScript.cpp --------------------------------------===//
+//===- ReaderWriter/LinkerScript.cpp ----------------------------*- C++ -*-===//
//
// The LLVM Linker
//
@@ -14,6 +14,11 @@
#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 {
@@ -63,6 +68,9 @@ void Token::dump(raw_ostream &os) const {
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)
@@ -70,6 +78,7 @@ void Token::dump(raw_ostream &os) const {
CASE(kw_length)
CASE(kw_memory)
CASE(kw_origin)
+ CASE(kw_phdrs)
CASE(kw_provide)
CASE(kw_provide_hidden)
CASE(kw_only_if_ro)
@@ -100,7 +109,7 @@ static llvm::ErrorOr<uint64_t> parseDecimal(StringRef str) {
for (auto &c : str) {
res *= 10;
if (c < '0' || c > '9')
- return llvm::ErrorOr<uint64_t>(std::make_error_code(std::errc::io_error));
+ return llvm::ErrorOr<uint64_t>(make_error_code(llvm::errc::io_error));
res += c - '0';
}
return res;
@@ -111,7 +120,7 @@ static llvm::ErrorOr<uint64_t> parseOctal(StringRef str) {
for (auto &c : str) {
res <<= 3;
if (c < '0' || c > '7')
- return llvm::ErrorOr<uint64_t>(std::make_error_code(std::errc::io_error));
+ return llvm::ErrorOr<uint64_t>(make_error_code(llvm::errc::io_error));
res += c - '0';
}
return res;
@@ -122,7 +131,7 @@ static llvm::ErrorOr<uint64_t> parseBinary(StringRef str) {
for (auto &c : str) {
res <<= 1;
if (c != '0' && c != '1')
- return llvm::ErrorOr<uint64_t>(std::make_error_code(std::errc::io_error));
+ return llvm::ErrorOr<uint64_t>(make_error_code(llvm::errc::io_error));
res += c - '0';
}
return res;
@@ -139,7 +148,7 @@ static llvm::ErrorOr<uint64_t> parseHex(StringRef str) {
else if (c >= 'A' && c <= 'F')
res += c - 'A' + 10;
else
- return llvm::ErrorOr<uint64_t>(std::make_error_code(std::errc::io_error));
+ return llvm::ErrorOr<uint64_t>(make_error_code(llvm::errc::io_error));
}
return res;
}
@@ -469,6 +478,9 @@ void Lexer::lex(Token &tok) {
.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)
@@ -486,6 +498,7 @@ void Lexer::lex(Token &tok) {
.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)
@@ -544,14 +557,14 @@ void Lexer::skipWhitespace() {
// Constant functions
void Constant::dump(raw_ostream &os) const { os << _num; }
-ErrorOr<int64_t> Constant::evalExpr(SymbolTableTy &symbolTable) const {
+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(SymbolTableTy &symbolTable) const {
+ErrorOr<int64_t> Symbol::evalExpr(const SymbolTableTy &symbolTable) const {
auto it = symbolTable.find(_name);
if (it == symbolTable.end())
return LinkerScriptReaderError::unknown_symbol_in_expr;
@@ -569,7 +582,8 @@ void FunctionCall::dump(raw_ostream &os) const {
os << ")";
}
-ErrorOr<int64_t> FunctionCall::evalExpr(SymbolTableTy &symbolTable) const {
+ErrorOr<int64_t>
+FunctionCall::evalExpr(const SymbolTableTy &symbolTable) const {
return LinkerScriptReaderError::unrecognized_function_in_expr;
}
@@ -584,7 +598,7 @@ void Unary::dump(raw_ostream &os) const {
os << ")";
}
-ErrorOr<int64_t> Unary::evalExpr(SymbolTableTy &symbolTable) const {
+ErrorOr<int64_t> Unary::evalExpr(const SymbolTableTy &symbolTable) const {
auto child = _child->evalExpr(symbolTable);
if (child.getError())
return child.getError();
@@ -654,7 +668,7 @@ void BinOp::dump(raw_ostream &os) const {
os << ")";
}
-ErrorOr<int64_t> BinOp::evalExpr(SymbolTableTy &symbolTable) const {
+ErrorOr<int64_t> BinOp::evalExpr(const SymbolTableTy &symbolTable) const {
auto lhs = _lhs->evalExpr(symbolTable);
if (lhs.getError())
return lhs.getError();
@@ -695,7 +709,7 @@ void TernaryConditional::dump(raw_ostream &os) const {
}
ErrorOr<int64_t>
-TernaryConditional::evalExpr(SymbolTableTy &symbolTable) const {
+TernaryConditional::evalExpr(const SymbolTableTy &symbolTable) const {
auto conditional = _conditional->evalExpr(symbolTable);
if (conditional.getError())
return conditional.getError();
@@ -857,6 +871,12 @@ void InputSectionsCmd::dump(raw_ostream &os) const {
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)
@@ -909,6 +929,9 @@ void OutputSectionDescription::dump(raw_ostream &os) const {
}
os << " }";
+ for (auto && phdr : _phdrs)
+ os << " : " << phdr;
+
if (_fillStream.size() > 0) {
os << " =";
dumpByteStream(os, _fillStream);
@@ -918,6 +941,37 @@ void OutputSectionDescription::dump(raw_ostream &os) const {
}
}
+// 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";
@@ -965,7 +1019,6 @@ void Extern::dump(raw_ostream &os) const {
os << ")\n";
}
-
// Parser functions
std::error_code Parser::parse() {
// Get the first token.
@@ -1024,6 +1077,13 @@ std::error_code Parser::parse() {
_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)
@@ -1122,7 +1182,7 @@ const Expression *Parser::parseExprOperand() {
case Token::identifier: {
if (peek()._kind== Token::l_paren)
return parseFunctionCall();
- Symbol *sym = new (_alloc) Symbol(*this, _tok._range);
+ auto *sym = new (_alloc) Symbol(*this, _tok._range);
consumeToken();
return sym;
}
@@ -1140,7 +1200,7 @@ const Expression *Parser::parseExprOperand() {
error(_tok, "Unrecognized number constant");
return nullptr;
}
- Constant *c = new (_alloc) Constant(*this, *val);
+ auto *c = new (_alloc) Constant(*this, *val);
consumeToken();
return c;
}
@@ -1588,7 +1648,7 @@ llvm::ErrorOr<InputSectionsCmd::VectorTy> Parser::parseExcludeFile() {
if (!expectAndConsume(Token::l_paren, "expected ("))
return llvm::ErrorOr<InputSectionsCmd::VectorTy>(
- std::make_error_code(std::errc::io_error));
+ make_error_code(llvm::errc::io_error));
while (_tok._kind == Token::identifier) {
res.push_back(new (_alloc) InputSectionName(*this, _tok._range, true));
@@ -1597,7 +1657,7 @@ llvm::ErrorOr<InputSectionsCmd::VectorTy> Parser::parseExcludeFile() {
if (!expectAndConsume(Token::r_paren, "expected )"))
return llvm::ErrorOr<InputSectionsCmd::VectorTy>(
- std::make_error_code(std::errc::io_error));
+ make_error_code(llvm::errc::io_error));
return llvm::ErrorOr<InputSectionsCmd::VectorTy>(std::move(res));
}
@@ -1793,6 +1853,46 @@ const InputSectionsCmd *Parser::parseInputSectionsCmd() {
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!");
@@ -1892,6 +1992,12 @@ const OutputSectionDescription *Parser::parseOutputSectionDescription() {
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:
@@ -1921,6 +2027,17 @@ const OutputSectionDescription *Parser::parseOutputSectionDescription() {
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")) {
@@ -1945,7 +2062,7 @@ const OutputSectionDescription *Parser::parseOutputSectionDescription() {
return new (_alloc) OutputSectionDescription(
*this, sectionName, address, align, subAlign, at, fillExpr, fillStream,
- alignWithInput, discard, constraint, outputSectionCommands);
+ alignWithInput, discard, constraint, outputSectionCommands, phdrs);
}
const Overlay *Parser::parseOverlay() {
@@ -1954,6 +2071,141 @@ const Overlay *Parser::parseOverlay() {
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();
@@ -2101,8 +2353,7 @@ Memory *Parser::parseMemory() {
if (!length)
return nullptr;
- MemoryBlock *block =
- new (_alloc) MemoryBlock(name, attrs, origin, length);
+ auto *block = new (_alloc) MemoryBlock(name, attrs, origin, length);
blocks.push_back(block);
} else {
unrecognizedToken = true;
@@ -2142,14 +2393,22 @@ Extern *Parser::parseExtern() {
}
// Sema member functions
-Sema::Sema()
- : _scripts(), _layoutCommands(), _memberToLayoutOrder(),
- _memberNameWildcards(), _cacheSectionOrder(), _cacheExpressionOrder(),
- _deliveredExprs(), _symbolTable() {}
+Sema::Sema() : _programPHDR(nullptr) {}
+
+std::error_code Sema::perform() {
+ llvm::StringMap<const PHDR *> phdrs;
-void Sema::perform() {
- for (auto &parser : _scripts)
- perform(parser->get());
+ 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 {
@@ -2254,6 +2513,15 @@ uint64_t Sema::getLinkerScriptExprValue(StringRef name) const {
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";
@@ -2287,7 +2555,7 @@ static bool wildcardMatch(StringRef pattern, StringRef name) {
switch (*j) {
case '*':
while (!wildcardMatch(pattern.drop_front(j - pattern.begin() + 1),
- name.drop_front(i - name.begin() + 1))) {
+ name.drop_front(i - name.begin()))) {
if (i == name.end())
return false;
++i;
@@ -2295,6 +2563,7 @@ static bool wildcardMatch(StringRef pattern, StringRef name) {
break;
case '?':
// Matches any character
+ ++i;
break;
case '[': {
// Matches a range of characters specified between brackets
@@ -2307,20 +2576,22 @@ static bool wildcardMatch(StringRef pattern, StringRef name) {
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;
}
- ++i;
}
// If our pattern has't consumed the entire string, it is not a match
@@ -2376,11 +2647,10 @@ int Sema::getLayoutOrder(const SectionKey &key, bool coarse) const {
// If we still couldn't find a rule for this input section, try to match
// wildcards
- for (auto I = _memberNameWildcards.begin(), E = _memberNameWildcards.end();
- I != E; ++I) {
- if (!wildcardMatch(I->first, key.memberPath))
+ for (const auto &I : _memberNameWildcards) {
+ if (!wildcardMatch(I.first, key.memberPath))
continue;
- int order = I->second;
+ int order = I.second;
int exprOrder = -1;
if ((exprOrder = matchSectionName(order, key)) >= 0) {
@@ -2490,6 +2760,74 @@ bool Sema::localCompare(int order, const SectionKey &lhs,
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 == '\\')
@@ -2553,12 +2891,5 @@ void Sema::linearizeAST(const Sections *sections) {
}
}
-void Sema::perform(const LinkerScript *ls) {
- for (const Command *c : ls->_commands) {
- if (const Sections *sec = dyn_cast<Sections>(c))
- linearizeAST(sec);
- }
-}
-
-} // End namespace script
+} // end namespace script
} // end namespace lld
diff --git a/lib/ReaderWriter/MachO/ArchHandler.h b/lib/ReaderWriter/MachO/ArchHandler.h
index 7f0961ebc807..120f5dfd4cd2 100644
--- a/lib/ReaderWriter/MachO/ArchHandler.h
+++ b/lib/ReaderWriter/MachO/ArchHandler.h
@@ -49,6 +49,12 @@ public:
return false;
}
+ /// Used by TLVPass to locate TLV References.
+ virtual bool isTLVAccess(const Reference &) const { return false; }
+
+ /// Used by the TLVPass to update TLV References.
+ virtual void updateReferenceToTLV(const Reference *) {}
+
/// Used by ShimPass to insert shims in branches that switch mode.
virtual bool isNonCallBranch(const Reference &) = 0;
diff --git a/lib/ReaderWriter/MachO/ArchHandler_arm.cpp b/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
index 43f88a1d30d8..4e15a2d434c6 100644
--- a/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
+++ b/lib/ReaderWriter/MachO/ArchHandler_arm.cpp
@@ -28,8 +28,8 @@ using llvm::support::little32_t;
class ArchHandler_arm : public ArchHandler {
public:
- ArchHandler_arm();
- virtual ~ArchHandler_arm();
+ ArchHandler_arm() = default;
+ ~ArchHandler_arm() override = default;
const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
@@ -202,10 +202,6 @@ private:
// ArchHandler_arm
//===----------------------------------------------------------------------===//
-ArchHandler_arm::ArchHandler_arm() { }
-
-ArchHandler_arm::~ArchHandler_arm() { }
-
const Registry::KindStrings ArchHandler_arm::_sKindStrings[] = {
LLD_KIND_STRING_ENTRY(invalid),
LLD_KIND_STRING_ENTRY(modeThumbCode),
@@ -463,7 +459,6 @@ bool ArchHandler_arm::isArmMovt(uint32_t instruction) {
return (instruction & 0x0FF00000) == 0x03400000;
}
-
uint16_t ArchHandler_arm::getWordFromThumbMov(uint32_t instruction) {
assert(isThumbMovw(instruction) || isThumbMovt(instruction));
uint32_t i = ((instruction & 0x00000400) >> 10);
@@ -480,7 +475,6 @@ uint16_t ArchHandler_arm::getWordFromArmMov(uint32_t instruction) {
return (imm4 << 12) | imm12;
}
-
uint32_t ArchHandler_arm::setWordFromThumbMov(uint32_t instr, uint16_t word) {
assert(isThumbMovw(instr) || isThumbMovt(instr));
uint32_t imm4 = (word & 0xF000) >> 12;
@@ -497,7 +491,6 @@ uint32_t ArchHandler_arm::setWordFromArmMov(uint32_t instr, uint16_t word) {
return (instr & 0xFFF0F000) | (imm4 << 16) | imm12;
}
-
uint32_t ArchHandler_arm::clearThumbBit(uint32_t value, const Atom *target) {
// The assembler often adds one to the address of a thumb function.
// We need to undo that so it does not look like an addend.
@@ -619,7 +612,7 @@ std::error_code ArchHandler_arm::getReferenceInfo(
*addend += (clearThumbBit(instruction, *target) - reloc.value);
return std::error_code();
default:
- return make_dynamic_error_code(Twine("unsupported arm relocation type"));
+ return make_dynamic_error_code("unsupported arm relocation type");
}
return std::error_code();
}
@@ -777,7 +770,7 @@ ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
pointerDiff = true;
break;
default:
- return make_dynamic_error_code(Twine("unsupported arm relocation pair"));
+ return make_dynamic_error_code("unsupported arm relocation pair");
}
const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
std::error_code ec;
@@ -800,8 +793,8 @@ ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
if (ec)
return ec;
if (scatterable && (fromTarget != inAtom))
- return make_dynamic_error_code(Twine("SECTDIFF relocation where "
- "subtrahend label is not in atom"));
+ return make_dynamic_error_code(
+ "SECTDIFF relocation where subtrahend label is not in atom");
*kind = delta32;
value = clearThumbBit(instruction, *target);
*addend = (int32_t)(value - (toAddress - fixupAddress));
@@ -815,29 +808,28 @@ ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
if (ec)
return ec;
if (fromTarget != inAtom)
- return make_dynamic_error_code(
- Twine("ARM_RELOC_HALF_SECTDIFF relocation "
- "where subtrahend label is not in atom"));
+ return make_dynamic_error_code("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(Twine("expected movt instruction"));
+ return make_dynamic_error_code("expected movt instruction");
}
else {
if (!isThumbMovw(instruction))
- return make_dynamic_error_code(Twine("expected movw instruction"));
+ return make_dynamic_error_code("expected movw instruction");
}
instruction16 = getWordFromThumbMov(instruction);
}
else {
if (top) {
if (!isArmMovt(instruction))
- return make_dynamic_error_code(Twine("expected movt instruction"));
+ return make_dynamic_error_code("expected movt instruction");
}
else {
if (!isArmMovw(instruction))
- return make_dynamic_error_code(Twine("expected movw instruction"));
+ return make_dynamic_error_code("expected movw instruction");
}
instruction16 = getWordFromArmMov(instruction);
}
@@ -854,22 +846,22 @@ ArchHandler_arm::getPairReferenceInfo(const normalized::Relocation &reloc1,
if (thumbReloc) {
if (top) {
if (!isThumbMovt(instruction))
- return make_dynamic_error_code(Twine("expected movt instruction"));
+ return make_dynamic_error_code("expected movt instruction");
}
else {
if (!isThumbMovw(instruction))
- return make_dynamic_error_code(Twine("expected movw instruction"));
+ return make_dynamic_error_code("expected movw instruction");
}
instruction16 = getWordFromThumbMov(instruction);
}
else {
if (top) {
if (!isArmMovt(instruction))
- return make_dynamic_error_code(Twine("expected movt instruction"));
+ return make_dynamic_error_code("expected movt instruction");
}
else {
if (!isArmMovw(instruction))
- return make_dynamic_error_code(Twine("expected movw instruction"));
+ return make_dynamic_error_code("expected movw instruction");
}
instruction16 = getWordFromArmMov(instruction);
}
@@ -1041,7 +1033,6 @@ void ArchHandler_arm::generateAtomContent(const DefinedAtom &atom,
}
}
-
bool ArchHandler_arm::useExternalRelocationTo(const Atom &target) {
// Undefined symbols are referenced via external relocations.
if (isa<UndefinedAtom>(&target))
@@ -1410,7 +1401,6 @@ bool ArchHandler_arm::isThumbFunction(const DefinedAtom &atom) {
return false;
}
-
class Thumb2ToArmShimAtom : public SimpleDefinedAtom {
public:
Thumb2ToArmShimAtom(MachOFile &file, StringRef targetName,
@@ -1433,9 +1423,7 @@ public:
return DefinedAtom::typeCode;
}
- Alignment alignment() const override {
- return Alignment(2);
- }
+ Alignment alignment() const override { return 4; }
uint64_t size() const override {
return 12;
@@ -1458,7 +1446,6 @@ private:
StringRef _name;
};
-
class ArmToThumbShimAtom : public SimpleDefinedAtom {
public:
ArmToThumbShimAtom(MachOFile &file, StringRef targetName,
@@ -1479,9 +1466,7 @@ public:
return DefinedAtom::typeCode;
}
- Alignment alignment() const override {
- return Alignment(2);
- }
+ Alignment alignment() const override { return 4; }
uint64_t size() const override {
return 16;
@@ -1515,7 +1500,6 @@ const DefinedAtom *ArchHandler_arm::createShim(MachOFile &file,
return new (file.allocator()) ArmToThumbShimAtom(file, targetName, target);
}
-
std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_arm() {
return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_arm());
}
diff --git a/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp b/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
index fd9984b89ce6..5e5a426b310b 100644
--- a/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
+++ b/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp
@@ -31,8 +31,8 @@ using llvm::support::little64_t;
class ArchHandler_arm64 : public ArchHandler {
public:
- ArchHandler_arm64();
- virtual ~ArchHandler_arm64();
+ ArchHandler_arm64() = default;
+ ~ArchHandler_arm64() override = default;
const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
@@ -50,6 +50,9 @@ public:
case gotOffset12:
canBypassGOT = true;
return true;
+ case delta32ToGOT:
+ canBypassGOT = false;
+ return true;
case imageOffsetGot:
canBypassGOT = false;
return true;
@@ -74,6 +77,9 @@ public:
const_cast<Reference *>(ref)->setKindValue(targetNowGOT ?
offset12scale8 : addOffset12);
break;
+ case delta32ToGOT:
+ const_cast<Reference *>(ref)->setKindValue(delta32);
+ break;
case imageOffsetGot:
const_cast<Reference *>(ref)->setKindValue(imageOffset);
break;
@@ -213,10 +219,6 @@ private:
static uint32_t setImm12(uint32_t instr, uint32_t offset);
};
-ArchHandler_arm64::ArchHandler_arm64() {}
-
-ArchHandler_arm64::~ArchHandler_arm64() {}
-
const Registry::KindStrings ArchHandler_arm64::_sKindStrings[] = {
LLD_KIND_STRING_ENTRY(invalid),
LLD_KIND_STRING_ENTRY(branch26),
@@ -437,7 +439,7 @@ std::error_code ArchHandler_arm64::getReferenceInfo(
*addend = 0;
return std::error_code();
default:
- return make_dynamic_error_code(Twine("unsupported arm64 relocation type"));
+ return make_dynamic_error_code("unsupported arm64 relocation type");
}
}
@@ -480,6 +482,9 @@ std::error_code ArchHandler_arm64::getPairReferenceInfo(
*kind = delta64;
if (auto ec = atomFromSymbolIndex(reloc2.symbol, target))
return ec;
+ // 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");
*addend = (int64_t)*(const little64_t *)fixupContent + offsetInAtom;
return std::error_code();
case ((ARM64_RELOC_SUBTRACTOR | rExtern | rLength4) << 16 |
@@ -491,7 +496,7 @@ std::error_code ArchHandler_arm64::getPairReferenceInfo(
*addend = (int32_t)*(const little32_t *)fixupContent + offsetInAtom;
return std::error_code();
default:
- return make_dynamic_error_code(Twine("unsupported arm64 relocation pair"));
+ return make_dynamic_error_code("unsupported arm64 relocation pair");
}
}
@@ -669,7 +674,7 @@ void ArchHandler_arm64::applyFixupRelocatable(const Reference &ref,
*loc32 = ref.addend() + inAtomAddress - fixupAddress;
return;
case negDelta32:
- *loc32 = fixupAddress - inAtomAddress + ref.addend();
+ *loc32 = fixupAddress - targetAddress + ref.addend();
return;
case pointer64ToGOT:
*loc64 = 0;
diff --git a/lib/ReaderWriter/MachO/ArchHandler_x86.cpp b/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
index 19c8780e707a..7aac2584d078 100644
--- a/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
+++ b/lib/ReaderWriter/MachO/ArchHandler_x86.cpp
@@ -30,8 +30,8 @@ using llvm::support::little32_t;
class ArchHandler_x86 : public ArchHandler {
public:
- ArchHandler_x86();
- virtual ~ArchHandler_x86();
+ ArchHandler_x86() = default;
+ ~ArchHandler_x86() override = default;
const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
@@ -49,9 +49,11 @@ public:
bool needsCompactUnwind() override {
return false;
}
+
Reference::KindValue imageOffsetKind() override {
return invalid;
}
+
Reference::KindValue imageOffsetKindIndirect() override {
return invalid;
}
@@ -68,7 +70,6 @@ public:
return invalid;
}
-
uint32_t dwarfCompactUnwindType() override {
return 0x04000000U;
}
@@ -169,10 +170,6 @@ private:
// ArchHandler_x86
//===----------------------------------------------------------------------===//
-ArchHandler_x86::ArchHandler_x86() {}
-
-ArchHandler_x86::~ArchHandler_x86() { }
-
const Registry::KindStrings ArchHandler_x86::_sKindStrings[] = {
LLD_KIND_STRING_ENTRY(invalid),
LLD_KIND_STRING_ENTRY(modeCode),
@@ -334,7 +331,7 @@ ArchHandler_x86::getReferenceInfo(const Relocation &reloc,
*addend = *(const ulittle32_t *)fixupContent - reloc.value;
break;
default:
- return make_dynamic_error_code(Twine("unsupported i386 relocation type"));
+ return make_dynamic_error_code("unsupported i386 relocation type");
}
return std::error_code();
}
@@ -376,8 +373,8 @@ ArchHandler_x86::getPairReferenceInfo(const normalized::Relocation &reloc1,
return ec;
if (fromTarget != inAtom) {
if (*target != inAtom)
- return make_dynamic_error_code(Twine("SECTDIFF relocation where "
- "neither target is in atom"));
+ return make_dynamic_error_code(
+ "SECTDIFF relocation where neither target is in atom");
*kind = negDelta32;
*addend = toAddress - value - fromAddress;
*target = fromTarget;
@@ -400,7 +397,7 @@ ArchHandler_x86::getPairReferenceInfo(const normalized::Relocation &reloc1,
return std::error_code();
break;
default:
- return make_dynamic_error_code(Twine("unsupported i386 relocation type"));
+ return make_dynamic_error_code("unsupported i386 relocation type");
}
}
@@ -545,7 +542,6 @@ bool ArchHandler_x86::useExternalRelocationTo(const Atom &target) {
return false;
}
-
void ArchHandler_x86::appendSectionRelocations(
const DefinedAtom &atom,
uint64_t atomSectionOffset,
@@ -633,7 +629,6 @@ void ArchHandler_x86::appendSectionRelocations(
}
}
-
std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_x86() {
return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_x86());
}
diff --git a/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp b/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
index 81fe1af42d7e..c57a00359e33 100644
--- a/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
+++ b/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp
@@ -30,8 +30,8 @@ using llvm::support::little64_t;
class ArchHandler_x86_64 : public ArchHandler {
public:
- ArchHandler_x86_64();
- virtual ~ArchHandler_x86_64();
+ ArchHandler_x86_64() = default;
+ ~ArchHandler_x86_64() override = default;
const Registry::KindStrings *kindStrings() override { return _sKindStrings; }
@@ -59,6 +59,19 @@ public:
}
}
+ bool isTLVAccess(const Reference &ref) const override {
+ assert(ref.kindNamespace() == Reference::KindNamespace::mach_o);
+ assert(ref.kindArch() == Reference::KindArch::x86_64);
+ return ref.kindValue() == ripRel32Tlv;
+ }
+
+ void updateReferenceToTLV(const Reference *ref) override {
+ assert(ref->kindNamespace() == Reference::KindNamespace::mach_o);
+ assert(ref->kindArch() == Reference::KindArch::x86_64);
+ assert(ref->kindValue() == ripRel32Tlv);
+ const_cast<Reference*>(ref)->setKindValue(ripRel32);
+ }
+
/// Used by GOTPass to update GOT References
void updateReferenceToGOT(const Reference *ref, bool targetNowGOT) override {
assert(ref->kindNamespace() == Reference::KindNamespace::mach_o);
@@ -82,9 +95,11 @@ public:
bool needsCompactUnwind() override {
return true;
}
+
Reference::KindValue imageOffsetKind() override {
return imageOffset;
}
+
Reference::KindValue imageOffsetKindIndirect() override {
return imageOffsetGot;
}
@@ -168,8 +183,12 @@ private:
ripRel32Minus2, /// ex: movw $0x1234, _foo(%rip)
ripRel32Minus4, /// ex: movl $0x12345678, _foo(%rip)
ripRel32Anon, /// ex: movq L1(%rip), %rax
+ ripRel32Minus1Anon, /// ex: movb $0x12, L1(%rip)
+ ripRel32Minus2Anon, /// ex: movw $0x1234, L1(%rip)
+ ripRel32Minus4Anon, /// ex: movw $0x12345678, L1(%rip)
ripRel32GotLoad, /// ex: movq _foo@GOTPCREL(%rip), %rax
ripRel32Got, /// ex: pushq _foo@GOTPCREL(%rip)
+ ripRel32Tlv, /// ex: movq _foo@TLVP(%rip), %rdi
pointer64, /// ex: .quad _foo
pointer64Anon, /// ex: .quad L1
delta64, /// ex: .quad _foo - .
@@ -192,6 +211,8 @@ private:
/// relocatable object (yay for implicit contracts!).
unwindInfoToEhFrame, /// Fix low 24 bits of compact unwind encoding to
/// refer to __eh_frame entry.
+ tlvInitSectionOffset /// Location contains offset tlv init-value atom
+ /// within the __thread_data section.
};
Reference::KindValue kindFromReloc(const normalized::Relocation &reloc);
@@ -209,18 +230,18 @@ private:
uint64_t inAtomAddress);
};
-
-ArchHandler_x86_64::ArchHandler_x86_64() { }
-
-ArchHandler_x86_64::~ArchHandler_x86_64() { }
-
const Registry::KindStrings ArchHandler_x86_64::_sKindStrings[] = {
LLD_KIND_STRING_ENTRY(invalid), LLD_KIND_STRING_ENTRY(branch32),
LLD_KIND_STRING_ENTRY(ripRel32), LLD_KIND_STRING_ENTRY(ripRel32Minus1),
LLD_KIND_STRING_ENTRY(ripRel32Minus2), LLD_KIND_STRING_ENTRY(ripRel32Minus4),
- LLD_KIND_STRING_ENTRY(ripRel32Anon), LLD_KIND_STRING_ENTRY(ripRel32GotLoad),
+ LLD_KIND_STRING_ENTRY(ripRel32Anon),
+ LLD_KIND_STRING_ENTRY(ripRel32Minus1Anon),
+ LLD_KIND_STRING_ENTRY(ripRel32Minus2Anon),
+ LLD_KIND_STRING_ENTRY(ripRel32Minus4Anon),
+ LLD_KIND_STRING_ENTRY(ripRel32GotLoad),
LLD_KIND_STRING_ENTRY(ripRel32GotLoadNowLea),
- LLD_KIND_STRING_ENTRY(ripRel32Got), LLD_KIND_STRING_ENTRY(lazyPointer),
+ LLD_KIND_STRING_ENTRY(ripRel32Got), LLD_KIND_STRING_ENTRY(ripRel32Tlv),
+ LLD_KIND_STRING_ENTRY(lazyPointer),
LLD_KIND_STRING_ENTRY(lazyImmediateLocation),
LLD_KIND_STRING_ENTRY(pointer64), LLD_KIND_STRING_ENTRY(pointer64Anon),
LLD_KIND_STRING_ENTRY(delta32), LLD_KIND_STRING_ENTRY(delta64),
@@ -229,6 +250,7 @@ const Registry::KindStrings ArchHandler_x86_64::_sKindStrings[] = {
LLD_KIND_STRING_ENTRY(imageOffset), LLD_KIND_STRING_ENTRY(imageOffsetGot),
LLD_KIND_STRING_ENTRY(unwindFDEToFunction),
LLD_KIND_STRING_ENTRY(unwindInfoToEhFrame),
+ LLD_KIND_STRING_ENTRY(tlvInitSectionOffset),
LLD_KIND_STRING_END
};
@@ -301,14 +323,22 @@ ArchHandler_x86_64::kindFromReloc(const Relocation &reloc) {
return ripRel32Anon;
case X86_64_RELOC_SIGNED_1 | rPcRel | rExtern | rLength4:
return ripRel32Minus1;
+ case X86_64_RELOC_SIGNED_1 | rPcRel | rLength4:
+ return ripRel32Minus1Anon;
case X86_64_RELOC_SIGNED_2 | rPcRel | rExtern | rLength4:
return ripRel32Minus2;
+ case X86_64_RELOC_SIGNED_2 | rPcRel | rLength4:
+ return ripRel32Minus2Anon;
case X86_64_RELOC_SIGNED_4 | rPcRel | rExtern | rLength4:
return ripRel32Minus4;
+ case X86_64_RELOC_SIGNED_4 | rPcRel | rLength4:
+ return ripRel32Minus4Anon;
case X86_64_RELOC_GOT_LOAD | rPcRel | rExtern | rLength4:
return ripRel32GotLoad;
case X86_64_RELOC_GOT | rPcRel | rExtern | rLength4:
return ripRel32Got;
+ case X86_64_RELOC_TLV | rPcRel | rExtern | rLength4:
+ return ripRel32Tlv;
case X86_64_RELOC_UNSIGNED | rExtern | rLength8:
return pointer64;
case X86_64_RELOC_UNSIGNED | rLength8:
@@ -331,7 +361,7 @@ ArchHandler_x86_64::getReferenceInfo(const Relocation &reloc,
typedef std::error_code E;
*kind = kindFromReloc(reloc);
if (*kind == invalid)
- return make_dynamic_error_code(Twine("unknown type"));
+ return make_dynamic_error_code("unknown type");
const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
uint64_t targetAddress;
switch (*kind) {
@@ -359,16 +389,34 @@ ArchHandler_x86_64::getReferenceInfo(const Relocation &reloc,
case ripRel32Anon:
targetAddress = fixupAddress + 4 + *(const little32_t *)fixupContent;
return atomFromAddress(reloc.symbol, targetAddress, target, addend);
+ case ripRel32Minus1Anon:
+ targetAddress = fixupAddress + 5 + *(const little32_t *)fixupContent;
+ return atomFromAddress(reloc.symbol, targetAddress, target, addend);
+ case ripRel32Minus2Anon:
+ targetAddress = fixupAddress + 6 + *(const little32_t *)fixupContent;
+ return atomFromAddress(reloc.symbol, targetAddress, target, addend);
+ case ripRel32Minus4Anon:
+ targetAddress = fixupAddress + 8 + *(const little32_t *)fixupContent;
+ return atomFromAddress(reloc.symbol, targetAddress, target, addend);
case ripRel32GotLoad:
case ripRel32Got:
+ case ripRel32Tlv:
if (E ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
*addend = *(const little32_t *)fixupContent;
return std::error_code();
+ case tlvInitSectionOffset:
case pointer64:
if (E ec = atomFromSymbolIndex(reloc.symbol, target))
return ec;
- *addend = *(const little64_t *)fixupContent;
+ // 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.
+ if (inAtom->contentType() == DefinedAtom::typeThunkTLV &&
+ offsetInAtom == 16) {
+ *kind = tlvInitSectionOffset;
+ assert(*addend == 0 && "TLV-init has non-zero addend?");
+ } else
+ *addend = *(const little64_t *)fixupContent;
return std::error_code();
case pointer64Anon:
targetAddress = *(const little64_t *)fixupContent;
@@ -413,7 +461,7 @@ ArchHandler_x86_64::getPairReferenceInfo(const normalized::Relocation &reloc1,
Reference::Addend *addend) {
*kind = kindFromRelocPair(reloc1, reloc2);
if (*kind == invalid)
- return make_dynamic_error_code(Twine("unknown pair"));
+ return make_dynamic_error_code("unknown pair");
const uint8_t *fixupContent = &inAtom->rawContent()[offsetInAtom];
typedef std::error_code E;
uint64_t targetAddress;
@@ -421,7 +469,7 @@ ArchHandler_x86_64::getPairReferenceInfo(const normalized::Relocation &reloc1,
if (E ec = atomFromSymbolIndex(reloc1.symbol, &fromTarget))
return ec;
if (fromTarget != inAtom)
- return make_dynamic_error_code(Twine("pointer diff not in base atom"));
+ return make_dynamic_error_code("pointer diff not in base atom");
switch (*kind) {
case delta64:
if (E ec = atomFromSymbolIndex(reloc2.symbol, target))
@@ -486,19 +534,26 @@ void ArchHandler_x86_64::applyFixupFinal(
case ripRel32Anon:
case ripRel32Got:
case ripRel32GotLoad:
+ case ripRel32Tlv:
*loc32 = targetAddress - (fixupAddress + 4) + ref.addend();
return;
case pointer64:
case pointer64Anon:
*loc64 = targetAddress + ref.addend();
return;
+ case tlvInitSectionOffset:
+ *loc64 = targetAddress - findSectionAddress(*ref.target()) + ref.addend();
+ return;
case ripRel32Minus1:
+ case ripRel32Minus1Anon:
*loc32 = targetAddress - (fixupAddress + 5) + ref.addend();
return;
case ripRel32Minus2:
+ case ripRel32Minus2Anon:
*loc32 = targetAddress - (fixupAddress + 6) + ref.addend();
return;
case ripRel32Minus4:
+ case ripRel32Minus4Anon:
*loc32 = targetAddress - (fixupAddress + 8) + ref.addend();
return;
case delta32:
@@ -542,7 +597,6 @@ void ArchHandler_x86_64::applyFixupFinal(
llvm_unreachable("invalid x86_64 Reference Kind");
}
-
void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref,
uint8_t *loc,
uint64_t fixupAddress,
@@ -558,11 +612,13 @@ void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref,
case ripRel32:
case ripRel32Got:
case ripRel32GotLoad:
+ case ripRel32Tlv:
*loc32 = ref.addend();
return;
case ripRel32Anon:
*loc32 = (targetAddress - (fixupAddress + 4)) + ref.addend();
return;
+ case tlvInitSectionOffset:
case pointer64:
*loc64 = ref.addend();
return;
@@ -572,12 +628,21 @@ void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref,
case ripRel32Minus1:
*loc32 = ref.addend() - 1;
return;
+ case ripRel32Minus1Anon:
+ *loc32 = (targetAddress - (fixupAddress + 5)) + ref.addend();
+ return;
case ripRel32Minus2:
*loc32 = ref.addend() - 2;
return;
+ case ripRel32Minus2Anon:
+ *loc32 = (targetAddress - (fixupAddress + 6)) + ref.addend();
+ return;
case ripRel32Minus4:
*loc32 = ref.addend() - 4;
return;
+ case ripRel32Minus4Anon:
+ *loc32 = (targetAddress - (fixupAddress + 8)) + ref.addend();
+ return;
case delta32:
*loc32 = ref.addend() + inAtomAddress - fixupAddress;
return;
@@ -638,7 +703,7 @@ void ArchHandler_x86_64::appendSectionRelocations(
return;
case ripRel32Anon:
appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
- X86_64_RELOC_SIGNED | rPcRel | rLength4 );
+ X86_64_RELOC_SIGNED | rPcRel | rLength4 );
return;
case ripRel32Got:
appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
@@ -648,6 +713,11 @@ void ArchHandler_x86_64::appendSectionRelocations(
appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
X86_64_RELOC_GOT_LOAD | rPcRel | rExtern | rLength4 );
return;
+ case ripRel32Tlv:
+ appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
+ X86_64_RELOC_TLV | rPcRel | rExtern | rLength4 );
+ return;
+ case tlvInitSectionOffset:
case pointer64:
appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
X86_64_RELOC_UNSIGNED | rExtern | rLength8);
@@ -660,14 +730,26 @@ void ArchHandler_x86_64::appendSectionRelocations(
appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
X86_64_RELOC_SIGNED_1 | rPcRel | rExtern | rLength4 );
return;
+ case ripRel32Minus1Anon:
+ appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
+ X86_64_RELOC_SIGNED_1 | rPcRel | rLength4 );
+ return;
case ripRel32Minus2:
appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
X86_64_RELOC_SIGNED_2 | rPcRel | rExtern | rLength4 );
return;
+ case ripRel32Minus2Anon:
+ appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
+ X86_64_RELOC_SIGNED_2 | rPcRel | rLength4 );
+ return;
case ripRel32Minus4:
appendReloc(relocs, sectionOffset, symbolIndexForAtom(*ref.target()), 0,
X86_64_RELOC_SIGNED_4 | rPcRel | rExtern | rLength4 );
return;
+ case ripRel32Minus4Anon:
+ appendReloc(relocs, sectionOffset, sectionIndexForAtom(*ref.target()), 0,
+ X86_64_RELOC_SIGNED_4 | rPcRel | rLength4 );
+ return;
case delta32:
appendReloc(relocs, sectionOffset, symbolIndexForAtom(atom), 0,
X86_64_RELOC_SUBTRACTOR | rExtern | rLength4 );
@@ -714,7 +796,6 @@ void ArchHandler_x86_64::appendSectionRelocations(
llvm_unreachable("unknown x86_64 Reference Kind");
}
-
std::unique_ptr<mach_o::ArchHandler> ArchHandler::create_x86_64() {
return std::unique_ptr<mach_o::ArchHandler>(new ArchHandler_x86_64());
}
diff --git a/lib/ReaderWriter/MachO/Atoms.h b/lib/ReaderWriter/MachO/Atoms.h
index 8d60c1a163a6..9f2e5acad99a 100644
--- a/lib/ReaderWriter/MachO/Atoms.h
+++ b/lib/ReaderWriter/MachO/Atoms.h
@@ -25,11 +25,11 @@ public:
// Constructor for zero-fill content
MachODefinedAtom(const File &f, const StringRef name, Scope scope,
- uint64_t size, bool noDeadStrip, Alignment align)
+ ContentType type, uint64_t size, bool noDeadStrip,
+ Alignment align)
: SimpleDefinedAtom(f), _name(name),
_content(ArrayRef<uint8_t>(nullptr, size)), _align(align),
- _contentType(DefinedAtom::typeZeroFill),
- _scope(scope), _merge(mergeNo), _thumb(false),
+ _contentType(type), _scope(scope), _merge(mergeNo), _thumb(false),
_noDeadStrip(noDeadStrip) {}
uint64_t size() const override { return _content.size(); }
@@ -103,7 +103,6 @@ private:
StringRef _sectionName;
};
-
class MachOTentativeDefAtom : public SimpleDefinedAtom {
public:
MachOTentativeDefAtom(const File &f, const StringRef name, Scope scope,
@@ -126,7 +125,7 @@ public:
ArrayRef<uint8_t> rawContent() const override { return ArrayRef<uint8_t>(); }
private:
- const StringRef _name;
+ const std::string _name;
const Scope _scope;
const uint64_t _size;
const DefinedAtom::Alignment _align;
@@ -138,32 +137,26 @@ public:
StringRef dylibInstallName, bool weakDef)
: SharedLibraryAtom(), _file(file), _name(name),
_dylibInstallName(dylibInstallName) {}
- virtual ~MachOSharedLibraryAtom() {}
+ ~MachOSharedLibraryAtom() override = default;
- virtual StringRef loadName() const override {
- return _dylibInstallName;
- }
+ StringRef loadName() const override { return _dylibInstallName; }
- virtual bool canBeNullAtRuntime() const override {
+ bool canBeNullAtRuntime() const override {
// FIXME: this may actually be changeable. For now, all symbols are strongly
// defined though.
return false;
}
- virtual const File& file() const override {
- return _file;
- }
+ const File &file() const override { return _file; }
- virtual StringRef name() const override {
- return _name;
- }
+ StringRef name() const override { return _name; }
- virtual Type type() const override {
+ Type type() const override {
// Unused in MachO (I think).
return Type::Unknown;
}
- virtual uint64_t size() const override {
+ uint64_t size() const override {
// Unused in MachO (I think)
return 0;
}
@@ -174,8 +167,7 @@ private:
StringRef _dylibInstallName;
};
+} // namespace mach_o
+} // namespace lld
-} // mach_o
-} // lld
-
-#endif
+#endif // LLD_READER_WRITER_MACHO_ATOMS_H
diff --git a/lib/ReaderWriter/MachO/CMakeLists.txt b/lib/ReaderWriter/MachO/CMakeLists.txt
index e396537c63c8..7ce782af6f99 100644
--- a/lib/ReaderWriter/MachO/CMakeLists.txt
+++ b/lib/ReaderWriter/MachO/CMakeLists.txt
@@ -15,6 +15,7 @@ add_llvm_library(lldMachO
MachONormalizedFileYAML.cpp
ShimPass.cpp
StubsPass.cpp
+ TLVPass.cpp
WriterMachO.cpp
LINK_LIBS
lldCore
diff --git a/lib/ReaderWriter/MachO/CompactUnwindPass.cpp b/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
index fc8608383e5d..4b8644a67e70 100644
--- a/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
+++ b/lib/ReaderWriter/MachO/CompactUnwindPass.cpp
@@ -1,4 +1,4 @@
-//===- lib/ReaderWriter/MachO/CompactUnwindPass.cpp -----------------------===//
+//===- lib/ReaderWriter/MachO/CompactUnwindPass.cpp -------------*- C++ -*-===//
//
// The LLVM Linker
//
@@ -92,7 +92,7 @@ public:
return DefinedAtom::typeProcessedUnwindInfo;
}
- Alignment alignment() const override { return Alignment(2); }
+ Alignment alignment() const override { return 4; }
uint64_t size() const override { return _contents.size(); }
@@ -272,12 +272,12 @@ private:
class CompactUnwindPass : public Pass {
public:
CompactUnwindPass(const MachOLinkingContext &context)
- : _context(context), _archHandler(_context.archHandler()),
+ : _ctx(context), _archHandler(_ctx.archHandler()),
_file("<mach-o Compact Unwind Pass>"),
- _isBig(MachOLinkingContext::isBigEndian(_context.arch())) {}
+ _isBig(MachOLinkingContext::isBigEndian(_ctx.arch())) {}
private:
- void perform(std::unique_ptr<MutableFile> &mergedFile) override {
+ std::error_code perform(SimpleFile &mergedFile) override {
DEBUG(llvm::dbgs() << "MachO Compact Unwind pass\n");
std::map<const Atom *, CompactUnwindEntry> unwindLocs;
@@ -294,7 +294,7 @@ private:
// Skip rest of pass if no unwind info.
if (unwindLocs.empty() && dwarfFrames.empty())
- return;
+ return std::error_code();
// 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
@@ -310,6 +310,9 @@ private:
std::vector<CompactUnwindEntry> unwindInfos = createUnwindInfoEntries(
mergedFile, unwindLocs, personalities, dwarfFrames);
+ // Remove any unused eh-frame atoms.
+ pruneUnusedEHFrames(mergedFile, unwindInfos, unwindLocs, dwarfFrames);
+
// Finally, we can start creating pages based on these entries.
DEBUG(llvm::dbgs() << " Splitting entries into pages\n");
@@ -339,24 +342,26 @@ private:
<< " has " << entriesInPage << " entries\n");
} while (pageStart < unwindInfos.size());
- UnwindInfoAtom *unwind = new (_file.allocator())
+ auto *unwind = new (_file.allocator())
UnwindInfoAtom(_archHandler, _file, _isBig, personalities,
commonEncodings, pages, numLSDAs);
- mergedFile->addAtom(*unwind);
+ mergedFile.addAtom(*unwind);
// Finally, remove all __compact_unwind atoms now that we've processed them.
- mergedFile->removeDefinedAtomsIf([](const DefinedAtom *atom) {
+ mergedFile.removeDefinedAtomsIf([](const DefinedAtom *atom) {
return atom->contentType() == DefinedAtom::typeCompactUnwindInfo;
});
+
+ return std::error_code();
}
void collectCompactUnwindEntries(
- std::unique_ptr<MutableFile> &mergedFile,
+ const SimpleFile &mergedFile,
std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
std::vector<const Atom *> &personalities, uint32_t &numLSDAs) {
DEBUG(llvm::dbgs() << " Collecting __compact_unwind entries\n");
- for (const DefinedAtom *atom : mergedFile->defined()) {
+ for (const DefinedAtom *atom : mergedFile.defined()) {
if (atom->contentType() != DefinedAtom::typeCompactUnwindInfo)
continue;
@@ -422,9 +427,9 @@ private:
}
void
- collectDwarfFrameEntries(std::unique_ptr<MutableFile> &mergedFile,
+ collectDwarfFrameEntries(const SimpleFile &mergedFile,
std::map<const Atom *, const Atom *> &dwarfFrames) {
- for (const DefinedAtom *ehFrameAtom : mergedFile->defined()) {
+ for (const DefinedAtom *ehFrameAtom : mergedFile.defined()) {
if (ehFrameAtom->contentType() != DefinedAtom::typeCFI)
continue;
if (ArchHandler::isDwarfCIE(_isBig, ehFrameAtom))
@@ -442,7 +447,7 @@ private:
/// + A synthesised reference to __eh_frame if there's no __compact_unwind
/// or too many personality functions to be accommodated.
std::vector<CompactUnwindEntry> createUnwindInfoEntries(
- const std::unique_ptr<MutableFile> &mergedFile,
+ const SimpleFile &mergedFile,
const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
const std::vector<const Atom *> &personalities,
const std::map<const Atom *, const Atom *> &dwarfFrames) {
@@ -452,7 +457,7 @@ private:
// The final order in the __unwind_info section must be derived from the
// order of typeCode atoms, since that's how they'll be put into the object
// file eventually (yuck!).
- for (const DefinedAtom *atom : mergedFile->defined()) {
+ for (const DefinedAtom *atom : mergedFile.defined()) {
if (atom->contentType() != DefinedAtom::typeCode)
continue;
@@ -468,6 +473,53 @@ private:
return unwindInfos;
}
+ /// Remove unused EH frames.
+ ///
+ /// An EH frame is considered unused if there is a corresponding compact
+ /// unwind atom that doesn't require the EH frame.
+ void pruneUnusedEHFrames(
+ SimpleFile &mergedFile,
+ const std::vector<CompactUnwindEntry> &unwindInfos,
+ const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
+ const std::map<const Atom *, const Atom *> &dwarfFrames) {
+
+ // Worklist of all 'used' FDEs.
+ std::vector<const DefinedAtom *> usedDwarfWorklist;
+
+ // We have to check two conditions when building the worklist:
+ // (1) EH frames used by compact unwind entries.
+ for (auto &entry : unwindInfos)
+ if (entry.ehFrame)
+ usedDwarfWorklist.push_back(cast<DefinedAtom>(entry.ehFrame));
+
+ // (2) EH frames that reference functions with no corresponding compact
+ // unwind info.
+ for (auto &entry : dwarfFrames)
+ if (!unwindLocs.count(entry.first))
+ usedDwarfWorklist.push_back(cast<DefinedAtom>(entry.second));
+
+ // Add all transitively referenced CFI atoms by processing the worklist.
+ std::set<const Atom *> usedDwarfFrames;
+ while (!usedDwarfWorklist.empty()) {
+ const DefinedAtom *cfiAtom = usedDwarfWorklist.back();
+ usedDwarfWorklist.pop_back();
+ usedDwarfFrames.insert(cfiAtom);
+ for (const auto *ref : *cfiAtom) {
+ const DefinedAtom *cfiTarget = dyn_cast<DefinedAtom>(ref->target());
+ if (cfiTarget->contentType() == DefinedAtom::typeCFI)
+ usedDwarfWorklist.push_back(cfiTarget);
+ }
+ }
+
+ // Finally, delete all unreferenced CFI atoms.
+ mergedFile.removeDefinedAtomsIf([&](const DefinedAtom *atom) {
+ if ((atom->contentType() == DefinedAtom::typeCFI) &&
+ !usedDwarfFrames.count(atom))
+ return true;
+ return false;
+ });
+ }
+
CompactUnwindEntry finalizeUnwindInfoEntryForAtom(
const DefinedAtom *function,
const std::map<const Atom *, CompactUnwindEntry> &unwindLocs,
@@ -496,7 +548,6 @@ private:
}
}
-
auto personality = std::find(personalities.begin(), personalities.end(),
entry.personalityFunction);
uint32_t personalityIdx = personality == personalities.end()
@@ -515,7 +566,7 @@ private:
return entry;
}
- const MachOLinkingContext &_context;
+ const MachOLinkingContext &_ctx;
mach_o::ArchHandler &_archHandler;
MachOFile _file;
bool _isBig;
diff --git a/lib/ReaderWriter/MachO/ExecutableAtoms.h b/lib/ReaderWriter/MachO/ExecutableAtoms.h
new file mode 100644
index 000000000000..2e99af903dbd
--- /dev/null
+++ b/lib/ReaderWriter/MachO/ExecutableAtoms.h
@@ -0,0 +1,133 @@
+//===- lib/ReaderWriter/MachO/ExecutableAtoms.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_MACHO_EXECUTABLE_ATOMS_H
+#define LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
+
+#include "Atoms.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"
+#include "lld/Core/Reference.h"
+#include "lld/Core/Simple.h"
+#include "lld/Core/UndefinedAtom.h"
+#include "lld/ReaderWriter/MachOLinkingContext.h"
+
+namespace lld {
+namespace mach_o {
+
+
+//
+// CEntryFile adds an UndefinedAtom for "_main" so that the Resolving
+// phase will fail if "_main" is undefined.
+//
+class CEntryFile : public SimpleFile {
+public:
+ CEntryFile(const MachOLinkingContext &context)
+ : SimpleFile("C entry"),
+ _undefMain(*this, context.entrySymbolName()) {
+ this->addAtom(_undefMain);
+ }
+
+private:
+ SimpleUndefinedAtom _undefMain;
+};
+
+
+//
+// StubHelperFile adds an UndefinedAtom for "dyld_stub_binder" so that
+// the Resolveing phase will fail if "dyld_stub_binder" is undefined.
+//
+class StubHelperFile : public SimpleFile {
+public:
+ StubHelperFile(const MachOLinkingContext &context)
+ : SimpleFile("stub runtime"),
+ _undefBinder(*this, context.binderSymbolName()) {
+ this->addAtom(_undefBinder);
+ }
+
+private:
+ SimpleUndefinedAtom _undefBinder;
+};
+
+
+//
+// MachHeaderAliasFile lazily instantiates the magic symbols that mark the start
+// of the mach_header for final linked images.
+//
+class MachHeaderAliasFile : public ArchiveLibraryFile {
+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)) {
+ _definedAtoms.push_back(new (allocator()) MachODefinedAtom(
+ *this, sym, DefinedAtom::scopeLinkageUnit,
+ DefinedAtom::typeMachHeader, DefinedAtom::mergeNo, false, false,
+ ArrayRef<uint8_t>(), DefinedAtom::Alignment(4096)));
+ return this;
+ }
+ return nullptr;
+ }
+
+ const AtomVector<DefinedAtom> &defined() const override {
+ return _definedAtoms;
+ }
+ const AtomVector<UndefinedAtom> &undefined() const override {
+ return _noUndefinedAtoms;
+ }
+
+ const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ return _noSharedLibraryAtoms;
+ }
+
+ const AtomVector<AbsoluteAtom> &absolute() const override {
+ return _noAbsoluteAtoms;
+ }
+
+
+private:
+ mutable AtomVector<DefinedAtom> _definedAtoms;
+ StringRef _machHeaderSymbolName;
+};
+
+} // namespace mach_o
+} // namespace lld
+
+#endif // LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
diff --git a/lib/ReaderWriter/MachO/ExecutableAtoms.hpp b/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
deleted file mode 100644
index cd562de216d9..000000000000
--- a/lib/ReaderWriter/MachO/ExecutableAtoms.hpp
+++ /dev/null
@@ -1,136 +0,0 @@
-//===- lib/ReaderWriter/MachO/ExecutableAtoms.hpp -------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
-#define LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
-
-#include "Atoms.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"
-#include "lld/Core/Reference.h"
-#include "lld/Core/Simple.h"
-#include "lld/Core/UndefinedAtom.h"
-#include "lld/ReaderWriter/MachOLinkingContext.h"
-
-namespace lld {
-namespace mach_o {
-
-
-//
-// CEntryFile adds an UndefinedAtom for "_main" so that the Resolving
-// phase will fail if "_main" is undefined.
-//
-class CEntryFile : public SimpleFile {
-public:
- CEntryFile(const MachOLinkingContext &context)
- : SimpleFile("C entry"),
- _undefMain(*this, context.entrySymbolName()) {
- this->addAtom(_undefMain);
- }
-
-private:
- SimpleUndefinedAtom _undefMain;
-};
-
-
-//
-// StubHelperFile adds an UndefinedAtom for "dyld_stub_binder" so that
-// the Resolveing phase will fail if "dyld_stub_binder" is undefined.
-//
-class StubHelperFile : public SimpleFile {
-public:
- StubHelperFile(const MachOLinkingContext &context)
- : SimpleFile("stub runtime"),
- _undefBinder(*this, context.binderSymbolName()) {
- this->addAtom(_undefBinder);
- }
-
-private:
- SimpleUndefinedAtom _undefBinder;
-};
-
-
-//
-// MachHeaderAliasFile lazily instantiates the magic symbols that mark the start
-// of the mach_header for final linked images.
-//
-class MachHeaderAliasFile : public ArchiveLibraryFile {
-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)) {
- _definedAtoms._atoms.push_back(new (allocator()) MachODefinedAtom(
- *this, sym, DefinedAtom::scopeLinkageUnit,
- DefinedAtom::typeMachHeader, DefinedAtom::mergeNo, false, false,
- ArrayRef<uint8_t>(), DefinedAtom::Alignment(12,0)));
- return this;
- }
- return nullptr;
- }
-
- const atom_collection<DefinedAtom> &defined() const override {
- return _definedAtoms;
- }
- const atom_collection<UndefinedAtom> &undefined() const override {
- return _undefinedAtoms;
- }
-
- const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
- return _sharedLibraryAtoms;
- }
-
- const atom_collection<AbsoluteAtom> &absolute() const override {
- return _absoluteAtoms;
- }
-
-
-private:
- mutable atom_collection_vector<DefinedAtom> _definedAtoms;
- atom_collection_vector<UndefinedAtom> _undefinedAtoms;
- atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
- atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
- StringRef _machHeaderSymbolName;
-};
-
-} // namespace mach_o
-} // namespace lld
-
-#endif // LLD_READER_WRITER_MACHO_EXECUTABLE_ATOMS_H
diff --git a/lib/ReaderWriter/MachO/File.h b/lib/ReaderWriter/MachO/File.h
index 913644ec1fc0..c97dfa142b8d 100644
--- a/lib/ReaderWriter/MachO/File.h
+++ b/lib/ReaderWriter/MachO/File.h
@@ -1,4 +1,4 @@
-//===- lib/ReaderWriter/MachO/File.h --------------------------------------===//
+//===- lib/ReaderWriter/MachO/File.h ----------------------------*- C++ -*-===//
//
// The LLVM Linker
//
@@ -44,8 +44,8 @@ public:
}
DefinedAtom::Alignment align(
inSection->alignment,
- sectionOffset % ((uint64_t)1 << inSection->alignment));
- MachODefinedAtom *atom =
+ sectionOffset % inSection->alignment);
+ auto *atom =
new (allocator()) MachODefinedAtom(*this, name, scope, type, merge,
thumb, noDeadStrip, content, align);
addAtomForSection(inSection, atom, sectionOffset);
@@ -67,8 +67,8 @@ public:
}
DefinedAtom::Alignment align(
inSection->alignment,
- sectionOffset % ((uint64_t)1 << inSection->alignment));
- MachODefinedCustomSectionAtom *atom =
+ sectionOffset % inSection->alignment);
+ auto *atom =
new (allocator()) MachODefinedCustomSectionAtom(*this, name, scope, type,
merge, thumb,
noDeadStrip, content,
@@ -86,10 +86,23 @@ public:
}
DefinedAtom::Alignment align(
inSection->alignment,
- sectionOffset % ((uint64_t)1 << inSection->alignment));
- MachODefinedAtom *atom =
- new (allocator()) MachODefinedAtom(*this, name, scope, size, noDeadStrip,
- align);
+ sectionOffset % inSection->alignment);
+
+ DefinedAtom::ContentType type = DefinedAtom::typeUnknown;
+ switch (inSection->type) {
+ case llvm::MachO::S_ZEROFILL:
+ type = DefinedAtom::typeZeroFill;
+ break;
+ case llvm::MachO::S_THREAD_LOCAL_ZEROFILL:
+ type = DefinedAtom::typeTLVInitialZeroFill;
+ break;
+ default:
+ llvm_unreachable("Unrecognized zero-fill section");
+ }
+
+ auto *atom =
+ new (allocator()) MachODefinedAtom(*this, name, scope, type, size,
+ noDeadStrip, align);
addAtomForSection(inSection, atom, sectionOffset);
}
@@ -98,8 +111,7 @@ public:
// Make a copy of the atom's name that is owned by this file.
name = name.copy(allocator());
}
- SimpleUndefinedAtom *atom =
- new (allocator()) SimpleUndefinedAtom(*this, name);
+ auto *atom = new (allocator()) SimpleUndefinedAtom(*this, name);
addAtom(*atom);
_undefAtoms[name] = atom;
}
@@ -110,7 +122,7 @@ public:
// Make a copy of the atom's name that is owned by this file.
name = name.copy(allocator());
}
- MachOTentativeDefAtom *atom =
+ auto *atom =
new (allocator()) MachOTentativeDefAtom(*this, name, scope, size, align);
addAtom(*atom);
_undefAtoms[name] = atom;
@@ -200,7 +212,6 @@ private:
addAtom(*atom);
}
-
typedef llvm::DenseMap<const normalized::Section *,
std::vector<SectionOffsetAndAtom>> SectionToAtoms;
typedef llvm::StringMap<const lld::Atom *> NameToAtom;
@@ -298,7 +309,6 @@ private:
return nullptr;
}
-
struct ReExportedDylib {
ReExportedDylib(StringRef p) : path(p), file(nullptr) { }
StringRef path;
@@ -324,4 +334,4 @@ private:
} // end namespace mach_o
} // end namespace lld
-#endif
+#endif // LLD_READER_WRITER_MACHO_FILE_H
diff --git a/lib/ReaderWriter/MachO/FlatNamespaceFile.h b/lib/ReaderWriter/MachO/FlatNamespaceFile.h
new file mode 100644
index 000000000000..6c6a9262ba2e
--- /dev/null
+++ b/lib/ReaderWriter/MachO/FlatNamespaceFile.h
@@ -0,0 +1,61 @@
+//===- lib/ReaderWriter/MachO/FlatNamespaceFile.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_MACHO_FLAT_NAMESPACE_FILE_H
+#define LLD_READER_WRITER_MACHO_FLAT_NAMESPACE_FILE_H
+
+#include "lld/Core/SharedLibraryFile.h"
+#include "llvm/Support/Debug.h"
+
+namespace lld {
+namespace mach_o {
+
+//
+// A FlateNamespaceFile instance may be added as a resolution source of last
+// resort, depending on how -flat_namespace and -undefined are set.
+//
+class FlatNamespaceFile : public SharedLibraryFile {
+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();
+ }
+
+ StringRef getDSOName() const override { return "flat-namespace"; }
+
+ const AtomVector<DefinedAtom> &defined() const override {
+ return _noDefinedAtoms;
+ }
+ const AtomVector<UndefinedAtom> &undefined() const override {
+ return _noUndefinedAtoms;
+ }
+
+ const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ return _sharedLibraryAtoms;
+ }
+
+ const AtomVector<AbsoluteAtom> &absolute() const override {
+ return _noAbsoluteAtoms;
+ }
+
+private:
+ mutable AtomVector<SharedLibraryAtom> _sharedLibraryAtoms;
+};
+
+} // namespace mach_o
+} // namespace lld
+
+#endif // LLD_READER_WRITER_MACHO_FLAT_NAMESPACE_FILE_H
diff --git a/lib/ReaderWriter/MachO/GOTPass.cpp b/lib/ReaderWriter/MachO/GOTPass.cpp
index 1ddec4003cbd..a5816277dd71 100644
--- a/lib/ReaderWriter/MachO/GOTPass.cpp
+++ b/lib/ReaderWriter/MachO/GOTPass.cpp
@@ -1,4 +1,4 @@
-//===- lib/ReaderWriter/MachO/GOTPass.cpp ---------------------------------===//
+//===- lib/ReaderWriter/MachO/GOTPass.cpp -----------------------*- C++ -*-===//
//
// The LLVM Linker
//
@@ -46,7 +46,6 @@
namespace lld {
namespace mach_o {
-
//
// GOT Entry Atom created by the GOT pass.
//
@@ -60,7 +59,7 @@ public:
}
Alignment alignment() const override {
- return Alignment(_is64 ? 3 : 2);
+ return _is64 ? 8 : 4;
}
uint64_t size() const override {
@@ -86,20 +85,18 @@ private:
StringRef _name;
};
-
/// Pass for instantiating and optimizing GOT slots.
///
class GOTPass : public Pass {
public:
GOTPass(const MachOLinkingContext &context)
- : _context(context), _archHandler(_context.archHandler()),
- _file("<mach-o GOT Pass>") { }
+ : _ctx(context), _archHandler(_ctx.archHandler()),
+ _file("<mach-o GOT Pass>") {}
private:
-
- void perform(std::unique_ptr<MutableFile> &mergedFile) override {
+ std::error_code perform(SimpleFile &mergedFile) override {
// Scan all references in all atoms.
- for (const DefinedAtom *atom : mergedFile->defined()) {
+ for (const DefinedAtom *atom : mergedFile.defined()) {
for (const Reference *ref : *atom) {
// Look at instructions accessing the GOT.
bool canBypassGOT;
@@ -131,7 +128,9 @@ private:
return (left->slotName().compare(right->slotName()) < 0);
});
for (const GOTEntryAtom *slot : entries)
- mergedFile->addAtom(*slot);
+ mergedFile.addAtom(*slot);
+
+ return std::error_code();
}
bool shouldReplaceTargetWithGOTAtom(const Atom *target, bool canBypassGOT) {
@@ -154,8 +153,8 @@ private:
const DefinedAtom *makeGOTEntry(const Atom *target) {
auto pos = _targetToGOT.find(target);
if (pos == _targetToGOT.end()) {
- GOTEntryAtom *gotEntry = new (_file.allocator())
- GOTEntryAtom(_file, _context.is64Bit(), target->name());
+ auto *gotEntry = new (_file.allocator())
+ GOTEntryAtom(_file, _ctx.is64Bit(), target->name());
_targetToGOT[target] = gotEntry;
const ArchHandler::ReferenceInfo &nlInfo = _archHandler.stubInfo().
nonLazyPointerReferenceToBinder;
@@ -166,20 +165,16 @@ private:
return pos->second;
}
-
- const MachOLinkingContext &_context;
+ const MachOLinkingContext &_ctx;
mach_o::ArchHandler &_archHandler;
MachOFile _file;
llvm::DenseMap<const Atom*, const GOTEntryAtom*> _targetToGOT;
};
-
-
void addGOTPass(PassManager &pm, const MachOLinkingContext &ctx) {
assert(ctx.needsGOTPass());
pm.add(llvm::make_unique<GOTPass>(ctx));
}
-
} // end namesapce mach_o
} // end namesapce lld
diff --git a/lib/ReaderWriter/MachO/LayoutPass.cpp b/lib/ReaderWriter/MachO/LayoutPass.cpp
index 2d096e4c1a6a..0c14ee9d39ab 100644
--- a/lib/ReaderWriter/MachO/LayoutPass.cpp
+++ b/lib/ReaderWriter/MachO/LayoutPass.cpp
@@ -133,7 +133,7 @@ static void checkReachabilityFromRoot(AtomToAtomT &followOnRoots,
}
}
-static void printDefinedAtoms(const MutableFile::DefinedAtomRange &atomRange) {
+static void printDefinedAtoms(const SimpleFile::DefinedAtomRange &atomRange) {
for (const DefinedAtom *atom : atomRange) {
llvm::dbgs() << " file=" << atom->file().path()
<< ", name=" << atom->name()
@@ -146,7 +146,7 @@ static void printDefinedAtoms(const MutableFile::DefinedAtomRange &atomRange) {
/// Verify that the followon chain is sane. Should not be called in
/// release binary.
-void LayoutPass::checkFollowonChain(MutableFile::DefinedAtomRange &range) {
+void LayoutPass::checkFollowonChain(SimpleFile::DefinedAtomRange &range) {
ScopedTask task(getDefaultDomain(), "LayoutPass::checkFollowonChain");
// Verify that there's no cycle in follow-on chain.
@@ -329,7 +329,7 @@ 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(MutableFile::DefinedAtomRange &range) {
+void LayoutPass::buildFollowOnTable(SimpleFile::DefinedAtomRange &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.
@@ -397,7 +397,7 @@ void LayoutPass::buildFollowOnTable(MutableFile::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(MutableFile::DefinedAtomRange &range) {
+void LayoutPass::buildOrdinalOverrideMap(SimpleFile::DefinedAtomRange &range) {
ScopedTask task(getDefaultDomain(), "LayoutPass::buildOrdinalOverrideMap");
uint64_t index = 0;
for (const DefinedAtom *ai : range) {
@@ -407,7 +407,7 @@ void LayoutPass::buildOrdinalOverrideMap(MutableFile::DefinedAtomRange &range) {
AtomToAtomT::iterator start = _followOnRoots.find(atom);
if (start == _followOnRoots.end())
continue;
- for (const DefinedAtom *nextAtom = start->second; nextAtom != NULL;
+ for (const DefinedAtom *nextAtom = start->second; nextAtom;
nextAtom = _followOnNexts[nextAtom]) {
AtomToOrdinalT::iterator pos = _ordinalOverrideMap.find(nextAtom);
if (pos == _ordinalOverrideMap.end())
@@ -417,7 +417,7 @@ void LayoutPass::buildOrdinalOverrideMap(MutableFile::DefinedAtomRange &range) {
}
std::vector<LayoutPass::SortKey>
-LayoutPass::decorate(MutableFile::DefinedAtomRange &atomRange) const {
+LayoutPass::decorate(SimpleFile::DefinedAtomRange &atomRange) const {
std::vector<SortKey> ret;
for (const DefinedAtom *atom : atomRange) {
auto ri = _followOnRoots.find(atom);
@@ -429,7 +429,7 @@ LayoutPass::decorate(MutableFile::DefinedAtomRange &atomRange) const {
return ret;
}
-void LayoutPass::undecorate(MutableFile::DefinedAtomRange &atomRange,
+void LayoutPass::undecorate(SimpleFile::DefinedAtomRange &atomRange,
std::vector<SortKey> &keys) const {
size_t i = 0;
for (SortKey &k : keys)
@@ -437,10 +437,11 @@ void LayoutPass::undecorate(MutableFile::DefinedAtomRange &atomRange,
}
/// Perform the actual pass
-void LayoutPass::perform(std::unique_ptr<MutableFile> &mergedFile) {
+std::error_code LayoutPass::perform(SimpleFile &mergedFile) {
+ DEBUG(llvm::dbgs() << "******** Laying out atoms:\n");
// sort the atoms
ScopedTask task(getDefaultDomain(), "LayoutPass");
- MutableFile::DefinedAtomRange atomRange = mergedFile->definedAtoms();
+ SimpleFile::DefinedAtomRange atomRange = mergedFile.definedAtoms();
// Build follow on tables
buildFollowOnTable(atomRange);
@@ -468,6 +469,9 @@ void LayoutPass::perform(std::unique_ptr<MutableFile> &mergedFile) {
llvm::dbgs() << "sorted atoms:\n";
printDefinedAtoms(atomRange);
});
+
+ DEBUG(llvm::dbgs() << "******** Finished laying out atoms\n");
+ return std::error_code();
}
void addLayoutPass(PassManager &pm, const MachOLinkingContext &ctx) {
diff --git a/lib/ReaderWriter/MachO/LayoutPass.h b/lib/ReaderWriter/MachO/LayoutPass.h
index 186f29be0719..d6072b0ca4fb 100644
--- a/lib/ReaderWriter/MachO/LayoutPass.h
+++ b/lib/ReaderWriter/MachO/LayoutPass.h
@@ -13,6 +13,7 @@
#include "lld/Core/File.h"
#include "lld/Core/Pass.h"
#include "lld/Core/Reader.h"
+#include "lld/Core/Simple.h"
#include "llvm/ADT/DenseMap.h"
#include <map>
#include <string>
@@ -20,7 +21,7 @@
namespace lld {
class DefinedAtom;
-class MutableFile;
+class SimpleFile;
namespace mach_o {
@@ -45,17 +46,17 @@ public:
LayoutPass(const Registry &registry, SortOverride sorter);
/// Sorts atoms in mergedFile by content type then by command line order.
- void perform(std::unique_ptr<MutableFile> &mergedFile) override;
+ std::error_code perform(SimpleFile &mergedFile) override;
- virtual ~LayoutPass() {}
+ ~LayoutPass() override = default;
private:
// Build the followOn atoms chain as specified by the kindLayoutAfter
// reference type
- void buildFollowOnTable(MutableFile::DefinedAtomRange &range);
+ void buildFollowOnTable(SimpleFile::DefinedAtomRange &range);
// Build a map of Atoms to ordinals for sorting the atoms
- void buildOrdinalOverrideMap(MutableFile::DefinedAtomRange &range);
+ void buildOrdinalOverrideMap(SimpleFile::DefinedAtomRange &range);
const Registry &_registry;
SortOverride _customSorter;
@@ -83,12 +84,12 @@ private:
void setChainRoot(const DefinedAtom *targetAtom, const DefinedAtom *root);
- std::vector<SortKey> decorate(MutableFile::DefinedAtomRange &atomRange) const;
- void undecorate(MutableFile::DefinedAtomRange &atomRange,
+ std::vector<SortKey> decorate(SimpleFile::DefinedAtomRange &atomRange) const;
+ void undecorate(SimpleFile::DefinedAtomRange &atomRange,
std::vector<SortKey> &keys) const;
// Check if the follow-on graph is a correct structure. For debugging only.
- void checkFollowonChain(MutableFile::DefinedAtomRange &range);
+ void checkFollowonChain(SimpleFile::DefinedAtomRange &range);
};
} // namespace mach_o
diff --git a/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
index 92385cf3e820..1c97c5a39d3f 100644
--- a/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
+++ b/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
@@ -10,8 +10,10 @@
#include "lld/ReaderWriter/MachOLinkingContext.h"
#include "ArchHandler.h"
#include "File.h"
+#include "FlatNamespaceFile.h"
#include "MachONormalizedFile.h"
#include "MachOPasses.h"
+#include "SectCreateFile.h"
#include "lld/Core/ArchiveLibraryFile.h"
#include "lld/Core/PassManager.h"
#include "lld/Core/Reader.h"
@@ -73,7 +75,6 @@ bool MachOLinkingContext::parsePackedVersion(StringRef str, uint32_t &result) {
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 },
@@ -133,8 +134,7 @@ bool MachOLinkingContext::isThinObjectFile(StringRef path, Arch &arch) {
return mach_o::normalized::isThinObjectFile(path, arch);
}
-bool MachOLinkingContext::sliceFromFatFile(const MemoryBuffer &mb,
- uint32_t &offset,
+bool MachOLinkingContext::sliceFromFatFile(MemoryBufferRef mb, uint32_t &offset,
uint32_t &size) {
return mach_o::normalized::sliceFromFatFile(mb, _arch, offset, size);
}
@@ -143,11 +143,13 @@ 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),
- _compatibilityVersion(0), _currentVersion(0), _deadStrippableDylib(false),
- _printAtoms(false), _testingFileUsage(false), _keepPrivateExterns(false),
- _demangle(false), _archHandler(nullptr),
+ _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) {}
+ _debugInfoMode(DebugInfoMode::addDebugMap), _orderFileEntries(0),
+ _flatNamespaceFile(nullptr) {}
MachOLinkingContext::~MachOLinkingContext() {}
@@ -196,6 +198,9 @@ void MachOLinkingContext::configure(HeaderFileType type, Arch arch, OS os,
_pageZeroSize = 0x1000;
}
+ // Initial base address is __PAGEZERO size.
+ _baseAddress = _pageZeroSize;
+
// Make PIE by default when targetting newer OSs.
switch (os) {
case OS::macOSX:
@@ -268,8 +273,6 @@ bool MachOLinkingContext::isBigEndian(Arch arch) {
llvm_unreachable("Unknown arch type");
}
-
-
bool MachOLinkingContext::is64Bit() const {
return is64Bit(_arch);
}
@@ -337,13 +340,21 @@ bool MachOLinkingContext::needsShimPass() const {
}
}
+bool MachOLinkingContext::needsTLVPass() const {
+ switch (_outputMachOType) {
+ case MH_BUNDLE:
+ case MH_EXECUTE:
+ case MH_DYLIB:
+ return true;
+ default:
+ return false;
+ }
+}
+
StringRef MachOLinkingContext::binderSymbolName() const {
return archHandler().stubInfo().binderSymbolName;
}
-
-
-
bool MachOLinkingContext::minOS(StringRef mac, StringRef iOS) const {
uint32_t parsedVersion;
switch (_os) {
@@ -473,7 +484,6 @@ void MachOLinkingContext::addFrameworkSearchDir(StringRef fwPath,
_frameworkDirs.push_back(fwPath);
}
-
ErrorOr<StringRef>
MachOLinkingContext::searchDirForLibrary(StringRef path,
StringRef libName) const {
@@ -502,8 +512,6 @@ MachOLinkingContext::searchDirForLibrary(StringRef path,
return make_error_code(llvm::errc::no_such_file_or_directory);
}
-
-
ErrorOr<StringRef> MachOLinkingContext::searchLibrary(StringRef libName) const {
SmallString<256> path;
for (StringRef dir : searchDirs()) {
@@ -515,7 +523,6 @@ ErrorOr<StringRef> MachOLinkingContext::searchLibrary(StringRef libName) const {
return make_error_code(llvm::errc::no_such_file_or_directory);
}
-
ErrorOr<StringRef> MachOLinkingContext::findPathForFramework(StringRef fwName) const{
SmallString<256> fullPath;
for (StringRef dir : frameworkDirs()) {
@@ -589,6 +596,8 @@ void MachOLinkingContext::addPasses(PassManager &pm) {
mach_o::addCompactUnwindPass(pm, *this);
if (needsGOTPass())
mach_o::addGOTPass(pm, *this);
+ if (needsTLVPass())
+ mach_o::addTLVPass(pm, *this);
if (needsShimPass())
mach_o::addShimPass(pm, *this); // Shim pass must run after stubs pass.
}
@@ -613,7 +622,7 @@ MachOLinkingContext::getMemoryBuffer(StringRef path) {
// and switch buffer to point to just that required slice.
uint32_t offset;
uint32_t size;
- if (sliceFromFatFile(*mb, offset, size))
+ if (sliceFromFatFile(mb->getMemBufferRef(), offset, size))
return MemoryBuffer::getFileSlice(path, size, offset);
return std::move(mb);
}
@@ -623,18 +632,18 @@ MachODylibFile* MachOLinkingContext::loadIndirectDylib(StringRef path) {
if (mbOrErr.getError())
return nullptr;
- std::vector<std::unique_ptr<File>> files;
- if (registry().loadFile(std::move(mbOrErr.get()), files))
+ ErrorOr<std::unique_ptr<File>> fileOrErr =
+ registry().loadFile(std::move(mbOrErr.get()));
+ if (!fileOrErr)
return nullptr;
- assert(files.size() == 1 && "expected one file in dylib");
- files[0]->parse();
- MachODylibFile* result = reinterpret_cast<MachODylibFile*>(files[0].get());
+ std::unique_ptr<File> &file = fileOrErr.get();
+ file->parse();
+ MachODylibFile *result = reinterpret_cast<MachODylibFile *>(file.get());
// Node object now owned by _indirectDylibs vector.
- _indirectDylibs.push_back(std::move(files[0]));
+ _indirectDylibs.push_back(std::move(file));
return result;
}
-
MachODylibFile* MachOLinkingContext::findIndirectDylib(StringRef path) {
// See if already loaded.
auto pos = _pathToDylibMap.find(path);
@@ -685,7 +694,7 @@ uint32_t MachOLinkingContext::dylibCompatVersion(StringRef installName) const {
return 0x1000; // 1.0
}
-bool MachOLinkingContext::createImplicitFiles(
+void MachOLinkingContext::createImplicitFiles(
std::vector<std::unique_ptr<File> > &result) {
// Add indirect dylibs by asking each linked dylib to add its indirects.
// Iterate until no more dylibs get loaded.
@@ -699,12 +708,19 @@ bool MachOLinkingContext::createImplicitFiles(
}
// Let writer add output type specific extras.
- return writer().createImplicitFiles(result);
-}
+ writer().createImplicitFiles(result);
+ // If undefinedMode is != error, add a FlatNamespaceFile instance. This will
+ // provide a SharedLibraryAtom for symbols that aren't defined elsewhere.
+ if (undefinedMode() != UndefinedMode::error) {
+ result.emplace_back(new mach_o::FlatNamespaceFile(*this));
+ _flatNamespaceFile = result.back().get();
+ }
+}
void MachOLinkingContext::registerDylib(MachODylibFile *dylib,
bool upward) const {
+ std::lock_guard<std::mutex> lock(_dylibsMutex);
_allDylibs.insert(dylib);
_pathToDylibMap[dylib->installName()] = dylib;
// If path is different than install name, register path too.
@@ -714,7 +730,6 @@ void MachOLinkingContext::registerDylib(MachODylibFile *dylib,
_upwardDylibs.insert(dylib);
}
-
bool MachOLinkingContext::isUpwardDylib(StringRef installName) const {
for (MachODylibFile *dylib : _upwardDylibs) {
if (dylib->installName().equals(installName))
@@ -729,28 +744,37 @@ ArchHandler &MachOLinkingContext::archHandler() const {
return *_archHandler;
}
-
void MachOLinkingContext::addSectionAlignment(StringRef seg, StringRef sect,
- uint8_t align2) {
- SectionAlign entry;
- entry.segmentName = seg;
- entry.sectionName = sect;
- entry.align2 = align2;
+ uint16_t align) {
+ SectionAlign entry = { seg, sect, align };
_sectAligns.push_back(entry);
}
+void MachOLinkingContext::addSectCreateSection(
+ StringRef seg, StringRef sect,
+ std::unique_ptr<MemoryBuffer> content) {
+
+ if (!_sectCreateFile) {
+ auto sectCreateFile = llvm::make_unique<mach_o::SectCreateFile>();
+ _sectCreateFile = sectCreateFile.get();
+ getNodes().push_back(llvm::make_unique<FileNode>(std::move(sectCreateFile)));
+ }
+
+ assert(_sectCreateFile && "sectcreate file does not exist.");
+ _sectCreateFile->addSection(seg, sect, std::move(content));
+}
+
bool MachOLinkingContext::sectionAligned(StringRef seg, StringRef sect,
- uint8_t &align2) const {
+ uint16_t &align) const {
for (const SectionAlign &entry : _sectAligns) {
if (seg.equals(entry.segmentName) && sect.equals(entry.sectionName)) {
- align2 = entry.align2;
+ align = entry.align;
return true;
}
}
return false;
}
-
void MachOLinkingContext::addExportSymbol(StringRef sym) {
// Support old crufty export lists with bogus entries.
if (sym.endswith(".eh") || sym.startswith(".objc_category_name_")) {
@@ -805,7 +829,7 @@ std::string MachOLinkingContext::demangle(StringRef symbolName) const {
const char *cstr = nullTermSym.data() + 1;
int status;
char *demangled = abi::__cxa_demangle(cstr, nullptr, nullptr, &status);
- if (demangled != NULL) {
+ if (demangled) {
std::string result(demangled);
// __cxa_demangle() always uses a malloc'ed buffer to return the result.
free(demangled);
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFile.h b/lib/ReaderWriter/MachO/MachONormalizedFile.h
index 70bcde2dea22..cccf180f1043 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFile.h
+++ b/lib/ReaderWriter/MachO/MachONormalizedFile.h
@@ -45,6 +45,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Allocator.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/ErrorOr.h"
#include "llvm/Support/MachO.h"
#include "llvm/Support/YAMLTraits.h"
@@ -108,17 +109,26 @@ LLVM_YAML_STRONG_TYPEDEF(uint32_t, SectionAttr)
/// can support either kind.
struct Section {
Section() : type(llvm::MachO::S_REGULAR),
- attributes(0), alignment(0), address(0) { }
+ attributes(0), alignment(1), address(0) { }
StringRef segmentName;
StringRef sectionName;
SectionType type;
SectionAttr attributes;
- uint32_t alignment;
+ uint16_t alignment;
Hex64 address;
ArrayRef<uint8_t> content;
Relocations relocations;
IndirectSymbols indirectSymbols;
+
+#ifndef NDEBUG
+ raw_ostream& operator<<(raw_ostream &OS) const {
+ dump(OS);
+ return OS;
+ }
+
+ void dump(raw_ostream &OS = llvm::dbgs()) const;
+#endif
};
@@ -142,6 +152,14 @@ struct Symbol {
Hex64 value;
};
+/// Check whether the given section type indicates a zero-filled section.
+// FIXME: Utility functions of this kind should probably be moved into
+// llvm/Support.
+inline bool isZeroFillSection(SectionType T) {
+ return (T == llvm::MachO::S_ZEROFILL ||
+ T == llvm::MachO::S_THREAD_LOCAL_ZEROFILL);
+}
+
/// A typedef so that YAML I/O can (de/en)code the protection bits of a segment.
LLVM_YAML_STRONG_TYPEDEF(uint32_t, VMProtect)
@@ -210,15 +228,9 @@ LLVM_YAML_STRONG_TYPEDEF(uint32_t, FileFlags)
///
struct NormalizedFile {
- NormalizedFile() : arch(MachOLinkingContext::arch_unknown),
- fileType(llvm::MachO::MH_OBJECT),
- flags(0),
- hasUUID(false),
- os(MachOLinkingContext::OS::unknown) { }
-
- MachOLinkingContext::Arch arch;
- HeaderFileType fileType;
- FileFlags flags;
+ MachOLinkingContext::Arch arch = MachOLinkingContext::arch_unknown;
+ HeaderFileType fileType = llvm::MachO::MH_OBJECT;
+ FileFlags flags = 0;
std::vector<Segment> segments; // Not used in object files.
std::vector<Section> sections;
@@ -229,19 +241,20 @@ struct NormalizedFile {
// Maps to load commands with no LINKEDIT content (final linked images only).
std::vector<DependentDylib> dependentDylibs;
- StringRef installName; // dylibs only
- PackedVersion compatVersion; // dylibs only
- PackedVersion currentVersion; // dylibs only
- bool hasUUID;
+ StringRef installName; // dylibs only
+ PackedVersion compatVersion = 0; // dylibs only
+ PackedVersion currentVersion = 0; // dylibs only
+ bool hasUUID = false;
std::vector<StringRef> rpaths;
- Hex64 entryAddress;
- MachOLinkingContext::OS os;
- Hex64 sourceVersion;
- PackedVersion minOSverson;
- PackedVersion sdkVersion;
+ Hex64 entryAddress = 0;
+ Hex64 stackSize = 0;
+ MachOLinkingContext::OS os = MachOLinkingContext::OS::unknown;
+ Hex64 sourceVersion = 0;
+ PackedVersion minOSverson = 0;
+ PackedVersion sdkVersion = 0;
// Maps to load commands with LINKEDIT content (final linked images only).
- Hex32 pageSize;
+ Hex32 pageSize = 0;
std::vector<RebaseLocation> rebasingInfo;
std::vector<BindLocation> bindingInfo;
std::vector<BindLocation> weakBindingInfo;
@@ -264,8 +277,8 @@ bool isThinObjectFile(StringRef path, MachOLinkingContext::Arch &arch);
/// If the buffer is a fat file with the request arch, then this function
/// returns true with 'offset' and 'size' set to location of the arch slice
/// within the buffer. Otherwise returns false;
-bool sliceFromFatFile(const MemoryBuffer &mb, MachOLinkingContext::Arch arch,
- uint32_t &offset, uint32_t &size);
+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>>
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
index 07a6dbfe569b..1013d3ddaef3 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp
@@ -30,6 +30,7 @@
#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Twine.h"
#include "llvm/Object/MachO.h"
#include "llvm/Support/Casting.h"
@@ -169,9 +170,8 @@ bool isThinObjectFile(StringRef path, MachOLinkingContext::Arch &arch) {
return true;
}
-
-bool sliceFromFatFile(const MemoryBuffer &mb, MachOLinkingContext::Arch arch,
- uint32_t &offset, uint32_t &size) {
+bool sliceFromFatFile(MemoryBufferRef mb, MachOLinkingContext::Arch arch,
+ uint32_t &offset, uint32_t &size) {
const char *start = mb.getBufferStart();
const llvm::MachO::fat_header *fh =
reinterpret_cast<const llvm::MachO::fat_header *>(start);
@@ -211,7 +211,7 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
uint32_t sliceOffset;
uint32_t sliceSize;
- if (sliceFromFatFile(*mb, arch, sliceOffset, sliceSize)) {
+ if (sliceFromFatFile(mb->getMemBufferRef(), arch, sliceOffset, sliceSize)) {
start = &start[sliceOffset];
objSize = sliceSize;
mh = reinterpret_cast<const mach_header *>(start);
@@ -297,7 +297,7 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
section.type = (SectionType)(read32(&sect->flags, isBig) &
SECTION_TYPE);
section.attributes = read32(&sect->flags, isBig) & SECTION_ATTRIBUTES;
- section.alignment = read32(&sect->align, isBig);
+ section.alignment = 1 << read32(&sect->align, isBig);
section.address = read64(&sect->addr, isBig);
const uint8_t *content =
(const uint8_t *)start + read32(&sect->offset, isBig);
@@ -341,7 +341,7 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
SECTION_TYPE);
section.attributes =
read32((const uint8_t *)&sect->flags, isBig) & SECTION_ATTRIBUTES;
- section.alignment = read32(&sect->align, isBig);
+ section.alignment = 1 << read32(&sect->align, isBig);
section.address = read32(&sect->addr, isBig);
const uint8_t *content =
(const uint8_t *)start + read32(&sect->offset, isBig);
@@ -516,22 +516,17 @@ class MachOObjectReader : public Reader {
public:
MachOObjectReader(MachOLinkingContext &ctx) : _ctx(ctx) {}
- bool canParse(file_magic magic, StringRef ext,
- const MemoryBuffer &mb) const override {
- switch (magic) {
- case llvm::sys::fs::file_magic::macho_object:
- return (mb.getBufferSize() > 32);
- default:
- return false;
- }
+ bool canParse(file_magic magic, MemoryBufferRef mb) const override {
+ return (magic == llvm::sys::fs::file_magic::macho_object &&
+ mb.getBufferSize() > 32);
}
- std::error_code
- loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry &registry,
- std::vector<std::unique_ptr<File>> &result) const override {
- auto *file = new MachOFile(std::move(mb), &_ctx);
- result.push_back(std::unique_ptr<MachOFile>(file));
- return std::error_code();
+ ErrorOr<std::unique_ptr<File>>
+ loadFile(std::unique_ptr<MemoryBuffer> mb,
+ const Registry &registry) const override {
+ std::unique_ptr<File> ret =
+ llvm::make_unique<MachOFile>(std::move(mb), &_ctx);
+ return std::move(ret);
}
private:
@@ -542,23 +537,22 @@ class MachODylibReader : public Reader {
public:
MachODylibReader(MachOLinkingContext &ctx) : _ctx(ctx) {}
- bool canParse(file_magic magic, StringRef ext,
- const MemoryBuffer &mb) const override {
+ bool canParse(file_magic magic, MemoryBufferRef mb) const override {
switch (magic) {
case llvm::sys::fs::file_magic::macho_dynamically_linked_shared_lib:
case llvm::sys::fs::file_magic::macho_dynamically_linked_shared_lib_stub:
- return (mb.getBufferSize() > 32);
+ return mb.getBufferSize() > 32;
default:
return false;
}
}
- std::error_code
- loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry &registry,
- std::vector<std::unique_ptr<File>> &result) const override {
- auto *file = new MachODylibFile(std::move(mb), &_ctx);
- result.push_back(std::unique_ptr<MachODylibFile>(file));
- return std::error_code();
+ ErrorOr<std::unique_ptr<File>>
+ loadFile(std::unique_ptr<MemoryBuffer> mb,
+ const Registry &registry) const override {
+ std::unique_ptr<File> ret =
+ llvm::make_unique<MachODylibFile>(std::move(mb), &_ctx);
+ return std::move(ret);
}
private:
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
index be7acf9d4d60..4ecfece0629e 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
@@ -149,6 +149,7 @@ private:
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.
@@ -159,7 +160,6 @@ private:
struct TrieEdge {
TrieEdge(StringRef s, TrieNode *node) : _subString(s), _child(node) {}
- ~TrieEdge() {}
StringRef _subString;
struct TrieNode *_child;
@@ -169,14 +169,14 @@ private:
TrieNode(StringRef s)
: _cummulativeString(s), _address(0), _flags(0), _other(0),
_trieOffset(0), _hasExportInfo(false) {}
- ~TrieNode() {}
+ ~TrieNode() = default;
void addSymbol(const Export &entry, BumpPtrAllocator &allocator,
std::vector<TrieNode *> &allNodes);
bool updateOffset(uint32_t &offset);
void appendToByteBuffer(ByteBuffer &out);
-private:
+ private:
StringRef _cummulativeString;
std::list<TrieEdge> _children;
uint64_t _address;
@@ -263,7 +263,6 @@ size_t MachOFileLayout::headerAndLoadCommandsSize() const {
return _endOfLoadCommands;
}
-
MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
: _file(file),
_is64(MachOLinkingContext::is64Bit(file.arch)),
@@ -290,12 +289,12 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
unsigned relocCount = 0;
uint64_t offset = _startOfSectionsContent;
for (const Section &sect : file.sections) {
- if (sect.type != llvm::MachO::S_ZEROFILL) {
- offset = llvm::RoundUpToAlignment(offset, 1 << sect.alignment);
+ if (isZeroFillSection(sect.type))
+ _sectInfo[&sect].fileOffset = 0;
+ else {
+ offset = llvm::RoundUpToAlignment(offset, sect.alignment);
_sectInfo[&sect].fileOffset = offset;
offset += sect.content.size();
- } else {
- _sectInfo[&sect].fileOffset = 0;
}
relocCount += sect.relocations.size();
}
@@ -430,7 +429,7 @@ uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
// Add LC_RPATH
for (const StringRef &path : _file.rpaths) {
- size += sizeof(rpath_command) + pointerAlign(path.size()+1);
+ size += pointerAlign(sizeof(rpath_command) + path.size() + 1);
++count;
}
@@ -531,7 +530,7 @@ void MachOFileLayout::buildFileOffsets() {
for (const Section *s : _segInfo[&sg].sections) {
uint32_t sectOffset = s->address - sg.address;
uint32_t sectFileSize =
- s->type == llvm::MachO::S_ZEROFILL ? 0 : s->content.size();
+ isZeroFillSection(s->type) ? 0 : s->content.size();
segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
_sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
@@ -549,7 +548,6 @@ void MachOFileLayout::buildFileOffsets() {
_startOfLinkEdit = fileOffset;
}
-
size_t MachOFileLayout::size() const {
return _endOfSymbolStrings;
}
@@ -613,7 +611,7 @@ std::error_code MachOFileLayout::writeSingleSegmentLoadCommand(uint8_t *&lc) {
sout->addr = sin.address;
sout->size = sin.content.size();
sout->offset = _sectInfo[&sin].fileOffset;
- sout->align = sin.alignment;
+ sout->align = llvm::Log2_32(sin.alignment);
sout->reloff = sin.relocations.empty() ? 0 : relOffset;
sout->nreloc = sin.relocations.size();
sout->flags = sin.type | sin.attributes;
@@ -657,11 +655,11 @@ std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
setString16(section->segmentName, sect->segname);
sect->addr = section->address;
sect->size = section->content.size();
- if (section->type == llvm::MachO::S_ZEROFILL)
+ if (isZeroFillSection(section->type))
sect->offset = 0;
else
sect->offset = section->address - seg.address + segInfo.fileOffset;
- sect->align = section->alignment;
+ sect->align = llvm::Log2_32(section->alignment);
sect->reloff = 0;
sect->nreloc = 0;
sect->flags = section->type | section->attributes;
@@ -829,7 +827,7 @@ std::error_code MachOFileLayout::writeLoadCommands() {
ep->cmd = LC_MAIN;
ep->cmdsize = sizeof(entry_point_command);
ep->entryoff = _file.entryAddress - _seg1addr;
- ep->stacksize = 0;
+ ep->stacksize = _file.stackSize;
if (_swap)
swapStruct(*ep);
lc += sizeof(entry_point_command);
@@ -856,7 +854,7 @@ std::error_code MachOFileLayout::writeLoadCommands() {
// Add LC_RPATH
for (const StringRef &path : _file.rpaths) {
rpath_command *rpc = reinterpret_cast<rpath_command *>(lc);
- uint32_t size = sizeof(rpath_command) + pointerAlign(path.size()+1);
+ uint32_t size = pointerAlign(sizeof(rpath_command) + path.size() + 1);
rpc->cmd = LC_RPATH;
rpc->cmdsize = size;
rpc->path = sizeof(rpath_command); // offset
@@ -882,11 +880,10 @@ std::error_code MachOFileLayout::writeLoadCommands() {
return ec;
}
-
void MachOFileLayout::writeSectionContent() {
for (const Section &s : _file.sections) {
// Copy all section content to output buffer.
- if (s.type == llvm::MachO::S_ZEROFILL)
+ if (isZeroFillSection(s.type))
continue;
if (s.content.empty())
continue;
@@ -909,7 +906,6 @@ void MachOFileLayout::writeRelocations() {
}
}
-
void MachOFileLayout::appendSymbols(const std::vector<Symbol> &symbols,
uint32_t &symOffset, uint32_t &strOffset) {
for (const Symbol &sym : symbols) {
@@ -1043,7 +1039,12 @@ void MachOFileLayout::buildBindInfo() {
_bindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
| entry.segIndex);
_bindingInfo.append_uleb128(entry.segOffset);
- _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
+ if (entry.ordinal > 0)
+ _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
+ (entry.ordinal & 0xF));
+ else
+ _bindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
+ (entry.ordinal & 0xF));
_bindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
_bindingInfo.append_string(entry.symbolName);
if (entry.addend != lastAddend) {
@@ -1063,7 +1064,12 @@ void MachOFileLayout::buildLazyBindInfo() {
_lazyBindingInfo.append_byte(BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB
| entry.segIndex);
_lazyBindingInfo.append_uleb128Fixed(entry.segOffset, 5);
- _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM | entry.ordinal);
+ if (entry.ordinal > 0)
+ _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_ORDINAL_IMM |
+ (entry.ordinal & 0xF));
+ else
+ _lazyBindingInfo.append_byte(BIND_OPCODE_SET_DYLIB_SPECIAL_IMM |
+ (entry.ordinal & 0xF));
_lazyBindingInfo.append_byte(BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM);
_lazyBindingInfo.append_string(entry.symbolName);
_lazyBindingInfo.append_byte(BIND_OPCODE_DO_BIND);
@@ -1090,7 +1096,7 @@ void MachOFileLayout::TrieNode::addSymbol(const Export& entry,
// Splice in new node: was A -> C, now A -> B -> C
StringRef bNodeStr = edge._child->_cummulativeString;
bNodeStr = bNodeStr.drop_back(edgeStr.size()-n).copy(allocator);
- TrieNode* bNode = new (allocator) TrieNode(bNodeStr);
+ auto *bNode = new (allocator) TrieNode(bNodeStr);
allNodes.push_back(bNode);
TrieNode* cNode = edge._child;
StringRef abEdgeStr = edgeStr.substr(0,n).copy(allocator);
@@ -1103,7 +1109,7 @@ void MachOFileLayout::TrieNode::addSymbol(const Export& entry,
TrieEdge& abEdge = edge;
abEdge._subString = abEdgeStr;
abEdge._child = bNode;
- TrieEdge *bcEdge = new (allocator) TrieEdge(bcEdgeStr, cNode);
+ auto *bcEdge = new (allocator) TrieEdge(bcEdgeStr, cNode);
bNode->_children.push_back(std::move(*bcEdge));
bNode->addSymbol(entry, allocator, allNodes);
return;
@@ -1117,8 +1123,8 @@ void MachOFileLayout::TrieNode::addSymbol(const Export& entry,
assert(entry.otherOffset != 0);
}
// No commonality with any existing child, make a new edge.
- TrieNode* newNode = new (allocator) TrieNode(entry.name.copy(allocator));
- TrieEdge *newEdge = new (allocator) TrieEdge(partialStr, newNode);
+ auto *newNode = new (allocator) TrieNode(entry.name.copy(allocator));
+ auto *newEdge = new (allocator) TrieEdge(partialStr, newNode);
_children.push_back(std::move(*newEdge));
DEBUG_WITH_TYPE("trie-builder", llvm::dbgs()
<< "new TrieNode('" << entry.name << "') with edge '"
@@ -1230,7 +1236,7 @@ void MachOFileLayout::buildExportTrie() {
BumpPtrAllocator allocator;
// Build trie of all exported symbols.
- TrieNode* rootNode = new (allocator) TrieNode(StringRef());
+ auto *rootNode = new (allocator) TrieNode(StringRef());
std::vector<TrieNode*> allNodes;
allNodes.reserve(_file.exportInfo.size()*2);
allNodes.push_back(rootNode);
@@ -1257,14 +1263,13 @@ void MachOFileLayout::buildExportTrie() {
_exportTrie.align(_is64 ? 8 : 4);
}
-
void MachOFileLayout::computeSymbolTableSizes() {
// MachO symbol tables have three ranges: locals, globals, and undefines
const size_t nlistSize = (_is64 ? sizeof(nlist_64) : sizeof(nlist));
_symbolTableSize = nlistSize * (_file.localSymbols.size()
+ _file.globalSymbols.size()
+ _file.undefinedSymbols.size());
- _symbolStringPoolSize = 0;
+ _symbolStringPoolSize = 1; // Always reserve 1-byte for the empty string.
for (const Symbol &sym : _file.localSymbols) {
_symbolStringPoolSize += (sym.name.size()+1);
}
@@ -1310,19 +1315,18 @@ std::error_code MachOFileLayout::writeBinary(StringRef path) {
if (_ec)
return _ec;
// Create FileOutputBuffer with calculated size.
- std::unique_ptr<llvm::FileOutputBuffer> fob;
unsigned flags = 0;
if (_file.fileType != llvm::MachO::MH_OBJECT)
flags = llvm::FileOutputBuffer::F_executable;
- std::error_code ec;
- ec = llvm::FileOutputBuffer::create(path, size(), fob, flags);
- if (ec)
+ ErrorOr<std::unique_ptr<llvm::FileOutputBuffer>> fobOrErr =
+ llvm::FileOutputBuffer::create(path, size(), flags);
+ if (std::error_code ec = fobOrErr.getError())
return ec;
-
+ std::unique_ptr<llvm::FileOutputBuffer> &fob = *fobOrErr;
// Write content.
_buffer = fob->getBufferStart();
writeMachHeader();
- ec = writeLoadCommands();
+ std::error_code ec = writeLoadCommands();
if (ec)
return ec;
writeSectionContent();
@@ -1332,15 +1336,12 @@ std::error_code MachOFileLayout::writeBinary(StringRef path) {
return std::error_code();
}
-
/// Takes in-memory normalized view and writes a mach-o object file.
std::error_code writeBinary(const NormalizedFile &file, StringRef path) {
MachOFileLayout layout(file);
return layout.writeBinary(path);
}
-
} // namespace normalized
} // namespace mach_o
} // namespace lld
-
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
index 4d6183f71df7..f80e2ac467fc 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp
@@ -58,7 +58,7 @@ struct SectionInfo {
uint32_t attributes;
uint64_t address;
uint64_t size;
- uint32_t alignment;
+ uint16_t alignment;
std::vector<AtomInfo> atomsAndOffsets;
uint32_t normalizedSectionIndex;
uint32_t finalSectionIndex;
@@ -67,9 +67,9 @@ struct SectionInfo {
SectionInfo::SectionInfo(StringRef sg, StringRef sct, SectionType t,
const MachOLinkingContext &ctxt, uint32_t attrs)
: segmentName(sg), sectionName(sct), type(t), attributes(attrs),
- address(0), size(0), alignment(0),
+ address(0), size(0), alignment(1),
normalizedSectionIndex(0), finalSectionIndex(0) {
- uint8_t align;
+ uint16_t align = 1;
if (ctxt.sectionAligned(segmentName, sectionName, align)) {
alignment = align;
}
@@ -90,11 +90,11 @@ SegmentInfo::SegmentInfo(StringRef n)
: name(n), address(0), size(0), access(0), normalizedSegmentIndex(0) {
}
-
class Util {
public:
Util(const MachOLinkingContext &ctxt)
- : _context(ctxt), _archHandler(ctxt.archHandler()), _entryAtom(nullptr) {}
+ : _ctx(ctxt), _archHandler(ctxt.archHandler()), _entryAtom(nullptr),
+ _hasTLVDescriptors(false) {}
~Util();
void assignAtomsToSections(const lld::File &atomFile);
@@ -142,7 +142,6 @@ private:
void appendSection(SectionInfo *si, NormalizedFile &file);
uint32_t sectionIndexForAtom(const Atom *atom);
- static uint64_t alignTo(uint64_t value, uint8_t align2);
typedef llvm::DenseMap<const Atom*, uint32_t> AtomToIndex;
struct AtomAndIndex { const Atom *atom; uint32_t index; SymbolScope scope; };
struct AtomSorter {
@@ -157,7 +156,7 @@ private:
static unsigned weight(const SectionInfo *);
};
- const MachOLinkingContext &_context;
+ const MachOLinkingContext &_ctx;
mach_o::ArchHandler &_archHandler;
llvm::BumpPtrAllocator _allocator;
std::vector<SectionInfo*> _sectionInfos;
@@ -169,6 +168,7 @@ private:
const DefinedAtom *_entryAtom;
AtomToIndex _atomToSymbolIndex;
std::vector<const Atom *> _machHeaderAliasAtoms;
+ bool _hasTLVDescriptors;
};
Util::~Util() {
@@ -206,9 +206,8 @@ SectionInfo *Util::getRelocatableSection(DefinedAtom::ContentType type) {
}
}
// Otherwise allocate new SectionInfo object.
- SectionInfo *sect = new (_allocator) SectionInfo(segmentName, sectionName,
- sectionType, _context,
- sectionAttrs);
+ auto *sect = new (_allocator)
+ SectionInfo(segmentName, sectionName, sectionType, _ctx, sectionAttrs);
_sectionInfos.push_back(sect);
_sectionMap[type] = sect;
return sect;
@@ -248,12 +247,19 @@ const MachOFinalSectionFromAtomType sectsToAtomType[] = {
typeTerminatorPtr),
ENTRY("__DATA", "__got", S_NON_LAZY_SYMBOL_POINTERS,
typeGOT),
+ ENTRY("__DATA", "__thread_vars", S_THREAD_LOCAL_VARIABLES,
+ typeThunkTLV),
+ ENTRY("__DATA", "__thread_data", S_THREAD_LOCAL_REGULAR,
+ typeTLVInitialData),
+ ENTRY("__DATA", "__thread_ptrs", S_THREAD_LOCAL_VARIABLE_POINTERS,
+ typeTLVInitializerPtr),
+ ENTRY("__DATA", "__thread_bss", S_THREAD_LOCAL_ZEROFILL,
+ typeTLVInitialZeroFill),
ENTRY("__DATA", "__bss", S_ZEROFILL, typeZeroFill),
ENTRY("__DATA", "__interposing", S_INTERPOSING, typeInterposingTuples),
};
#undef ENTRY
-
SectionInfo *Util::getFinalSection(DefinedAtom::ContentType atomType) {
for (auto &p : sectsToAtomType) {
if (p.atomType != atomType)
@@ -265,6 +271,9 @@ SectionInfo *Util::getFinalSection(DefinedAtom::ContentType atomType) {
case DefinedAtom::typeStubHelper:
sectionAttrs = S_ATTR_PURE_INSTRUCTIONS;
break;
+ case DefinedAtom::typeThunkTLV:
+ _hasTLVDescriptors = true;
+ break;
default:
break;
}
@@ -277,11 +286,8 @@ SectionInfo *Util::getFinalSection(DefinedAtom::ContentType atomType) {
}
}
// Otherwise allocate new SectionInfo object.
- SectionInfo *sect = new (_allocator) SectionInfo(p.segmentName,
- p.sectionName,
- p.sectionType,
- _context,
- sectionAttrs);
+ auto *sect = new (_allocator) SectionInfo(
+ p.segmentName, p.sectionName, p.sectionType, _ctx, sectionAttrs);
_sectionInfos.push_back(sect);
_sectionMap[atomType] = sect;
return sect;
@@ -289,8 +295,6 @@ SectionInfo *Util::getFinalSection(DefinedAtom::ContentType atomType) {
llvm_unreachable("content type not yet supported");
}
-
-
SectionInfo *Util::sectionForAtom(const DefinedAtom *atom) {
if (atom->sectionChoice() == DefinedAtom::sectionBasedOnContent) {
// Section for this atom is derived from content type.
@@ -298,7 +302,7 @@ SectionInfo *Util::sectionForAtom(const DefinedAtom *atom) {
auto pos = _sectionMap.find(type);
if ( pos != _sectionMap.end() )
return pos->second;
- bool rMode = (_context.outputMachOType() == llvm::MachO::MH_OBJECT);
+ bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
return rMode ? getRelocatableSection(type) : getFinalSection(type);
} else {
// This atom needs to be in a custom section.
@@ -315,31 +319,30 @@ SectionInfo *Util::sectionForAtom(const DefinedAtom *atom) {
assert(seperatorIndex != StringRef::npos);
StringRef segName = customName.slice(0, seperatorIndex);
StringRef sectName = customName.drop_front(seperatorIndex + 1);
- SectionInfo *sect = new (_allocator) SectionInfo(segName, sectName,
- S_REGULAR, _context);
+ auto *sect =
+ new (_allocator) SectionInfo(segName, sectName, S_REGULAR, _ctx);
_customSections.push_back(sect);
_sectionInfos.push_back(sect);
return sect;
}
}
-
void Util::appendAtom(SectionInfo *sect, const DefinedAtom *atom) {
// Figure out offset for atom in this section given alignment constraints.
uint64_t offset = sect->size;
DefinedAtom::Alignment atomAlign = atom->alignment();
- uint64_t align2 = 1 << atomAlign.powerOf2;
+ uint64_t align = atomAlign.value;
uint64_t requiredModulus = atomAlign.modulus;
- uint64_t currentModulus = (offset % align2);
+ uint64_t currentModulus = (offset % align);
if ( currentModulus != requiredModulus ) {
if ( requiredModulus > currentModulus )
offset += requiredModulus-currentModulus;
else
- offset += align2+requiredModulus-currentModulus;
+ offset += align+requiredModulus-currentModulus;
}
// Record max alignment of any atom in this section.
- if ( atomAlign.powerOf2 > sect->alignment )
- sect->alignment = atomAlign.powerOf2;
+ if (align > sect->alignment)
+ sect->alignment = atomAlign.value;
// Assign atom to this section with this offset.
AtomInfo ai = {atom, offset};
sect->atomsAndOffsets.push_back(ai);
@@ -361,7 +364,7 @@ SegmentInfo *Util::segmentForName(StringRef segName) {
if ( si->name.equals(segName) )
return si;
}
- SegmentInfo *info = new (_allocator) SegmentInfo(segName);
+ auto *info = new (_allocator) SegmentInfo(segName);
if (segName.equals("__TEXT"))
info->access = VM_PROT_READ | VM_PROT_EXECUTE;
else if (segName.equals("__DATA"))
@@ -402,16 +405,15 @@ bool Util::TextSectionSorter::operator()(const SectionInfo *left,
return (weight(left) < weight(right));
}
-
void Util::organizeSections() {
- if (_context.outputMachOType() == llvm::MachO::MH_OBJECT) {
+ if (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT) {
// Leave sections ordered as normalized file specified.
uint32_t sectionIndex = 1;
for (SectionInfo *si : _sectionInfos) {
si->finalSectionIndex = sectionIndex++;
}
} else {
- switch (_context.outputMachOType()){
+ switch (_ctx.outputMachOType()) {
case llvm::MachO::MH_EXECUTE:
// Main executables, need a zero-page segment
segmentForName("__PAGEZERO");
@@ -450,24 +452,17 @@ void Util::organizeSections() {
}
}
}
-
}
-uint64_t Util::alignTo(uint64_t value, uint8_t align2) {
- return llvm::RoundUpToAlignment(value, 1 << align2);
-}
-
-
void Util::layoutSectionsInSegment(SegmentInfo *seg, uint64_t &addr) {
seg->address = addr;
for (SectionInfo *sect : seg->sections) {
- sect->address = alignTo(addr, sect->alignment);
+ sect->address = llvm::RoundUpToAlignment(addr, sect->alignment);
addr = sect->address + sect->size;
}
- seg->size = llvm::RoundUpToAlignment(addr - seg->address,_context.pageSize());
+ seg->size = llvm::RoundUpToAlignment(addr - seg->address, _ctx.pageSize());
}
-
// __TEXT segment lays out backwards so padding is at front after load commands.
void Util::layoutSectionsInTextSegment(size_t hlcSize, SegmentInfo *seg,
uint64_t &addr) {
@@ -477,39 +472,38 @@ void Util::layoutSectionsInTextSegment(size_t hlcSize, SegmentInfo *seg,
for (auto it = seg->sections.rbegin(); it != seg->sections.rend(); ++it) {
SectionInfo *sect = *it;
taddr -= sect->size;
- taddr = taddr & (0 - (1 << sect->alignment));
+ taddr = taddr & (0 - sect->alignment);
}
int64_t padding = taddr - hlcSize;
while (padding < 0)
- padding += _context.pageSize();
+ padding += _ctx.pageSize();
// Start assigning section address starting at padded offset.
addr += (padding + hlcSize);
for (SectionInfo *sect : seg->sections) {
- sect->address = alignTo(addr, sect->alignment);
+ sect->address = llvm::RoundUpToAlignment(addr, sect->alignment);
addr = sect->address + sect->size;
}
- seg->size = llvm::RoundUpToAlignment(addr - seg->address,_context.pageSize());
+ seg->size = llvm::RoundUpToAlignment(addr - seg->address, _ctx.pageSize());
}
-
void Util::assignAddressesToSections(const NormalizedFile &file) {
size_t hlcSize = headerAndLoadCommandsSize(file);
uint64_t address = 0;
- if (_context.outputMachOType() != llvm::MachO::MH_OBJECT) {
+ if (_ctx.outputMachOType() != llvm::MachO::MH_OBJECT) {
for (SegmentInfo *seg : _segmentInfos) {
if (seg->name.equals("__PAGEZERO")) {
- seg->size = _context.pageZeroSize();
+ seg->size = _ctx.pageZeroSize();
address += seg->size;
}
else if (seg->name.equals("__TEXT")) {
- // _context.baseAddress() == 0 implies it was either unspecified or
+ // _ctx.baseAddress() == 0 implies it was either unspecified or
// pageZeroSize is also 0. In either case resetting address is safe.
- address = _context.baseAddress() ? _context.baseAddress() : address;
+ address = _ctx.baseAddress() ? _ctx.baseAddress() : address;
layoutSectionsInTextSegment(hlcSize, seg, address);
} else
layoutSectionsInSegment(seg, address);
- address = llvm::RoundUpToAlignment(address, _context.pageSize());
+ address = llvm::RoundUpToAlignment(address, _ctx.pageSize());
}
DEBUG_WITH_TYPE("WriterMachO-norm",
llvm::dbgs() << "assignAddressesToSections()\n";
@@ -528,7 +522,7 @@ void Util::assignAddressesToSections(const NormalizedFile &file) {
);
} else {
for (SectionInfo *sect : _sectionInfos) {
- sect->address = alignTo(address, sect->alignment);
+ sect->address = llvm::RoundUpToAlignment(address, sect->alignment);
address = sect->address + sect->size;
}
DEBUG_WITH_TYPE("WriterMachO-norm",
@@ -543,7 +537,6 @@ void Util::assignAddressesToSections(const NormalizedFile &file) {
}
}
-
void Util::copySegmentInfo(NormalizedFile &file) {
for (SegmentInfo *sgi : _segmentInfos) {
Segment seg;
@@ -572,7 +565,7 @@ void Util::appendSection(SectionInfo *si, NormalizedFile &file) {
}
void Util::copySectionContent(NormalizedFile &file) {
- const bool r = (_context.outputMachOType() == llvm::MachO::MH_OBJECT);
+ const bool r = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
// Utility function for ArchHandler to find address of atom in output file.
auto addrForAtom = [&] (const Atom &atom) -> uint64_t {
@@ -591,7 +584,7 @@ void Util::copySectionContent(NormalizedFile &file) {
for (SectionInfo *si : _sectionInfos) {
Section *normSect = &file.sections[si->normalizedSectionIndex];
- if (si->type == llvm::MachO::S_ZEROFILL) {
+ if (isZeroFillSection(si->type)) {
const uint8_t *empty = nullptr;
normSect->content = llvm::makeArrayRef(empty, si->size);
continue;
@@ -603,17 +596,16 @@ void Util::copySectionContent(NormalizedFile &file) {
uint8_t *atomContent = reinterpret_cast<uint8_t*>
(&sectionContent[ai.offsetInSection]);
_archHandler.generateAtomContent(*ai.atom, r, addrForAtom,
- sectionAddrForAtom,
- _context.baseAddress(), atomContent);
+ sectionAddrForAtom, _ctx.baseAddress(),
+ atomContent);
}
}
}
-
void Util::copySectionInfo(NormalizedFile &file) {
file.sections.reserve(_sectionInfos.size());
// For final linked images, write sections grouped by segment.
- if (_context.outputMachOType() != llvm::MachO::MH_OBJECT) {
+ if (_ctx.outputMachOType() != llvm::MachO::MH_OBJECT) {
for (SegmentInfo *sgi : _segmentInfos) {
for (SectionInfo *si : sgi->sections) {
appendSection(si, file);
@@ -629,7 +621,7 @@ void Util::copySectionInfo(NormalizedFile &file) {
void Util::updateSectionInfo(NormalizedFile &file) {
file.sections.reserve(_sectionInfos.size());
- if (_context.outputMachOType() != llvm::MachO::MH_OBJECT) {
+ if (_ctx.outputMachOType() != llvm::MachO::MH_OBJECT) {
// For final linked images, sections grouped by segment.
for (SegmentInfo *sgi : _segmentInfos) {
Segment *normSeg = &file.segments[sgi->normalizedSegmentIndex];
@@ -650,7 +642,7 @@ void Util::updateSectionInfo(NormalizedFile &file) {
}
void Util::copyEntryPointAddress(NormalizedFile &nFile) {
- if (_context.outputTypeHasEntry()) {
+ if (_ctx.outputTypeHasEntry()) {
if (_archHandler.isThumbFunction(*_entryAtom))
nFile.entryAddress = (_atomToAddress[_entryAtom] | 1);
else
@@ -661,13 +653,13 @@ void Util::copyEntryPointAddress(NormalizedFile &nFile) {
void Util::buildAtomToAddressMap() {
DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
<< "assign atom addresses:\n");
- const bool lookForEntry = _context.outputTypeHasEntry();
+ const bool lookForEntry = _ctx.outputTypeHasEntry();
for (SectionInfo *sect : _sectionInfos) {
for (const AtomInfo &info : sect->atomsAndOffsets) {
_atomToAddress[info.atom] = sect->address + info.offsetInSection;
if (lookForEntry && (info.atom->contentType() == DefinedAtom::typeCode) &&
(info.atom->size() != 0) &&
- info.atom->name() == _context.entrySymbolName()) {
+ info.atom->name() == _ctx.entrySymbolName()) {
_entryAtom = info.atom;
}
DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
@@ -678,7 +670,7 @@ void Util::buildAtomToAddressMap() {
}
}
for (const Atom *atom : _machHeaderAliasAtoms) {
- _atomToAddress[atom] = _context.baseAddress();
+ _atomToAddress[atom] = _ctx.baseAddress();
DEBUG_WITH_TYPE("WriterMachO-address", llvm::dbgs()
<< " address="
<< llvm::format("0x%016X", _atomToAddress[atom])
@@ -715,30 +707,28 @@ uint16_t Util::descBits(const DefinedAtom* atom) {
return desc;
}
-
bool Util::AtomSorter::operator()(const AtomAndIndex &left,
const AtomAndIndex &right) {
return (left.atom->name().compare(right.atom->name()) < 0);
}
-
std::error_code Util::getSymbolTableRegion(const DefinedAtom* atom,
bool &inGlobalsRegion,
SymbolScope &scope) {
- bool rMode = (_context.outputMachOType() == llvm::MachO::MH_OBJECT);
+ bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
switch (atom->scope()) {
case Atom::scopeTranslationUnit:
scope = 0;
inGlobalsRegion = false;
return std::error_code();
case Atom::scopeLinkageUnit:
- if ((_context.exportMode() == MachOLinkingContext::ExportMode::whiteList)
- && _context.exportSymbolNamed(atom->name())) {
+ if ((_ctx.exportMode() == MachOLinkingContext::ExportMode::whiteList) &&
+ _ctx.exportSymbolNamed(atom->name())) {
return make_dynamic_error_code(Twine("cannot export hidden symbol ")
+ atom->name());
}
if (rMode) {
- if (_context.keepPrivateExterns()) {
+ if (_ctx.keepPrivateExterns()) {
// -keep_private_externs means keep in globals region as N_PEXT.
scope = N_PEXT | N_EXT;
inGlobalsRegion = true;
@@ -750,8 +740,8 @@ std::error_code Util::getSymbolTableRegion(const DefinedAtom* atom,
inGlobalsRegion = false;
return std::error_code();
case Atom::scopeGlobal:
- if (_context.exportRestrictMode()) {
- if (_context.exportSymbolNamed(atom->name())) {
+ if (_ctx.exportRestrictMode()) {
+ if (_ctx.exportSymbolNamed(atom->name())) {
scope = N_EXT;
inGlobalsRegion = true;
return std::error_code();
@@ -772,7 +762,7 @@ std::error_code Util::getSymbolTableRegion(const DefinedAtom* atom,
std::error_code Util::addSymbols(const lld::File &atomFile,
NormalizedFile &file) {
- bool rMode = (_context.outputMachOType() == llvm::MachO::MH_OBJECT);
+ bool rMode = (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT);
// Mach-O symbol table has three regions: locals, globals, undefs.
// Add all local (non-global) symbols in address order
@@ -835,7 +825,6 @@ std::error_code Util::addSymbols(const lld::File &atomFile,
file.globalSymbols.push_back(sym);
}
-
// Sort undefined symbol alphabetically, then add to symbol table.
std::vector<AtomAndIndex> undefs;
undefs.reserve(128);
@@ -853,7 +842,9 @@ std::error_code Util::addSymbols(const lld::File &atomFile,
Symbol sym;
uint16_t desc = 0;
if (!rMode) {
- uint8_t ordinal = dylibOrdinal(dyn_cast<SharedLibraryAtom>(ai.atom));
+ uint8_t ordinal = 0;
+ if (!_ctx.useFlatNamespace())
+ ordinal = dylibOrdinal(dyn_cast<SharedLibraryAtom>(ai.atom));
llvm::MachO::SET_LIBRARY_ORDINAL(desc, ordinal);
}
sym.name = ai.atom->name();
@@ -891,7 +882,6 @@ const Atom *Util::targetOfStub(const DefinedAtom *stubAtom) {
return nullptr;
}
-
void Util::addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file) {
for (SectionInfo *si : _sectionInfos) {
Section &normSect = file.sections[si->normalizedSectionIndex];
@@ -940,7 +930,6 @@ void Util::addIndirectSymbols(const lld::File &atomFile, NormalizedFile &file) {
break;
}
}
-
}
void Util::addDependentDylibs(const lld::File &atomFile,NormalizedFile &nFile) {
@@ -951,16 +940,28 @@ void Util::addDependentDylibs(const lld::File &atomFile,NormalizedFile &nFile) {
DylibPathToInfo::iterator pos = _dylibInfo.find(loadPath);
if (pos == _dylibInfo.end()) {
DylibInfo info;
- info.ordinal = ordinal++;
+ bool flatNamespaceAtom = &slAtom->file() == _ctx.flatNamespaceFile();
+
+ // If we're in -flat_namespace mode (or this atom came from the flat
+ // namespace file under -undefined dynamic_lookup) then use the flat
+ // lookup ordinal.
+ if (flatNamespaceAtom || _ctx.useFlatNamespace())
+ info.ordinal = BIND_SPECIAL_DYLIB_FLAT_LOOKUP;
+ else
+ info.ordinal = ordinal++;
info.hasWeak = slAtom->canBeNullAtRuntime();
info.hasNonWeak = !info.hasWeak;
_dylibInfo[loadPath] = info;
- DependentDylib depInfo;
- depInfo.path = loadPath;
- depInfo.kind = llvm::MachO::LC_LOAD_DYLIB;
- depInfo.currentVersion = _context.dylibCurrentVersion(loadPath);
- depInfo.compatVersion = _context.dylibCompatVersion(loadPath);
- nFile.dependentDylibs.push_back(depInfo);
+
+ // Unless this was a flat_namespace atom, record the source dylib.
+ if (!flatNamespaceAtom) {
+ DependentDylib depInfo;
+ depInfo.path = loadPath;
+ depInfo.kind = llvm::MachO::LC_LOAD_DYLIB;
+ depInfo.currentVersion = _ctx.dylibCurrentVersion(loadPath);
+ depInfo.compatVersion = _ctx.dylibCompatVersion(loadPath);
+ nFile.dependentDylibs.push_back(depInfo);
+ }
} else {
if ( slAtom->canBeNullAtRuntime() )
pos->second.hasWeak = true;
@@ -973,12 +974,11 @@ void Util::addDependentDylibs(const lld::File &atomFile,NormalizedFile &nFile) {
DylibInfo &info = _dylibInfo[dep.path];
if (info.hasWeak && !info.hasNonWeak)
dep.kind = llvm::MachO::LC_LOAD_WEAK_DYLIB;
- else if (_context.isUpwardDylib(dep.path))
+ else if (_ctx.isUpwardDylib(dep.path))
dep.kind = llvm::MachO::LC_LOAD_UPWARD_DYLIB;
}
}
-
int Util::dylibOrdinal(const SharedLibraryAtom *sa) {
return _dylibInfo[sa->loadName()].ordinal;
}
@@ -997,7 +997,6 @@ void Util::segIndexForSection(const SectionInfo *sect, uint8_t &segmentIndex,
llvm_unreachable("section not in any segment");
}
-
uint32_t Util::sectionIndexForAtom(const Atom *atom) {
uint64_t address = _atomToAddress[atom];
uint32_t index = 1;
@@ -1010,10 +1009,9 @@ uint32_t Util::sectionIndexForAtom(const Atom *atom) {
}
void Util::addSectionRelocs(const lld::File &, NormalizedFile &file) {
- if (_context.outputMachOType() != llvm::MachO::MH_OBJECT)
+ if (_ctx.outputMachOType() != llvm::MachO::MH_OBJECT)
return;
-
// Utility function for ArchHandler to find symbol index for an atom.
auto symIndexForAtom = [&] (const Atom &atom) -> uint32_t {
auto pos = _atomToSymbolIndex.find(&atom);
@@ -1090,7 +1088,7 @@ void Util::buildDataInCodeArray(const lld::File &, NormalizedFile &file) {
void Util::addRebaseAndBindingInfo(const lld::File &atomFile,
NormalizedFile &nFile) {
- if (_context.outputMachOType() == llvm::MachO::MH_OBJECT)
+ if (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT)
return;
uint8_t segmentIndex;
@@ -1146,7 +1144,7 @@ void Util::addRebaseAndBindingInfo(const lld::File &atomFile,
}
void Util::addExportInfo(const lld::File &atomFile, NormalizedFile &nFile) {
- if (_context.outputMachOType() == llvm::MachO::MH_OBJECT)
+ if (_ctx.outputMachOType() == llvm::MachO::MH_OBJECT)
return;
for (SectionInfo *sect : _sectionInfos) {
@@ -1154,13 +1152,13 @@ void Util::addExportInfo(const lld::File &atomFile, NormalizedFile &nFile) {
const DefinedAtom *atom = info.atom;
if (atom->scope() != Atom::scopeGlobal)
continue;
- if (_context.exportRestrictMode()) {
- if (!_context.exportSymbolNamed(atom->name()))
+ if (_ctx.exportRestrictMode()) {
+ if (!_ctx.exportSymbolNamed(atom->name()))
continue;
}
Export exprt;
exprt.name = atom->name();
- exprt.offset = _atomToAddress[atom]; // FIXME: subtract base address
+ exprt.offset = _atomToAddress[atom] - _ctx.baseAddress();
exprt.kind = EXPORT_SYMBOL_FLAGS_KIND_REGULAR;
if (atom->merge() == DefinedAtom::mergeAsWeak)
exprt.flags = EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
@@ -1175,19 +1173,22 @@ void Util::addExportInfo(const lld::File &atomFile, NormalizedFile &nFile) {
uint32_t Util::fileFlags() {
// FIXME: these need to determined at runtime.
- if (_context.outputMachOType() == MH_OBJECT) {
+ if (_ctx.outputMachOType() == MH_OBJECT) {
return MH_SUBSECTIONS_VIA_SYMBOLS;
} else {
- if ((_context.outputMachOType() == MH_EXECUTE) && _context.PIE())
- return MH_DYLDLINK | MH_NOUNDEFS | MH_TWOLEVEL | MH_PIE;
- else
- return MH_DYLDLINK | MH_NOUNDEFS | MH_TWOLEVEL;
+ uint32_t flags = MH_DYLDLINK;
+ if (!_ctx.useFlatNamespace())
+ flags |= MH_TWOLEVEL | MH_NOUNDEFS;
+ if ((_ctx.outputMachOType() == MH_EXECUTE) && _ctx.PIE())
+ flags |= MH_PIE;
+ if (_hasTLVDescriptors)
+ flags |= (MH_PIE | MH_HAS_TLV_DESCRIPTORS);
+ return flags;
}
}
} // end anonymous namespace
-
namespace lld {
namespace mach_o {
namespace normalized {
@@ -1206,6 +1207,7 @@ normalizedFromAtoms(const lld::File &atomFile,
normFile.arch = context.arch();
normFile.fileType = context.outputMachOType();
normFile.flags = util.fileFlags();
+ normFile.stackSize = context.stackSize();
normFile.installName = context.installName();
normFile.currentVersion = context.currentVersion();
normFile.compatVersion = context.compatibilityVersion();
@@ -1231,8 +1233,6 @@ normalizedFromAtoms(const lld::File &atomFile,
return std::move(f);
}
-
} // namespace normalized
} // namespace mach_o
} // namespace lld
-
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
index 124e0eaffeeb..1c4bb1d4f6a3 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp
@@ -27,12 +27,17 @@
#include "MachONormalizedFileBinaryUtils.h"
#include "lld/Core/Error.h"
#include "lld/Core/LLVM.h"
+#include "llvm/Support/Debug.h"
#include "llvm/Support/Format.h"
#include "llvm/Support/MachO.h"
+#include "llvm/Support/LEB128.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm::MachO;
using namespace lld::mach_o::normalized;
+#define DEBUG_TYPE "normalized-file-to-atoms"
+
namespace lld {
namespace mach_o {
@@ -78,6 +83,11 @@ const MachORelocatableSectionToAtomType sectsToAtomType[] = {
ENTRY("", "", S_NON_LAZY_SYMBOL_POINTERS,
typeGOT),
ENTRY("__DATA", "__interposing", S_INTERPOSING, typeInterposingTuples),
+ ENTRY("__DATA", "__thread_vars", S_THREAD_LOCAL_VARIABLES,
+ typeThunkTLV),
+ ENTRY("__DATA", "__thread_data", S_THREAD_LOCAL_REGULAR, typeTLVInitialData),
+ ENTRY("__DATA", "__thread_bss", S_THREAD_LOCAL_ZEROFILL,
+ typeTLVInitialZeroFill),
ENTRY("", "", S_INTERPOSING, typeInterposingTuples),
ENTRY("__LD", "__compact_unwind", S_REGULAR,
typeCompactUnwindInfo),
@@ -228,7 +238,7 @@ void atomFromSymbol(DefinedAtom::ContentType atomType, const Section &section,
uint64_t size = nextSymbolAddr - symbolAddr;
uint64_t offset = symbolAddr - section.address;
bool noDeadStrip = (symbolDescFlags & N_NO_DEAD_STRIP) || !scatterable;
- if (section.type == llvm::MachO::S_ZEROFILL) {
+ if (isZeroFillSection(section.type)) {
file.addZeroFillDefinedAtom(symbolName, symbolScope, offset, size,
noDeadStrip, copyRefs, &section);
} else {
@@ -558,17 +568,17 @@ std::error_code convertRelocs(const Section &section,
*result = target;
return std::error_code();
}
- return make_dynamic_error_code(Twine("no atom found for defined symbol"));
+ return make_dynamic_error_code("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 make_dynamic_error_code(Twine("no undefined atom found for sym"));
+ return make_dynamic_error_code("no undefined atom found for sym");
} else {
// Search undefs
- return make_dynamic_error_code(Twine("no atom found for symbol"));
+ return make_dynamic_error_code("no atom found for symbol");
}
};
@@ -594,10 +604,37 @@ std::error_code convertRelocs(const Section &section,
Reference::KindValue kind;
std::error_code relocErr;
if (handler.isPairedReloc(reloc)) {
- // Handle paired relocations together.
+ // Handle paired relocations together.
+ const Relocation &reloc2 = *++it;
relocErr = handler.getPairReferenceInfo(
- reloc, *++it, inAtom, offsetInAtom, fixupAddress, isBig, scatterable,
+ 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)))
+ + ")" );
+ }
}
else {
// Use ArchHandler to convert relocation record into information
@@ -605,26 +642,25 @@ std::error_code convertRelocs(const Section &section,
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)))
+ + ")" );
+ }
}
- 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)))
- + ")" );
- } else {
- // Instantiate an lld::Reference object and add to its atom.
- inAtom->addReference(offsetInAtom, kind, target, addend,
- handler.kindArch());
- }
+ // Instantiate an lld::Reference object and add to its atom.
+ inAtom->addReference(offsetInAtom, kind, target, addend,
+ handler.kindArch());
}
return std::error_code();
@@ -644,11 +680,158 @@ static int64_t readSPtr(bool is64, bool isBig, const uint8_t *addr) {
return res;
}
+/// --- Augmentation String Processing ---
+
+struct CIEInfo {
+ bool _augmentationDataPresent = false;
+ bool _mayHaveLSDA = false;
+};
+
+typedef llvm::DenseMap<const MachODefinedAtom*, CIEInfo> CIEInfoMap;
+
+static std::error_code processAugmentationString(const uint8_t *augStr,
+ CIEInfo &cieInfo,
+ unsigned *len = nullptr) {
+
+ if (augStr[0] == '\0') {
+ if (len)
+ *len = 1;
+ return std::error_code();
+ }
+
+ if (augStr[0] != 'z')
+ return make_dynamic_error_code("expected 'z' at start of augmentation "
+ "string");
+
+ cieInfo._augmentationDataPresent = true;
+ uint64_t idx = 1;
+
+ while (augStr[idx] != '\0') {
+ if (augStr[idx] == 'L') {
+ cieInfo._mayHaveLSDA = true;
+ ++idx;
+ } else
+ ++idx;
+ }
+
+ if (len)
+ *len = idx + 1;
+ return std::error_code();
+}
+
+static std::error_code processCIE(const NormalizedFile &normalizedFile,
+ MachODefinedAtom *atom,
+ CIEInfoMap &cieInfos) {
+ const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
+ const uint8_t *frameData = atom->rawContent().data();
+
+ CIEInfo cieInfo;
+
+ uint32_t size = read32(frameData, isBig);
+ uint64_t cieIDField = size == 0xffffffffU
+ ? sizeof(uint32_t) + sizeof(uint64_t)
+ : sizeof(uint32_t);
+ uint64_t versionField = cieIDField + sizeof(uint32_t);
+ uint64_t augmentationStringField = versionField + sizeof(uint8_t);
+
+ if (auto err = processAugmentationString(frameData + augmentationStringField,
+ cieInfo))
+ return err;
+
+ cieInfos[atom] = std::move(cieInfo);
+
+ return std::error_code();
+}
+
+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) {
+
+ 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.
+ if (atom->begin() != atom->end())
+ return std::error_code();
+
+ const uint8_t *frameData = atom->rawContent().data();
+ uint32_t size = read32(frameData, isBig);
+ uint64_t cieFieldInFDE = size == 0xffffffffU
+ ? sizeof(uint32_t) + sizeof(uint64_t)
+ : sizeof(uint32_t);
+
+ // Linker needs to fixup a reference from the FDE to its parent CIE (a
+ // 32-bit byte offset backwards in the __eh_frame section).
+ uint32_t cieDelta = read32(frameData + cieFieldInFDE, isBig);
+ 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 &&
+ "FDE's CIE field does not point at the start of a CIE.");
+
+ const CIEInfo &cieInfo = cieInfos.find(cie)->second;
+
+ // Linker needs to fixup reference from the FDE to the function it's
+ // describing. FIXME: there are actually different ways to do this, and the
+ // particular method used is specified in the CIE's augmentation fields
+ // (hopefully)
+ uint64_t rangeFieldInFDE = cieFieldInFDE + sizeof(uint32_t);
+
+ int64_t functionFromFDE = readSPtr(is64, isBig,
+ frameData + rangeFieldInFDE);
+ 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());
+
+ // Handle the augmentation data if there is any.
+ if (cieInfo._augmentationDataPresent) {
+ // First process the augmentation data length field.
+ uint64_t augmentationDataLengthFieldInFDE =
+ rangeFieldInFDE + 2 * (is64 ? sizeof(uint64_t) : sizeof(uint32_t));
+ unsigned lengthFieldSize = 0;
+ uint64_t augmentationDataLength =
+ llvm::decodeULEB128(frameData + augmentationDataLengthFieldInFDE,
+ &lengthFieldSize);
+
+ if (cieInfo._mayHaveLSDA && augmentationDataLength > 0) {
+
+ // Look at the augmentation data field.
+ uint64_t augmentationDataFieldInFDE =
+ augmentationDataLengthFieldInFDE + lengthFieldSize;
+
+ int64_t lsdaFromFDE = readSPtr(is64, isBig,
+ frameData + augmentationDataFieldInFDE);
+ 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());
+ }
+ }
+
+ return std::error_code();
+}
+
std::error_code addEHFrameReferences(const NormalizedFile &normalizedFile,
MachOFile &file,
mach_o::ArchHandler &handler) {
- const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
- const bool is64 = MachOLinkingContext::is64Bit(normalizedFile.arch);
const Section *ehFrameSection = nullptr;
for (auto &section : normalizedFile.sections)
@@ -662,51 +845,26 @@ std::error_code addEHFrameReferences(const NormalizedFile &normalizedFile,
if (!ehFrameSection)
return std::error_code();
+ std::error_code ehFrameErr;
+ CIEInfoMap cieInfos;
+
file.eachAtomInSection(*ehFrameSection,
[&](MachODefinedAtom *atom, uint64_t offset) -> void {
assert(atom->contentType() == DefinedAtom::typeCFI);
- if (ArchHandler::isDwarfCIE(isBig, atom))
+ // Bail out if we've encountered an error.
+ if (ehFrameErr)
return;
- // Compiler wasn't lazy and actually told us what it meant.
- if (atom->begin() != atom->end())
- return;
-
- const uint8_t *frameData = atom->rawContent().data();
- uint32_t size = read32(frameData, isBig);
- uint64_t cieFieldInFDE = size == 0xffffffffU
- ? sizeof(uint32_t) + sizeof(uint64_t)
- : sizeof(uint32_t);
-
- // Linker needs to fixup a reference from the FDE to its parent CIE (a
- // 32-bit byte offset backwards in the __eh_frame section).
- uint32_t cieDelta = read32(frameData + cieFieldInFDE, isBig);
- uint64_t cieAddress = ehFrameSection->address + offset + cieFieldInFDE;
- cieAddress -= cieDelta;
-
- Reference::Addend addend;
- const Atom *cie =
- findAtomCoveringAddress(normalizedFile, file, cieAddress, &addend);
- atom->addReference(cieFieldInFDE, handler.unwindRefToCIEKind(), cie,
- addend, handler.kindArch());
-
- // Linker needs to fixup reference from the FDE to the function it's
- // describing. FIXME: there are actually different ways to do this, and the
- // particular method used is specified in the CIE's augmentation fields
- // (hopefully)
- uint64_t rangeFieldInFDE = cieFieldInFDE + sizeof(uint32_t);
-
- int64_t functionFromFDE = readSPtr(is64, isBig, frameData + rangeFieldInFDE);
- 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());
+ const bool isBig = MachOLinkingContext::isBigEndian(normalizedFile.arch);
+ if (ArchHandler::isDwarfCIE(isBig, atom))
+ ehFrameErr = processCIE(normalizedFile, atom, cieInfos);
+ else
+ ehFrameErr = processFDE(normalizedFile, file, handler, ehFrameSection,
+ atom, offset, cieInfos);
});
- return std::error_code();
+
+ return ehFrameErr;
}
@@ -738,10 +896,13 @@ std::error_code
normalizedObjectToAtoms(MachOFile *file,
const NormalizedFile &normalizedFile,
bool copyRefs) {
+ DEBUG(llvm::dbgs() << "******** Normalizing file to atoms: "
+ << file->path() << "\n");
bool scatterable = ((normalizedFile.flags & MH_SUBSECTIONS_VIA_SYMBOLS) != 0);
// Create atoms from each section.
for (auto &sect : normalizedFile.sections) {
+ DEBUG(llvm::dbgs() << "Creating atoms: "; sect.dump());
if (isDebugInfoSection(sect))
continue;
bool customSectionName;
@@ -759,7 +920,8 @@ normalizedObjectToAtoms(MachOFile *file,
file->addUndefinedAtom(sym.name, copyRefs);
} else {
file->addTentativeDefAtom(sym.name, atomScope(sym.scope), sym.value,
- DefinedAtom::Alignment(sym.desc >> 8), copyRefs);
+ DefinedAtom::Alignment(1 << (sym.desc >> 8)),
+ copyRefs);
}
}
@@ -906,6 +1068,14 @@ normalizedToAtoms(const NormalizedFile &normalizedFile, StringRef path,
}
}
+#ifndef NDEBUG
+void Section::dump(llvm::raw_ostream &OS) const {
+ OS << "Section (\"" << segmentName << ", " << sectionName << "\"";
+ OS << ", addr: " << llvm::format_hex(address, 16, true);
+ OS << ", size: " << llvm::format_hex(content.size(), 8, true) << ")\n";
+}
+#endif
+
} // namespace normalized
} // namespace mach_o
} // namespace lld
diff --git a/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp b/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
index ae14d755e2b9..0b92a68eeae8 100644
--- a/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
+++ b/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp
@@ -276,9 +276,9 @@ struct MappingTraits<Section> {
io.mapRequired("section", sect.sectionName);
io.mapRequired("type", sect.type);
io.mapOptional("attributes", sect.attributes);
- io.mapOptional("alignment", sect.alignment, 0U);
+ io.mapOptional("alignment", sect.alignment, (uint16_t)1);
io.mapRequired("address", sect.address);
- if (sect.type == llvm::MachO::S_ZEROFILL) {
+ if (isZeroFillSection(sect.type)) {
// S_ZEROFILL sections use "size:" instead of "content:"
uint64_t size = sect.content.size();
io.mapOptional("size", size);
@@ -688,6 +688,7 @@ struct MappingTraits<NormalizedFile> {
io.mapOptional("has-UUID", file.hasUUID, true);
io.mapOptional("rpaths", file.rpaths);
io.mapOptional("entry-point", file.entryAddress, Hex64(0));
+ io.mapOptional("stack-size", file.stackSize, Hex64(0));
io.mapOptional("source-version", file.sourceVersion, Hex64(0));
io.mapOptional("OS", file.os);
io.mapOptional("min-os-version", file.minOSverson, PackedVersion(0));
@@ -799,4 +800,3 @@ std::error_code writeYaml(const NormalizedFile &file, raw_ostream &out) {
} // namespace normalized
} // namespace mach_o
} // namespace lld
-
diff --git a/lib/ReaderWriter/MachO/MachOPasses.h b/lib/ReaderWriter/MachO/MachOPasses.h
index 86f4bc0f5d54..a73785418d5f 100644
--- a/lib/ReaderWriter/MachO/MachOPasses.h
+++ b/lib/ReaderWriter/MachO/MachOPasses.h
@@ -19,6 +19,7 @@ namespace mach_o {
void addLayoutPass(PassManager &pm, const MachOLinkingContext &ctx);
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 addShimPass(PassManager &pm, const MachOLinkingContext &ctx);
diff --git a/lib/ReaderWriter/MachO/Makefile b/lib/ReaderWriter/MachO/Makefile
deleted file mode 100644
index 1acd578ba9d3..000000000000
--- a/lib/ReaderWriter/MachO/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-##===- lld/lib/ReaderWriter/MachO/Makefile --------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL := ../../..
-LIBRARYNAME := lldMachO
-USEDLIBS = lldCore.a
-
-include $(LLD_LEVEL)/Makefile
diff --git a/lib/ReaderWriter/MachO/SectCreateFile.h b/lib/ReaderWriter/MachO/SectCreateFile.h
new file mode 100644
index 000000000000..2e6e97c5433f
--- /dev/null
+++ b/lib/ReaderWriter/MachO/SectCreateFile.h
@@ -0,0 +1,93 @@
+//===---- lib/ReaderWriter/MachO/SectCreateFile.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_MACHO_SECTCREATE_FILE_H
+#define LLD_READER_WRITER_MACHO_SECTCREATE_FILE_H
+
+#include "lld/Core/DefinedAtom.h"
+#include "lld/Core/Simple.h"
+#include "lld/ReaderWriter/MachOLinkingContext.h"
+
+namespace lld {
+namespace mach_o {
+
+//
+// A FlateNamespaceFile instance may be added as a resolution source of last
+// resort, depending on how -flat_namespace and -undefined are set.
+//
+class SectCreateFile : public File {
+public:
+ class SectCreateAtom : public SimpleDefinedAtom {
+ public:
+ SectCreateAtom(const File &file, StringRef segName, StringRef sectName,
+ std::unique_ptr<MemoryBuffer> content)
+ : SimpleDefinedAtom(file),
+ _combinedName((segName + "/" + sectName).str()),
+ _content(std::move(content)) {}
+
+ uint64_t size() const override { return _content->getBufferSize(); }
+
+ Scope scope() const override { return scopeGlobal; }
+
+ ContentType contentType() const override { return typeSectCreate; }
+
+ SectionChoice sectionChoice() const override { return sectionCustomRequired; }
+
+ StringRef customSectionName() const override { return _combinedName; }
+
+ DeadStripKind deadStrip() const override { return deadStripNever; }
+
+ ArrayRef<uint8_t> rawContent() const override {
+ const uint8_t *data =
+ reinterpret_cast<const uint8_t*>(_content->getBufferStart());
+ return ArrayRef<uint8_t>(data, _content->getBufferSize());
+ }
+
+ StringRef segmentName() const { return _segName; }
+ StringRef sectionName() const { return _sectName; }
+
+ private:
+ std::string _combinedName;
+ StringRef _segName;
+ StringRef _sectName;
+ std::unique_ptr<MemoryBuffer> _content;
+ };
+
+ SectCreateFile() : File("sectcreate", kindObject) {}
+
+ void addSection(StringRef seg, StringRef sect,
+ std::unique_ptr<MemoryBuffer> content) {
+ _definedAtoms.push_back(
+ new (allocator()) SectCreateAtom(*this, seg, sect, std::move(content)));
+ }
+
+ const AtomVector<DefinedAtom> &defined() const override {
+ return _definedAtoms;
+ }
+
+ const AtomVector<UndefinedAtom> &undefined() const override {
+ return _noUndefinedAtoms;
+ }
+
+ const AtomVector<SharedLibraryAtom> &sharedLibrary() const override {
+ return _noSharedLibraryAtoms;
+ }
+
+ const AtomVector<AbsoluteAtom> &absolute() const override {
+ return _noAbsoluteAtoms;
+ }
+
+private:
+ AtomVector<DefinedAtom> _definedAtoms;
+};
+
+} // namespace mach_o
+} // namespace lld
+
+#endif // LLD_READER_WRITER_MACHO_SECTCREATE_FILE_H
diff --git a/lib/ReaderWriter/MachO/ShimPass.cpp b/lib/ReaderWriter/MachO/ShimPass.cpp
index a8c69f8ceace..df29e37c183b 100644
--- a/lib/ReaderWriter/MachO/ShimPass.cpp
+++ b/lib/ReaderWriter/MachO/ShimPass.cpp
@@ -41,16 +41,12 @@ namespace mach_o {
class ShimPass : public Pass {
public:
ShimPass(const MachOLinkingContext &context)
- : _context(context)
- , _archHandler(_context.archHandler())
- , _stubInfo(_archHandler.stubInfo())
- , _file("<mach-o shim pass>") {
- }
-
+ : _ctx(context), _archHandler(_ctx.archHandler()),
+ _stubInfo(_archHandler.stubInfo()), _file("<mach-o shim pass>") {}
- void perform(std::unique_ptr<MutableFile> &mergedFile) override {
+ std::error_code perform(SimpleFile &mergedFile) override {
// Scan all references in all atoms.
- for (const DefinedAtom *atom : mergedFile->defined()) {
+ for (const DefinedAtom *atom : mergedFile.defined()) {
for (const Reference *ref : *atom) {
// Look at non-call branches.
if (!_archHandler.isNonCallBranch(*ref))
@@ -67,7 +63,7 @@ public:
}
// Exit early if no shims needed.
if (_targetToShim.empty())
- return;
+ return std::error_code();
// Sort shim atoms so the layout order is stable.
std::vector<const DefinedAtom *> shims;
@@ -81,9 +77,10 @@ public:
});
// Add all shims to master file.
- for (const DefinedAtom *shim : shims) {
- mergedFile->addAtom(*shim);
- }
+ for (const DefinedAtom *shim : shims)
+ mergedFile.addAtom(*shim);
+
+ return std::error_code();
}
private:
@@ -112,7 +109,7 @@ private:
}
}
- const MachOLinkingContext &_context;
+ const MachOLinkingContext &_ctx;
mach_o::ArchHandler &_archHandler;
const ArchHandler::StubInfo &_stubInfo;
MachOFile _file;
diff --git a/lib/ReaderWriter/MachO/StubsPass.cpp b/lib/ReaderWriter/MachO/StubsPass.cpp
index bc4d9c2087f3..1f61256a5b79 100644
--- a/lib/ReaderWriter/MachO/StubsPass.cpp
+++ b/lib/ReaderWriter/MachO/StubsPass.cpp
@@ -1,4 +1,4 @@
-//===- lib/ReaderWriter/MachO/StubsPass.cpp -------------------------------===//
+//===- lib/ReaderWriter/MachO/StubsPass.cpp ---------------------*- C++ -*-===//
//
// The LLVM Linker
//
@@ -26,11 +26,9 @@
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/SmallVector.h"
-
namespace lld {
namespace mach_o {
-
//
// Lazy Pointer Atom created by the stubs pass.
//
@@ -44,7 +42,7 @@ public:
}
Alignment alignment() const override {
- return Alignment(_is64 ? 3 : 2);
+ return _is64 ? 8 : 4;
}
uint64_t size() const override {
@@ -65,7 +63,6 @@ private:
const bool _is64;
};
-
//
// NonLazyPointer (GOT) Atom created by the stubs pass.
//
@@ -79,7 +76,7 @@ public:
}
Alignment alignment() const override {
- return Alignment(_is64 ? 3 : 2);
+ return _is64 ? 8 : 4;
}
uint64_t size() const override {
@@ -100,8 +97,6 @@ private:
const bool _is64;
};
-
-
//
// Stub Atom created by the stubs pass.
//
@@ -115,7 +110,7 @@ public:
}
Alignment alignment() const override {
- return Alignment(_stubInfo.codeAlignment);
+ return 1 << _stubInfo.codeAlignment;
}
uint64_t size() const override {
@@ -134,7 +129,6 @@ private:
const ArchHandler::StubInfo &_stubInfo;
};
-
//
// Stub Helper Atom created by the stubs pass.
//
@@ -148,7 +142,7 @@ public:
}
Alignment alignment() const override {
- return Alignment(_stubInfo.codeAlignment);
+ return 1 << _stubInfo.codeAlignment;
}
uint64_t size() const override {
@@ -168,7 +162,6 @@ private:
const ArchHandler::StubInfo &_stubInfo;
};
-
//
// Stub Helper Common Atom created by the stubs pass.
//
@@ -182,7 +175,7 @@ public:
}
Alignment alignment() const override {
- return Alignment(_stubInfo.codeAlignment);
+ return 1 << _stubInfo.codeAlignment;
}
uint64_t size() const override {
@@ -202,21 +195,19 @@ private:
const ArchHandler::StubInfo &_stubInfo;
};
-
class StubsPass : public Pass {
public:
StubsPass(const MachOLinkingContext &context)
- : _context(context), _archHandler(_context.archHandler()),
- _stubInfo(_archHandler.stubInfo()), _file("<mach-o Stubs pass>") { }
+ : _ctx(context), _archHandler(_ctx.archHandler()),
+ _stubInfo(_archHandler.stubInfo()), _file("<mach-o Stubs pass>") {}
-
- void perform(std::unique_ptr<MutableFile> &mergedFile) override {
+ std::error_code perform(SimpleFile &mergedFile) override {
// Skip this pass if output format uses text relocations instead of stubs.
if (!this->noTextRelocs())
- return;
+ return std::error_code();
// Scan all references in all atoms.
- for (const DefinedAtom *atom : mergedFile->defined()) {
+ for (const DefinedAtom *atom : mergedFile.defined()) {
for (const Reference *ref : *atom) {
// Look at call-sites.
if (!this->isCallSite(*ref))
@@ -240,15 +231,15 @@ public:
// Exit early if no stubs needed.
if (_targetToUses.empty())
- return;
+ return std::error_code();
// 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, _context.is64Bit());
+ new (_file.allocator()) NonLazyPointerAtom(_file, _ctx.is64Bit());
SimpleDefinedAtom *helperBinderNLPAtom =
- new (_file.allocator()) NonLazyPointerAtom(_file, _context.is64Bit());
+ new (_file.allocator()) NonLazyPointerAtom(_file, _ctx.is64Bit());
addReference(helperCommonAtom, _stubInfo.stubHelperCommonReferenceToCache,
helperCacheNLPAtom);
addOptReference(
@@ -259,17 +250,18 @@ public:
addOptReference(
helperCommonAtom, _stubInfo.stubHelperCommonReferenceToBinder,
_stubInfo.optStubHelperCommonReferenceToBinder, helperBinderNLPAtom);
- mergedFile->addAtom(*helperCommonAtom);
- mergedFile->addAtom(*helperBinderNLPAtom);
- mergedFile->addAtom(*helperCacheNLPAtom);
+ mergedFile.addAtom(*helperCommonAtom);
+ mergedFile.addAtom(*helperBinderNLPAtom);
+ mergedFile.addAtom(*helperCacheNLPAtom);
// Add reference to dyld_stub_binder in libSystem.dylib
auto I = std::find_if(
- mergedFile->sharedLibrary().begin(), mergedFile->sharedLibrary().end(),
+ mergedFile.sharedLibrary().begin(), mergedFile.sharedLibrary().end(),
[&](const SharedLibraryAtom *atom) {
return atom->name().equals(_stubInfo.binderSymbolName);
});
- assert(I != mergedFile->sharedLibrary().end() && "dyld_stub_binder not found");
+ assert(I != mergedFile.sharedLibrary().end() &&
+ "dyld_stub_binder not found");
addReference(helperBinderNLPAtom, _stubInfo.nonLazyPointerReferenceToBinder, *I);
// Sort targets by name, so stubs and lazy pointers are consistent
@@ -284,11 +276,10 @@ public:
// Make and append stubs, lazy pointers, and helpers in alphabetical order.
unsigned lazyOffset = 0;
for (const Atom *target : targetsNeedingStubs) {
- StubAtom *stub = new (_file.allocator()) StubAtom(_file, _stubInfo);
- LazyPointerAtom *lp =
- new (_file.allocator()) LazyPointerAtom(_file, _context.is64Bit());
- StubHelperAtom *helper =
- new (_file.allocator()) StubHelperAtom(_file, _stubInfo);
+ auto *stub = new (_file.allocator()) StubAtom(_file, _stubInfo);
+ auto *lp =
+ new (_file.allocator()) LazyPointerAtom(_file, _ctx.is64Bit());
+ auto *helper = new (_file.allocator()) StubHelperAtom(_file, _stubInfo);
addReference(stub, _stubInfo.stubReferenceToLP, lp);
addOptReference(stub, _stubInfo.stubReferenceToLP,
@@ -301,9 +292,9 @@ public:
addReference(helper, _stubInfo.stubHelperReferenceToHelperCommon,
helperCommonAtom);
- mergedFile->addAtom(*stub);
- mergedFile->addAtom(*lp);
- mergedFile->addAtom(*helper);
+ mergedFile.addAtom(*stub);
+ mergedFile.addAtom(*lp);
+ mergedFile.addAtom(*helper);
// Update each reference to use stub.
for (const Reference *ref : _targetToUses[target]) {
@@ -315,10 +306,11 @@ public:
// Calculate new offset
lazyOffset += target->name().size() + 12;
}
+
+ return std::error_code();
}
private:
-
bool noTextRelocs() {
return true;
}
@@ -356,15 +348,13 @@ private:
typedef llvm::DenseMap<const Atom*,
llvm::SmallVector<const Reference *, 8>> TargetToUses;
- const MachOLinkingContext &_context;
+ const MachOLinkingContext &_ctx;
mach_o::ArchHandler &_archHandler;
const ArchHandler::StubInfo &_stubInfo;
MachOFile _file;
TargetToUses _targetToUses;
};
-
-
void addStubsPass(PassManager &pm, const MachOLinkingContext &ctx) {
pm.add(std::unique_ptr<Pass>(new StubsPass(ctx)));
}
diff --git a/lib/ReaderWriter/MachO/TLVPass.cpp b/lib/ReaderWriter/MachO/TLVPass.cpp
new file mode 100644
index 000000000000..aba222edcd27
--- /dev/null
+++ b/lib/ReaderWriter/MachO/TLVPass.cpp
@@ -0,0 +1,137 @@
+//===- lib/ReaderWriter/MachO/TLVPass.cpp -----------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file
+/// This linker pass transforms all TLV references to real references.
+///
+//===----------------------------------------------------------------------===//
+
+#include "ArchHandler.h"
+#include "File.h"
+#include "MachOPasses.h"
+#include "lld/Core/Simple.h"
+#include "llvm/ADT/STLExtras.h"
+#include "llvm/Support/Debug.h"
+
+namespace lld {
+namespace mach_o {
+
+//
+// TLVP Entry Atom created by the TLV pass.
+//
+class TLVPEntryAtom : public SimpleDefinedAtom {
+public:
+ TLVPEntryAtom(const File &file, bool is64, StringRef name)
+ : SimpleDefinedAtom(file), _is64(is64), _name(name) {}
+
+ ContentType contentType() const override {
+ return DefinedAtom::typeTLVInitializerPtr;
+ }
+
+ Alignment alignment() const override {
+ return _is64 ? 8 : 4;
+ }
+
+ uint64_t size() const override {
+ return _is64 ? 8 : 4;
+ }
+
+ ContentPermissions permissions() const override {
+ return DefinedAtom::permRW_;
+ }
+
+ ArrayRef<uint8_t> rawContent() const override {
+ static const uint8_t zeros[] =
+ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ return llvm::makeArrayRef(zeros, size());
+ }
+
+ StringRef slotName() const {
+ return _name;
+ }
+
+private:
+ const bool _is64;
+ StringRef _name;
+};
+
+class TLVPass : public Pass {
+public:
+ TLVPass(const MachOLinkingContext &context)
+ : _ctx(context), _archHandler(_ctx.archHandler()),
+ _file("<mach-o TLV Pass>") {}
+
+private:
+ std::error_code perform(SimpleFile &mergedFile) override {
+ bool allowTLV = _ctx.minOS("10.7", "1.0");
+
+ for (const DefinedAtom *atom : mergedFile.defined()) {
+ for (const Reference *ref : *atom) {
+ if (!_archHandler.isTLVAccess(*ref))
+ continue;
+
+ if (!allowTLV)
+ return make_dynamic_error_code(
+ "targeted OS version does not support use of thread local "
+ "variables in " + atom->name() + " for architecture " +
+ _ctx.archName());
+
+ const Atom *target = ref->target();
+ assert(target != nullptr);
+
+ const DefinedAtom *tlvpEntry = makeTLVPEntry(target);
+ const_cast<Reference*>(ref)->setTarget(tlvpEntry);
+ _archHandler.updateReferenceToTLV(ref);
+ }
+ }
+
+ std::vector<const TLVPEntryAtom*> entries;
+ entries.reserve(_targetToTLVP.size());
+ for (auto &it : _targetToTLVP)
+ entries.push_back(it.second);
+ std::sort(entries.begin(), entries.end(),
+ [](const TLVPEntryAtom *lhs, const TLVPEntryAtom *rhs) {
+ return (lhs->slotName().compare(rhs->slotName()) < 0);
+ });
+
+ for (const TLVPEntryAtom *slot : entries)
+ mergedFile.addAtom(*slot);
+
+ return std::error_code();
+ }
+
+ const DefinedAtom *makeTLVPEntry(const Atom *target) {
+ auto pos = _targetToTLVP.find(target);
+
+ if (pos != _targetToTLVP.end())
+ return pos->second;
+
+ auto *tlvpEntry = new (_file.allocator())
+ TLVPEntryAtom(_file, _ctx.is64Bit(), target->name());
+ _targetToTLVP[target] = tlvpEntry;
+ const ArchHandler::ReferenceInfo &nlInfo =
+ _archHandler.stubInfo().nonLazyPointerReferenceToBinder;
+ tlvpEntry->addReference(Reference::KindNamespace::mach_o, nlInfo.arch,
+ nlInfo.kind, 0, target, 0);
+ return tlvpEntry;
+ }
+
+ const MachOLinkingContext &_ctx;
+ mach_o::ArchHandler &_archHandler;
+ MachOFile _file;
+ llvm::DenseMap<const Atom*, const TLVPEntryAtom*> _targetToTLVP;
+};
+
+void addTLVPass(PassManager &pm, const MachOLinkingContext &ctx) {
+ assert(ctx.needsTLVPass());
+ pm.add(llvm::make_unique<TLVPass>(ctx));
+}
+
+} // end namesapce mach_o
+} // end namesapce lld
diff --git a/lib/ReaderWriter/MachO/WriterMachO.cpp b/lib/ReaderWriter/MachO/WriterMachO.cpp
index de1c0e38063b..cce0a179608c 100644
--- a/lib/ReaderWriter/MachO/WriterMachO.cpp
+++ b/lib/ReaderWriter/MachO/WriterMachO.cpp
@@ -7,7 +7,7 @@
//
//===----------------------------------------------------------------------===//
-#include "ExecutableAtoms.hpp"
+#include "ExecutableAtoms.h"
#include "MachONormalizedFile.h"
#include "lld/Core/File.h"
#include "lld/Core/Writer.h"
@@ -26,18 +26,18 @@ namespace mach_o {
class MachOWriter : public Writer {
public:
- MachOWriter(const MachOLinkingContext &ctxt) : _context(ctxt) { }
+ MachOWriter(const MachOLinkingContext &ctxt) : _ctx(ctxt) {}
std::error_code writeFile(const lld::File &file, StringRef path) override {
// Construct empty normalized file from atoms.
ErrorOr<std::unique_ptr<NormalizedFile>> nFile =
- normalized::normalizedFromAtoms(file, _context);
+ normalized::normalizedFromAtoms(file, _ctx);
if (std::error_code ec = nFile.getError())
return ec;
// For testing, write out yaml form of normalized file.
- if (_context.printAtoms()) {
- std::unique_ptr<Writer> yamlWriter = createWriterYAML(_context);
+ if (_ctx.printAtoms()) {
+ std::unique_ptr<Writer> yamlWriter = createWriterYAML(_ctx);
yamlWriter->writeFile(file, "-");
}
@@ -45,21 +45,19 @@ public:
return writeBinary(*nFile->get(), path);
}
- bool createImplicitFiles(std::vector<std::unique_ptr<File> > &r) override {
+ void createImplicitFiles(std::vector<std::unique_ptr<File>> &r) override {
// When building main executables, add _main as required entry point.
- if (_context.outputTypeHasEntry())
- r.emplace_back(new CEntryFile(_context));
+ if (_ctx.outputTypeHasEntry())
+ r.emplace_back(new CEntryFile(_ctx));
// If this can link with dylibs, need helper function (dyld_stub_binder).
- if (_context.needsStubsPass())
- r.emplace_back(new StubHelperFile(_context));
+ if (_ctx.needsStubsPass())
+ r.emplace_back(new StubHelperFile(_ctx));
// Final linked images can access a symbol for their mach_header.
- if (_context.outputMachOType() != llvm::MachO::MH_OBJECT)
- r.emplace_back(new MachHeaderAliasFile(_context));
-
- return true;
+ if (_ctx.outputMachOType() != llvm::MachO::MH_OBJECT)
+ r.emplace_back(new MachHeaderAliasFile(_ctx));
}
private:
- const MachOLinkingContext &_context;
+ const MachOLinkingContext &_ctx;
};
diff --git a/lib/ReaderWriter/Makefile b/lib/ReaderWriter/Makefile
deleted file mode 100644
index 23587440805f..000000000000
--- a/lib/ReaderWriter/Makefile
+++ /dev/null
@@ -1,16 +0,0 @@
-##===- lld/lib/ReaderWriter/Makefile ---------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL := ../..
-LIBRARYNAME := lldReaderWriter
-
-# these link against this lib
-PARALLEL_DIRS := ELF MachO Native PECOFF YAML
-
-include $(LLD_LEVEL)/Makefile
diff --git a/lib/ReaderWriter/Native/CMakeLists.txt b/lib/ReaderWriter/Native/CMakeLists.txt
deleted file mode 100644
index e15f3d60e89c..000000000000
--- a/lib/ReaderWriter/Native/CMakeLists.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-add_llvm_library(lldNative
- ReaderNative.cpp
- WriterNative.cpp
- LINK_LIBS
- lldCore
- LLVMSupport
- )
diff --git a/lib/ReaderWriter/Native/Makefile b/lib/ReaderWriter/Native/Makefile
deleted file mode 100644
index 6aba37868900..000000000000
--- a/lib/ReaderWriter/Native/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-##===- lld/lib/ReaderWriter/Native/Makefile --------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL := ../../..
-LIBRARYNAME := lldNative
-USEDLIBS = lldCore.a
-
-include $(LLD_LEVEL)/Makefile
diff --git a/lib/ReaderWriter/Native/NativeFileFormat.h b/lib/ReaderWriter/Native/NativeFileFormat.h
deleted file mode 100644
index 535072fe2314..000000000000
--- a/lib/ReaderWriter/Native/NativeFileFormat.h
+++ /dev/null
@@ -1,258 +0,0 @@
-//===- lib/ReaderWriter/Native/NativeFileFormat.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_NATIVE_NATIVE_FILE_FORMAT_H
-#define LLD_READER_WRITER_NATIVE_NATIVE_FILE_FORMAT_H
-
-#include "llvm/Support/DataTypes.h"
-#include <cstdint>
-
-namespace lld {
-
-//
-// Overview:
-//
-// The number one design goal of this file format is enable the linker to
-// read object files into in-memory Atom objects extremely quickly.
-// The second design goal is to enable future modifications to the
-// Atom attribute model.
-//
-// The llvm native object file format is not like traditional object file
-// formats (e.g. ELF, COFF, mach-o). There is no symbol table and no
-// sections. Instead the file is essentially an array of archived Atoms.
-// It is *not* serialized Atoms which would require deserialization into
-// in memory objects. Instead it is an array of read-only info about each
-// Atom. The NativeReader bulk creates in-memory Atoms which just have
-// an ivar which points to the read-only info for that Atom. No additional
-// processing is done to construct the in-memory Atoms. All Atom attribute
-// getter methods are virtual calls which dig up the info they need from the
-// ivar data.
-//
-// To support the gradual evolution of Atom attributes, the Atom read-only
-// data is versioned. The NativeReader chooses which in-memory Atom class
-// to use based on the version. What this means is that if new attributes
-// are added (or changed) in the Atom model, a new native atom class and
-// read-only atom info struct needs to be defined. Then, all the existing
-// native reader atom classes need to be modified to do their best effort
-// to map their old style read-only data to the new Atom model. At some point
-// some classes to support old versions may be dropped.
-//
-//
-// Details:
-//
-// The native object file format consists of a header that specifies the
-// endianness of the file and the architecture along with a list of "chunks"
-// in the file. A Chunk is simply a tagged range of the file. There is
-// one chunk for the array of atom infos. There is another chunk for the
-// string pool, and another for the content pool.
-//
-// It turns out there most atoms have very similar sets of attributes, only
-// the name and content attribute vary. To exploit this fact to reduce the file
-// size, the atom read-only info contains just the name and content info plus
-// a reference to which attribute set it uses. The attribute sets are stored
-// in another chunk.
-//
-
-
-//
-// An entry in the NativeFileHeader that describes one chunk of the file.
-//
-struct NativeChunk {
- uint32_t signature;
- uint32_t fileOffset;
- uint32_t fileSize;
- uint32_t elementCount;
-};
-
-
-//
-// The header in a native object file
-//
-struct NativeFileHeader {
- uint8_t magic[16];
- uint32_t endian;
- uint32_t architecture;
- uint32_t fileSize;
- uint32_t chunkCount;
- // NativeChunk chunks[]
-};
-
-//
-// Possible values for NativeChunk.signature field
-//
-enum NativeChunkSignatures {
- NCS_DefinedAtomsV1 = 1,
- NCS_AttributesArrayV1 = 2,
- NCS_AbsoluteAttributesV1 = 12,
- NCS_UndefinedAtomsV1 = 3,
- NCS_SharedLibraryAtomsV1 = 4,
- NCS_AbsoluteAtomsV1 = 5,
- NCS_Strings = 6,
- NCS_ReferencesArrayV1 = 7,
- NCS_ReferencesArrayV2 = 8,
- NCS_TargetsTable = 9,
- NCS_AddendsTable = 10,
- NCS_Content = 11,
-};
-
-//
-// The 16-bytes at the start of a native object file
-//
-#define NATIVE_FILE_HEADER_MAGIC "llvm nat obj v1 "
-
-//
-// Possible values for the NativeFileHeader.endian field
-//
-enum {
- NFH_BigEndian = 0x42696745,
- NFH_LittleEndian = 0x4574696c
-};
-
-
-//
-// Possible values for the NativeFileHeader.architecture field
-//
-enum {
- NFA_x86 = 1,
- NFA_x86_64 = 2,
- NFA_armv6 = 3,
- NFA_armv7 = 4,
-};
-
-
-//
-// The NCS_DefinedAtomsV1 chunk contains an array of these structs
-//
-struct NativeDefinedAtomIvarsV1 {
- uint32_t nameOffset;
- uint32_t attributesOffset;
- uint32_t referencesStartIndex;
- uint32_t referencesCount;
- uint32_t contentOffset;
- uint32_t contentSize;
- uint64_t sectionSize;
-};
-
-
-//
-// The NCS_AttributesArrayV1 chunk contains an array of these structs
-//
-struct NativeAtomAttributesV1 {
- uint32_t sectionNameOffset;
- uint16_t align2;
- uint16_t alignModulus;
- uint8_t scope;
- uint8_t interposable;
- uint8_t merge;
- uint8_t contentType;
- uint8_t sectionChoice;
- uint8_t deadStrip;
- uint8_t dynamicExport;
- uint8_t permissions;
- uint8_t alias;
- uint8_t codeModel;
-};
-
-
-
-//
-// The NCS_UndefinedAtomsV1 chunk contains an array of these structs
-//
-struct NativeUndefinedAtomIvarsV1 {
- uint32_t nameOffset;
- uint32_t flags;
- uint32_t fallbackNameOffset;
-};
-
-
-//
-// The NCS_SharedLibraryAtomsV1 chunk contains an array of these structs
-//
-struct NativeSharedLibraryAtomIvarsV1 {
- uint64_t size;
- uint32_t nameOffset;
- uint32_t loadNameOffset;
- uint32_t type;
- uint32_t flags;
-};
-
-
-
-//
-// The NCS_AbsoluteAtomsV1 chunk contains an array of these structs
-//
-struct NativeAbsoluteAtomIvarsV1 {
- uint32_t nameOffset;
- uint32_t attributesOffset;
- uint32_t reserved;
- uint64_t value;
-};
-
-
-
-//
-// The NCS_ReferencesArrayV1 chunk contains an array of these structs
-//
-struct NativeReferenceIvarsV1 {
- enum {
- noTarget = UINT16_MAX
- };
- uint32_t offsetInAtom;
- uint16_t kindValue;
- uint8_t kindNamespace;
- uint8_t kindArch;
- uint16_t targetIndex;
- uint16_t addendIndex;
-};
-
-
-//
-// The NCS_ReferencesArrayV2 chunk contains an array of these structs
-//
-struct NativeReferenceIvarsV2 {
- enum : unsigned {
- noTarget = UINT32_MAX
- };
- uint64_t offsetInAtom;
- int64_t addend;
- uint16_t kindValue;
- uint8_t kindNamespace;
- uint8_t kindArch;
- uint32_t targetIndex;
- uint32_t tag;
-};
-
-
-//
-// The NCS_TargetsTable chunk contains an array of uint32_t entries.
-// The C++ class Reference has a target() method that returns a
-// pointer to another Atom. We can't have pointers in object files,
-// so instead NativeReferenceIvarsV1 contains an index to the target.
-// The index is into this NCS_TargetsTable of uint32_t entries.
-// The values in this table are the index of the (target) atom in this file.
-// For DefinedAtoms the value is from 0 to NCS_DefinedAtomsV1.elementCount.
-// For UndefinedAtoms the value is from NCS_DefinedAtomsV1.elementCount to
-// NCS_DefinedAtomsV1.elementCount+NCS_UndefinedAtomsV1.elementCount.
-//
-
-
-//
-// The NCS_AddendsTable chunk contains an array of int64_t entries.
-// If we allocated space for addends directly in NativeReferenceIvarsV1
-// it would double the size of that struct. But since addends are rare,
-// we instead just keep a pool of addends and have NativeReferenceIvarsV1
-// (if it needs an addend) just store the index (into the pool) of the
-// addend it needs.
-//
-
-
-
-} // namespace lld
-
-#endif // LLD_READER_WRITER_NATIVE_NATIVE_FILE_FORMAT_H
diff --git a/lib/ReaderWriter/Native/ReaderNative.cpp b/lib/ReaderWriter/Native/ReaderNative.cpp
deleted file mode 100644
index 84cdb4b997e8..000000000000
--- a/lib/ReaderWriter/Native/ReaderNative.cpp
+++ /dev/null
@@ -1,1013 +0,0 @@
-//===- lib/ReaderWriter/Native/ReaderNative.cpp ---------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "NativeFileFormat.h"
-#include "lld/Core/Atom.h"
-#include "lld/Core/Error.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Format.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <memory>
-#include <vector>
-
-namespace lld {
-namespace native {
-
-// forward reference
-class File;
-
-//
-// An object of this class is instantied for each NativeDefinedAtomIvarsV1
-// struct in the NCS_DefinedAtomsV1 chunk.
-//
-class NativeDefinedAtomV1 : public DefinedAtom {
-public:
- NativeDefinedAtomV1(const File& f,
- const NativeDefinedAtomIvarsV1* ivarData)
- : _file(&f), _ivarData(ivarData) { }
-
- const lld::File& file() const override;
-
- uint64_t ordinal() const override;
-
- StringRef name() const override;
-
- uint64_t size() const override { return _ivarData->contentSize; }
-
- uint64_t sectionSize() const override { return _ivarData->sectionSize; }
-
- DefinedAtom::Scope scope() const override {
- return (DefinedAtom::Scope)(attributes().scope);
- }
-
- DefinedAtom::Interposable interposable() const override {
- return (DefinedAtom::Interposable)(attributes().interposable);
- }
-
- DefinedAtom::Merge merge() const override {
- return (DefinedAtom::Merge)(attributes().merge);
- }
-
- DefinedAtom::ContentType contentType() const override {
- const NativeAtomAttributesV1& attr = attributes();
- return (DefinedAtom::ContentType)(attr.contentType);
- }
-
- DefinedAtom::Alignment alignment() const override {
- return DefinedAtom::Alignment(attributes().align2, attributes().alignModulus);
- }
-
- DefinedAtom::SectionChoice sectionChoice() const override {
- return (DefinedAtom::SectionChoice)(attributes().sectionChoice);
- }
-
- StringRef customSectionName() const override;
-
- DefinedAtom::DeadStripKind deadStrip() const override {
- return (DefinedAtom::DeadStripKind)(attributes().deadStrip);
- }
-
- DynamicExport dynamicExport() const override {
- return (DynamicExport)attributes().dynamicExport;
- }
-
- DefinedAtom::CodeModel codeModel() const override {
- return DefinedAtom::CodeModel(attributes().codeModel);
- }
-
- DefinedAtom::ContentPermissions permissions() const override {
- return (DefinedAtom::ContentPermissions)(attributes().permissions);
- }
-
- ArrayRef<uint8_t> rawContent() const override;
-
- reference_iterator begin() const override;
-
- reference_iterator end() const override;
-
- const Reference* derefIterator(const void*) const override;
-
- void incrementIterator(const void*& it) const override;
-
-private:
- const NativeAtomAttributesV1& attributes() const;
-
- const File *_file;
- const NativeDefinedAtomIvarsV1 *_ivarData;
-};
-
-
-
-//
-// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
-// struct in the NCS_UndefinedAtomsV1 chunk.
-//
-class NativeUndefinedAtomV1 : public UndefinedAtom {
-public:
- NativeUndefinedAtomV1(const File& f,
- const NativeUndefinedAtomIvarsV1* ivarData)
- : _file(&f), _ivarData(ivarData) { }
-
- const lld::File& file() const override;
- StringRef name() const override;
-
- CanBeNull canBeNull() const override {
- return (CanBeNull)(_ivarData->flags & 0x3);
- }
-
- const UndefinedAtom *fallback() const override;
-
-private:
- const File *_file;
- const NativeUndefinedAtomIvarsV1 *_ivarData;
- mutable std::unique_ptr<const SimpleUndefinedAtom> _fallback;
-};
-
-
-//
-// An object of this class is instantied for each NativeUndefinedAtomIvarsV1
-// struct in the NCS_SharedLibraryAtomsV1 chunk.
-//
-class NativeSharedLibraryAtomV1 : public SharedLibraryAtom {
-public:
- NativeSharedLibraryAtomV1(const File& f,
- const NativeSharedLibraryAtomIvarsV1* ivarData)
- : _file(&f), _ivarData(ivarData) { }
-
- const lld::File& file() const override;
- StringRef name() const override;
- StringRef loadName() const override;
-
- bool canBeNullAtRuntime() const override {
- return (_ivarData->flags & 0x1);
- }
-
- Type type() const override {
- return (Type)_ivarData->type;
- }
-
- uint64_t size() const override {
- return _ivarData->size;
- }
-
-private:
- const File *_file;
- const NativeSharedLibraryAtomIvarsV1 *_ivarData;
-};
-
-
-//
-// An object of this class is instantied for each NativeAbsoluteAtomIvarsV1
-// struct in the NCS_AbsoluteAtomsV1 chunk.
-//
-class NativeAbsoluteAtomV1 : public AbsoluteAtom {
-public:
- NativeAbsoluteAtomV1(const File& f,
- const NativeAbsoluteAtomIvarsV1* ivarData)
- : _file(&f), _ivarData(ivarData) { }
-
- const lld::File& file() const override;
- StringRef name() const override;
- Scope scope() const override {
- const NativeAtomAttributesV1& attr = absAttributes();
- return (Scope)(attr.scope);
- }
- uint64_t value() const override {
- return _ivarData->value;
- }
-
-private:
- const NativeAtomAttributesV1& absAttributes() const;
- const File *_file;
- const NativeAbsoluteAtomIvarsV1 *_ivarData;
-};
-
-
-//
-// An object of this class is instantied for each NativeReferenceIvarsV1
-// struct in the NCS_ReferencesArrayV1 chunk.
-//
-class NativeReferenceV1 : public Reference {
-public:
- NativeReferenceV1(const File &f, const NativeReferenceIvarsV1 *ivarData)
- : Reference((KindNamespace)ivarData->kindNamespace,
- (KindArch)ivarData->kindArch, ivarData->kindValue),
- _file(&f), _ivarData(ivarData) {}
-
- uint64_t offsetInAtom() const override {
- return _ivarData->offsetInAtom;
- }
-
- const Atom* target() const override;
- Addend addend() const override;
- void setTarget(const Atom* newAtom) override;
- void setAddend(Addend a) override;
-
-private:
- const File *_file;
- const NativeReferenceIvarsV1 *_ivarData;
-};
-
-
-//
-// An object of this class is instantied for each NativeReferenceIvarsV1
-// struct in the NCS_ReferencesArrayV1 chunk.
-//
-class NativeReferenceV2 : public Reference {
-public:
- NativeReferenceV2(const File &f, const NativeReferenceIvarsV2 *ivarData)
- : Reference((KindNamespace)ivarData->kindNamespace,
- (KindArch)ivarData->kindArch, ivarData->kindValue),
- _file(&f), _ivarData(ivarData) {}
-
- uint64_t offsetInAtom() const override {
- return _ivarData->offsetInAtom;
- }
-
- const Atom* target() const override;
- Addend addend() const override;
- void setTarget(const Atom* newAtom) override;
- void setAddend(Addend a) override;
- uint32_t tag() const override;
-
-private:
- const File *_file;
- const NativeReferenceIvarsV2 *_ivarData;
-};
-
-
-//
-// lld::File object for native llvm object file
-//
-class File : public lld::File {
-public:
- File(std::unique_ptr<MemoryBuffer> mb)
- : lld::File(mb->getBufferIdentifier(), kindObject),
- _mb(std::move(mb)), // Reader now takes ownership of buffer
- _header(nullptr), _targetsTable(nullptr), _targetsTableCount(0),
- _strings(nullptr), _stringsMaxOffset(0), _addends(nullptr),
- _addendsMaxIndex(0), _contentStart(nullptr), _contentEnd(nullptr) {
- _header =
- reinterpret_cast<const NativeFileHeader *>(_mb->getBufferStart());
- }
-
- /// Parses a File object from a native object file.
- std::error_code doParse() override {
- const uint8_t *const base =
- reinterpret_cast<const uint8_t *>(_mb->getBufferStart());
- StringRef path(_mb->getBufferIdentifier());
- const NativeFileHeader *const header =
- reinterpret_cast<const NativeFileHeader *>(base);
- const NativeChunk *const chunks =
- reinterpret_cast<const NativeChunk *>(base + sizeof(NativeFileHeader));
- // make sure magic matches
- if (memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC,
- sizeof(header->magic)) != 0)
- return make_error_code(NativeReaderError::unknown_file_format);
-
- // make sure mapped file contains all needed data
- const size_t fileSize = _mb->getBufferSize();
- if (header->fileSize > fileSize)
- return make_error_code(NativeReaderError::file_too_short);
-
- DEBUG_WITH_TYPE("ReaderNative",
- llvm::dbgs() << " Native File Header:" << " fileSize="
- << header->fileSize << " chunkCount="
- << header->chunkCount << "\n");
-
- // process each chunk
- for (uint32_t i = 0; i < header->chunkCount; ++i) {
- std::error_code ec;
- const NativeChunk* chunk = &chunks[i];
- // sanity check chunk is within file
- if ( chunk->fileOffset > fileSize )
- return make_error_code(NativeReaderError::file_malformed);
- if ( (chunk->fileOffset + chunk->fileSize) > fileSize)
- return make_error_code(NativeReaderError::file_malformed);
- // process chunk, based on signature
- switch ( chunk->signature ) {
- case NCS_DefinedAtomsV1:
- ec = processDefinedAtomsV1(base, chunk);
- break;
- case NCS_AttributesArrayV1:
- ec = processAttributesV1(base, chunk);
- break;
- case NCS_UndefinedAtomsV1:
- ec = processUndefinedAtomsV1(base, chunk);
- break;
- case NCS_SharedLibraryAtomsV1:
- ec = processSharedLibraryAtomsV1(base, chunk);
- break;
- case NCS_AbsoluteAtomsV1:
- ec = processAbsoluteAtomsV1(base, chunk);
- break;
- case NCS_AbsoluteAttributesV1:
- ec = processAbsoluteAttributesV1(base, chunk);
- break;
- case NCS_ReferencesArrayV1:
- ec = processReferencesV1(base, chunk);
- break;
- case NCS_ReferencesArrayV2:
- ec = processReferencesV2(base, chunk);
- break;
- case NCS_TargetsTable:
- ec = processTargetsTable(base, chunk);
- break;
- case NCS_AddendsTable:
- ec = processAddendsTable(base, chunk);
- break;
- case NCS_Content:
- ec = processContent(base, chunk);
- break;
- case NCS_Strings:
- ec = processStrings(base, chunk);
- break;
- default:
- return make_error_code(NativeReaderError::unknown_chunk_type);
- }
- if ( ec ) {
- return ec;
- }
- }
- // TO DO: validate enough chunks were used
-
- DEBUG_WITH_TYPE("ReaderNative", {
- llvm::dbgs() << " ReaderNative DefinedAtoms:\n";
- for (const DefinedAtom *a : defined()) {
- llvm::dbgs() << llvm::format(" 0x%09lX", a)
- << ", name=" << a->name()
- << ", size=" << a->size() << "\n";
- for (const Reference *r : *a) {
- llvm::dbgs() << " offset="
- << llvm::format("0x%03X", r->offsetInAtom())
- << ", kind=" << r->kindValue()
- << ", target=" << r->target() << "\n";
- }
- }
- });
- return make_error_code(NativeReaderError::success);
- }
-
- virtual ~File() {
- // _mb is automatically deleted because of std::unique_ptr<>
-
- // All other ivar pointers are pointers into the MemoryBuffer, except
- // the _definedAtoms array which was allocated to contain an array
- // of Atom objects. The atoms have empty destructors, so it is ok
- // to just delete the memory.
- delete _definedAtoms._arrayStart;
- delete _undefinedAtoms._arrayStart;
- delete _sharedLibraryAtoms._arrayStart;
- delete _absoluteAtoms._arrayStart;
- delete _referencesV1.arrayStart;
- delete _referencesV2.arrayStart;
- delete [] _targetsTable;
- }
-
- const atom_collection<DefinedAtom>& defined() const override {
- return _definedAtoms;
- }
- const atom_collection<UndefinedAtom>& undefined() const override {
- return _undefinedAtoms;
- }
- const atom_collection<SharedLibraryAtom>& sharedLibrary() const override {
- return _sharedLibraryAtoms;
- }
- const atom_collection<AbsoluteAtom> &absolute() const override {
- return _absoluteAtoms;
- }
-
-private:
- friend NativeDefinedAtomV1;
- friend NativeUndefinedAtomV1;
- friend NativeSharedLibraryAtomV1;
- friend NativeAbsoluteAtomV1;
- friend NativeReferenceV1;
- friend NativeReferenceV2;
-
- // instantiate array of DefinedAtoms from v1 ivar data in file
- std::error_code processDefinedAtomsV1(const uint8_t *base,
- const NativeChunk *chunk) {
- const size_t atomSize = sizeof(NativeDefinedAtomV1);
- size_t atomsArraySize = chunk->elementCount * atomSize;
- uint8_t* atomsStart = reinterpret_cast<uint8_t*>
- (operator new(atomsArraySize, std::nothrow));
- if (atomsStart == nullptr)
- return make_error_code(NativeReaderError::memory_error);
- const size_t ivarElementSize = chunk->fileSize
- / chunk->elementCount;
- if ( ivarElementSize != sizeof(NativeDefinedAtomIvarsV1) )
- return make_error_code(NativeReaderError::file_malformed);
- uint8_t* atomsEnd = atomsStart + atomsArraySize;
- const NativeDefinedAtomIvarsV1* ivarData =
- reinterpret_cast<const NativeDefinedAtomIvarsV1*>
- (base + chunk->fileOffset);
- for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
- NativeDefinedAtomV1* atomAllocSpace =
- reinterpret_cast<NativeDefinedAtomV1*>(s);
- new (atomAllocSpace) NativeDefinedAtomV1(*this, ivarData);
- ++ivarData;
- }
- this->_definedAtoms._arrayStart = atomsStart;
- this->_definedAtoms._arrayEnd = atomsEnd;
- this->_definedAtoms._elementSize = atomSize;
- this->_definedAtoms._elementCount = chunk->elementCount;
- DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
- << " chunk DefinedAtomsV1: "
- << " count=" << chunk->elementCount
- << " chunkSize=" << chunk->fileSize
- << "\n");
- return make_error_code(NativeReaderError::success);
- }
-
-
-
- // set up pointers to attributes array
- std::error_code processAttributesV1(const uint8_t *base,
- const NativeChunk *chunk) {
- this->_attributes = base + chunk->fileOffset;
- this->_attributesMaxOffset = chunk->fileSize;
- DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
- << " chunk AttributesV1: "
- << " count=" << chunk->elementCount
- << " chunkSize=" << chunk->fileSize
- << "\n");
- return make_error_code(NativeReaderError::success);
- }
-
- // set up pointers to attributes array
- std::error_code processAbsoluteAttributesV1(const uint8_t *base,
- const NativeChunk *chunk) {
- this->_absAttributes = base + chunk->fileOffset;
- this->_absAbsoluteMaxOffset = chunk->fileSize;
- DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
- << " chunk AbsoluteAttributesV1: "
- << " count=" << chunk->elementCount
- << " chunkSize=" << chunk->fileSize
- << "\n");
- return make_error_code(NativeReaderError::success);
- }
-
- // instantiate array of UndefinedAtoms from v1 ivar data in file
- std::error_code processUndefinedAtomsV1(const uint8_t *base,
- const NativeChunk *chunk) {
- const size_t atomSize = sizeof(NativeUndefinedAtomV1);
- size_t atomsArraySize = chunk->elementCount * atomSize;
- uint8_t* atomsStart = reinterpret_cast<uint8_t*>
- (operator new(atomsArraySize, std::nothrow));
- if (atomsStart == nullptr)
- return make_error_code(NativeReaderError::memory_error);
- const size_t ivarElementSize = chunk->fileSize
- / chunk->elementCount;
- if ( ivarElementSize != sizeof(NativeUndefinedAtomIvarsV1) )
- return make_error_code(NativeReaderError::file_malformed);
- uint8_t* atomsEnd = atomsStart + atomsArraySize;
- const NativeUndefinedAtomIvarsV1* ivarData =
- reinterpret_cast<const NativeUndefinedAtomIvarsV1*>
- (base + chunk->fileOffset);
- for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
- NativeUndefinedAtomV1* atomAllocSpace =
- reinterpret_cast<NativeUndefinedAtomV1*>(s);
- new (atomAllocSpace) NativeUndefinedAtomV1(*this, ivarData);
- ++ivarData;
- }
- this->_undefinedAtoms._arrayStart = atomsStart;
- this->_undefinedAtoms._arrayEnd = atomsEnd;
- this->_undefinedAtoms._elementSize = atomSize;
- this->_undefinedAtoms._elementCount = chunk->elementCount;
- DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
- << " chunk UndefinedAtomsV1:"
- << " count=" << chunk->elementCount
- << " chunkSize=" << chunk->fileSize
- << "\n");
- return make_error_code(NativeReaderError::success);
- }
-
-
- // instantiate array of ShareLibraryAtoms from v1 ivar data in file
- std::error_code processSharedLibraryAtomsV1(const uint8_t *base,
- const NativeChunk *chunk) {
- const size_t atomSize = sizeof(NativeSharedLibraryAtomV1);
- size_t atomsArraySize = chunk->elementCount * atomSize;
- uint8_t* atomsStart = reinterpret_cast<uint8_t*>
- (operator new(atomsArraySize, std::nothrow));
- if (atomsStart == nullptr)
- return make_error_code(NativeReaderError::memory_error);
- const size_t ivarElementSize = chunk->fileSize
- / chunk->elementCount;
- if ( ivarElementSize != sizeof(NativeSharedLibraryAtomIvarsV1) )
- return make_error_code(NativeReaderError::file_malformed);
- uint8_t* atomsEnd = atomsStart + atomsArraySize;
- const NativeSharedLibraryAtomIvarsV1* ivarData =
- reinterpret_cast<const NativeSharedLibraryAtomIvarsV1*>
- (base + chunk->fileOffset);
- for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
- NativeSharedLibraryAtomV1* atomAllocSpace =
- reinterpret_cast<NativeSharedLibraryAtomV1*>(s);
- new (atomAllocSpace) NativeSharedLibraryAtomV1(*this, ivarData);
- ++ivarData;
- }
- this->_sharedLibraryAtoms._arrayStart = atomsStart;
- this->_sharedLibraryAtoms._arrayEnd = atomsEnd;
- this->_sharedLibraryAtoms._elementSize = atomSize;
- this->_sharedLibraryAtoms._elementCount = chunk->elementCount;
- DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
- << " chunk SharedLibraryAtomsV1:"
- << " count=" << chunk->elementCount
- << " chunkSize=" << chunk->fileSize
- << "\n");
- return make_error_code(NativeReaderError::success);
- }
-
-
- // instantiate array of AbsoluteAtoms from v1 ivar data in file
- std::error_code processAbsoluteAtomsV1(const uint8_t *base,
- const NativeChunk *chunk) {
- const size_t atomSize = sizeof(NativeAbsoluteAtomV1);
- size_t atomsArraySize = chunk->elementCount * atomSize;
- uint8_t* atomsStart = reinterpret_cast<uint8_t*>
- (operator new(atomsArraySize, std::nothrow));
- if (atomsStart == nullptr)
- return make_error_code(NativeReaderError::memory_error);
- const size_t ivarElementSize = chunk->fileSize
- / chunk->elementCount;
- if ( ivarElementSize != sizeof(NativeAbsoluteAtomIvarsV1) )
- return make_error_code(NativeReaderError::file_malformed);
- uint8_t* atomsEnd = atomsStart + atomsArraySize;
- const NativeAbsoluteAtomIvarsV1* ivarData =
- reinterpret_cast<const NativeAbsoluteAtomIvarsV1*>
- (base + chunk->fileOffset);
- for(uint8_t* s = atomsStart; s != atomsEnd; s += atomSize) {
- NativeAbsoluteAtomV1* atomAllocSpace =
- reinterpret_cast<NativeAbsoluteAtomV1*>(s);
- new (atomAllocSpace) NativeAbsoluteAtomV1(*this, ivarData);
- ++ivarData;
- }
- this->_absoluteAtoms._arrayStart = atomsStart;
- this->_absoluteAtoms._arrayEnd = atomsEnd;
- this->_absoluteAtoms._elementSize = atomSize;
- this->_absoluteAtoms._elementCount = chunk->elementCount;
- DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
- << " chunk AbsoluteAtomsV1: "
- << " count=" << chunk->elementCount
- << " chunkSize=" << chunk->fileSize
- << "\n");
- return make_error_code(NativeReaderError::success);
- }
-
- template <class T, class U>
- std::error_code
- processReferences(const uint8_t *base, const NativeChunk *chunk,
- uint8_t *&refsStart, uint8_t *&refsEnd) const {
- if (chunk->elementCount == 0)
- return make_error_code(NativeReaderError::success);
- size_t refsArraySize = chunk->elementCount * sizeof(T);
- refsStart = reinterpret_cast<uint8_t *>(
- operator new(refsArraySize, std::nothrow));
- if (refsStart == nullptr)
- return make_error_code(NativeReaderError::memory_error);
- const size_t ivarElementSize = chunk->fileSize / chunk->elementCount;
- if (ivarElementSize != sizeof(U))
- return make_error_code(NativeReaderError::file_malformed);
- refsEnd = refsStart + refsArraySize;
- const U* ivarData = reinterpret_cast<const U *>(base + chunk->fileOffset);
- for (uint8_t *s = refsStart; s != refsEnd; s += sizeof(T), ++ivarData) {
- T *atomAllocSpace = reinterpret_cast<T *>(s);
- new (atomAllocSpace) T(*this, ivarData);
- }
- return make_error_code(NativeReaderError::success);
- }
-
- // instantiate array of References from v1 ivar data in file
- std::error_code processReferencesV1(const uint8_t *base,
- const NativeChunk *chunk) {
- uint8_t *refsStart, *refsEnd;
- if (std::error_code ec =
- processReferences<NativeReferenceV1, NativeReferenceIvarsV1>(
- base, chunk, refsStart, refsEnd))
- return ec;
- this->_referencesV1.arrayStart = refsStart;
- this->_referencesV1.arrayEnd = refsEnd;
- this->_referencesV1.elementSize = sizeof(NativeReferenceV1);
- this->_referencesV1.elementCount = chunk->elementCount;
- DEBUG_WITH_TYPE("ReaderNative", {
- llvm::dbgs() << " chunk ReferencesV1: "
- << " count=" << chunk->elementCount
- << " chunkSize=" << chunk->fileSize << "\n";
- });
- return make_error_code(NativeReaderError::success);
- }
-
- // instantiate array of References from v2 ivar data in file
- std::error_code processReferencesV2(const uint8_t *base,
- const NativeChunk *chunk) {
- uint8_t *refsStart, *refsEnd;
- if (std::error_code ec =
- processReferences<NativeReferenceV2, NativeReferenceIvarsV2>(
- base, chunk, refsStart, refsEnd))
- return ec;
- this->_referencesV2.arrayStart = refsStart;
- this->_referencesV2.arrayEnd = refsEnd;
- this->_referencesV2.elementSize = sizeof(NativeReferenceV2);
- this->_referencesV2.elementCount = chunk->elementCount;
- DEBUG_WITH_TYPE("ReaderNative", {
- llvm::dbgs() << " chunk ReferencesV2: "
- << " count=" << chunk->elementCount
- << " chunkSize=" << chunk->fileSize << "\n";
- });
- return make_error_code(NativeReaderError::success);
- }
-
- // set up pointers to target table
- std::error_code processTargetsTable(const uint8_t *base,
- const NativeChunk *chunk) {
- const uint32_t* targetIndexes = reinterpret_cast<const uint32_t*>
- (base + chunk->fileOffset);
- this->_targetsTableCount = chunk->elementCount;
- this->_targetsTable = new const Atom*[chunk->elementCount];
- for (uint32_t i=0; i < chunk->elementCount; ++i) {
- const uint32_t index = targetIndexes[i];
- if ( index < _definedAtoms._elementCount ) {
- const uint8_t* p = _definedAtoms._arrayStart
- + index * _definedAtoms._elementSize;
- this->_targetsTable[i] = reinterpret_cast<const DefinedAtom*>(p);
- continue;
- }
- const uint32_t undefIndex = index - _definedAtoms._elementCount;
- if ( undefIndex < _undefinedAtoms._elementCount ) {
- const uint8_t* p = _undefinedAtoms._arrayStart
- + undefIndex * _undefinedAtoms._elementSize;
- this->_targetsTable[i] = reinterpret_cast<const UndefinedAtom*>(p);
- continue;
- }
- const uint32_t slIndex = index - _definedAtoms._elementCount
- - _undefinedAtoms._elementCount;
- if ( slIndex < _sharedLibraryAtoms._elementCount ) {
- const uint8_t* p = _sharedLibraryAtoms._arrayStart
- + slIndex * _sharedLibraryAtoms._elementSize;
- this->_targetsTable[i] = reinterpret_cast<const SharedLibraryAtom*>(p);
- continue;
- }
- const uint32_t abIndex = index - _definedAtoms._elementCount
- - _undefinedAtoms._elementCount
- - _sharedLibraryAtoms._elementCount;
- if ( abIndex < _absoluteAtoms._elementCount ) {
- const uint8_t* p = _absoluteAtoms._arrayStart
- + abIndex * _absoluteAtoms._elementSize;
- this->_targetsTable[i] = reinterpret_cast<const AbsoluteAtom*>(p);
- continue;
- }
- return make_error_code(NativeReaderError::file_malformed);
- }
- DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
- << " chunk Targets Table: "
- << " count=" << chunk->elementCount
- << " chunkSize=" << chunk->fileSize
- << "\n");
- return make_error_code(NativeReaderError::success);
- }
-
-
- // set up pointers to addend pool in file
- std::error_code processAddendsTable(const uint8_t *base,
- const NativeChunk *chunk) {
- this->_addends = reinterpret_cast<const Reference::Addend*>
- (base + chunk->fileOffset);
- this->_addendsMaxIndex = chunk->elementCount;
- DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
- << " chunk Addends: "
- << " count=" << chunk->elementCount
- << " chunkSize=" << chunk->fileSize
- << "\n");
- return make_error_code(NativeReaderError::success);
- }
-
- // set up pointers to string pool in file
- std::error_code processStrings(const uint8_t *base,
- const NativeChunk *chunk) {
- this->_strings = reinterpret_cast<const char*>(base + chunk->fileOffset);
- this->_stringsMaxOffset = chunk->fileSize;
- DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
- << " chunk Strings: "
- << " chunkSize=" << chunk->fileSize
- << "\n");
- return make_error_code(NativeReaderError::success);
- }
-
- // set up pointers to content area in file
- std::error_code processContent(const uint8_t *base,
- const NativeChunk *chunk) {
- this->_contentStart = base + chunk->fileOffset;
- this->_contentEnd = base + chunk->fileOffset + chunk->fileSize;
- DEBUG_WITH_TYPE("ReaderNative", llvm::dbgs()
- << " chunk content: "
- << " chunkSize=" << chunk->fileSize
- << "\n");
- return make_error_code(NativeReaderError::success);
- }
-
- StringRef string(uint32_t offset) const {
- assert(offset < _stringsMaxOffset);
- return StringRef(&_strings[offset]);
- }
-
- Reference::Addend addend(uint32_t index) const {
- if ( index == 0 )
- return 0; // addend index zero is used to mean "no addend"
- assert(index <= _addendsMaxIndex);
- return _addends[index-1]; // one-based indexing
- }
-
- const NativeAtomAttributesV1& attribute(uint32_t off) const {
- assert(off < _attributesMaxOffset);
- return *reinterpret_cast<const NativeAtomAttributesV1*>(_attributes + off);
- }
-
- const NativeAtomAttributesV1& absAttribute(uint32_t off) const {
- assert(off < _absAbsoluteMaxOffset);
- return *reinterpret_cast<const NativeAtomAttributesV1*>(_absAttributes + off);
- }
-
- const uint8_t* content(uint32_t offset, uint32_t size) const {
- const uint8_t* result = _contentStart + offset;
- assert((result+size) <= _contentEnd);
- return result;
- }
-
- const Reference* referenceByIndex(uintptr_t index) const {
- if (index < _referencesV1.elementCount) {
- return reinterpret_cast<const NativeReferenceV1*>(
- _referencesV1.arrayStart + index * _referencesV1.elementSize);
- }
- assert(index < _referencesV2.elementCount);
- return reinterpret_cast<const NativeReferenceV2*>(
- _referencesV2.arrayStart + index * _referencesV2.elementSize);
- }
-
- const Atom* targetV1(uint16_t index) const {
- if ( index == NativeReferenceIvarsV1::noTarget )
- return nullptr;
- assert(index < _targetsTableCount);
- return _targetsTable[index];
- }
-
- void setTargetV1(uint16_t index, const Atom* newAtom) const {
- assert(index != NativeReferenceIvarsV1::noTarget);
- assert(index > _targetsTableCount);
- _targetsTable[index] = newAtom;
- }
-
- const Atom* targetV2(uint32_t index) const {
- if (index == NativeReferenceIvarsV2::noTarget)
- return nullptr;
- assert(index < _targetsTableCount);
- return _targetsTable[index];
- }
-
- void setTargetV2(uint32_t index, const Atom* newAtom) const {
- assert(index != NativeReferenceIvarsV2::noTarget);
- assert(index > _targetsTableCount);
- _targetsTable[index] = newAtom;
- }
-
- template <typename T>
- class AtomArray : public File::atom_collection<T> {
- public:
- AtomArray() : _arrayStart(nullptr), _arrayEnd(nullptr),
- _elementSize(0), _elementCount(0) { }
-
- virtual atom_iterator<T> begin() const {
- return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayStart));
- }
- virtual atom_iterator<T> end() const{
- return atom_iterator<T>(*this, reinterpret_cast<const void*>(_arrayEnd));
- }
- virtual const T* deref(const void* it) const {
- return reinterpret_cast<const T*>(it);
- }
- virtual void next(const void*& it) const {
- const uint8_t* p = reinterpret_cast<const uint8_t*>(it);
- p += _elementSize;
- it = reinterpret_cast<const void*>(p);
- }
- virtual uint64_t size() const { return _elementCount; }
- const uint8_t *_arrayStart;
- const uint8_t *_arrayEnd;
- uint32_t _elementSize;
- uint32_t _elementCount;
- };
-
- struct IvarArray {
- IvarArray() :
- arrayStart(nullptr),
- arrayEnd(nullptr),
- elementSize(0),
- elementCount(0) { }
-
- const uint8_t* arrayStart;
- const uint8_t* arrayEnd;
- uint32_t elementSize;
- uint32_t elementCount;
- };
-
- std::unique_ptr<MemoryBuffer> _mb;
- const NativeFileHeader* _header;
- AtomArray<DefinedAtom> _definedAtoms;
- AtomArray<UndefinedAtom> _undefinedAtoms;
- AtomArray<SharedLibraryAtom> _sharedLibraryAtoms;
- AtomArray<AbsoluteAtom> _absoluteAtoms;
- const uint8_t* _absAttributes;
- uint32_t _absAbsoluteMaxOffset;
- const uint8_t* _attributes;
- uint32_t _attributesMaxOffset;
- IvarArray _referencesV1;
- IvarArray _referencesV2;
- const Atom** _targetsTable;
- uint32_t _targetsTableCount;
- const char* _strings;
- uint32_t _stringsMaxOffset;
- const Reference::Addend* _addends;
- uint32_t _addendsMaxIndex;
- const uint8_t *_contentStart;
- const uint8_t *_contentEnd;
-};
-
-inline const lld::File &NativeDefinedAtomV1::file() const {
- return *_file;
-}
-
-inline uint64_t NativeDefinedAtomV1:: ordinal() const {
- const uint8_t* p = reinterpret_cast<const uint8_t*>(_ivarData);
- return p - _file->_definedAtoms._arrayStart;
-}
-
-inline StringRef NativeDefinedAtomV1::name() const {
- return _file->string(_ivarData->nameOffset);
-}
-
-inline const NativeAtomAttributesV1& NativeDefinedAtomV1::attributes() const {
- return _file->attribute(_ivarData->attributesOffset);
-}
-
-inline ArrayRef<uint8_t> NativeDefinedAtomV1::rawContent() const {
- if (!occupiesDiskSpace())
- return ArrayRef<uint8_t>();
- const uint8_t* p = _file->content(_ivarData->contentOffset,
- _ivarData->contentSize);
- return ArrayRef<uint8_t>(p, _ivarData->contentSize);
-}
-
-inline StringRef NativeDefinedAtomV1::customSectionName() const {
- uint32_t offset = attributes().sectionNameOffset;
- return _file->string(offset);
-}
-
-DefinedAtom::reference_iterator NativeDefinedAtomV1::begin() const {
- uintptr_t index = _ivarData->referencesStartIndex;
- const void* it = reinterpret_cast<const void*>(index);
- return reference_iterator(*this, it);
-}
-
-DefinedAtom::reference_iterator NativeDefinedAtomV1::end() const {
- uintptr_t index = _ivarData->referencesStartIndex+_ivarData->referencesCount;
- const void* it = reinterpret_cast<const void*>(index);
- return reference_iterator(*this, it);
-}
-
-const Reference* NativeDefinedAtomV1::derefIterator(const void* it) const {
- uintptr_t index = reinterpret_cast<uintptr_t>(it);
- return _file->referenceByIndex(index);
-}
-
-void NativeDefinedAtomV1::incrementIterator(const void*& it) const {
- uintptr_t index = reinterpret_cast<uintptr_t>(it);
- ++index;
- it = reinterpret_cast<const void*>(index);
-}
-
-inline const lld::File& NativeUndefinedAtomV1::file() const {
- return *_file;
-}
-
-inline StringRef NativeUndefinedAtomV1::name() const {
- return _file->string(_ivarData->nameOffset);
-}
-
-inline const UndefinedAtom *NativeUndefinedAtomV1::fallback() const {
- if (!_ivarData->fallbackNameOffset)
- return nullptr;
- if (!_fallback)
- _fallback.reset(new SimpleUndefinedAtom(
- *_file, _file->string(_ivarData->fallbackNameOffset)));
- return _fallback.get();
-}
-
-inline const lld::File& NativeSharedLibraryAtomV1::file() const {
- return *_file;
-}
-
-inline StringRef NativeSharedLibraryAtomV1::name() const {
- return _file->string(_ivarData->nameOffset);
-}
-
-inline StringRef NativeSharedLibraryAtomV1::loadName() const {
- return _file->string(_ivarData->loadNameOffset);
-}
-
-
-
-inline const lld::File& NativeAbsoluteAtomV1::file() const {
- return *_file;
-}
-
-inline StringRef NativeAbsoluteAtomV1::name() const {
- return _file->string(_ivarData->nameOffset);
-}
-
-inline const NativeAtomAttributesV1& NativeAbsoluteAtomV1::absAttributes() const {
- return _file->absAttribute(_ivarData->attributesOffset);
-}
-
-inline const Atom* NativeReferenceV1::target() const {
- return _file->targetV1(_ivarData->targetIndex);
-}
-
-inline Reference::Addend NativeReferenceV1::addend() const {
- return _file->addend(_ivarData->addendIndex);
-}
-
-inline void NativeReferenceV1::setTarget(const Atom* newAtom) {
- return _file->setTargetV1(_ivarData->targetIndex, newAtom);
-}
-
-inline void NativeReferenceV1::setAddend(Addend a) {
- // Do nothing if addend value is not being changed.
- if (addend() == a)
- return;
- llvm_unreachable("setAddend() not supported");
-}
-
-inline const Atom* NativeReferenceV2::target() const {
- return _file->targetV2(_ivarData->targetIndex);
-}
-
-inline Reference::Addend NativeReferenceV2::addend() const {
- return _ivarData->addend;
-}
-
-inline void NativeReferenceV2::setTarget(const Atom* newAtom) {
- return _file->setTargetV2(_ivarData->targetIndex, newAtom);
-}
-
-inline void NativeReferenceV2::setAddend(Addend a) {
- // Do nothing if addend value is not being changed.
- if (addend() == a)
- return;
- llvm_unreachable("setAddend() not supported");
-}
-
-uint32_t NativeReferenceV2::tag() const { return _ivarData->tag; }
-
-} // end namespace native
-
-namespace {
-
-class NativeReader : public Reader {
-public:
- virtual bool canParse(file_magic magic, StringRef,
- const MemoryBuffer &mb) const override {
- const NativeFileHeader *const header =
- reinterpret_cast<const NativeFileHeader *>(mb.getBufferStart());
- return (memcmp(header->magic, NATIVE_FILE_HEADER_MAGIC,
- sizeof(header->magic)) == 0);
- }
-
- virtual std::error_code
- loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
- std::vector<std::unique_ptr<File>> &result) const override {
- auto *file = new lld::native::File(std::move(mb));
- result.push_back(std::unique_ptr<File>(file));
- return std::error_code();
- }
-};
-
-}
-
-void Registry::addSupportNativeObjects() {
- add(std::unique_ptr<Reader>(new NativeReader()));
-}
-
-} // end namespace lld
diff --git a/lib/ReaderWriter/Native/WriterNative.cpp b/lib/ReaderWriter/Native/WriterNative.cpp
deleted file mode 100644
index 5e01a6ce1c7c..000000000000
--- a/lib/ReaderWriter/Native/WriterNative.cpp
+++ /dev/null
@@ -1,566 +0,0 @@
-//===- lib/ReaderWriter/Native/WriterNative.cpp ---------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "NativeFileFormat.h"
-#include "lld/Core/File.h"
-#include "lld/Core/LinkingContext.h"
-#include "lld/Core/Writer.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cstdint>
-#include <set>
-#include <system_error>
-#include <vector>
-
-namespace lld {
-namespace native {
-
-///
-/// Class for writing native object files.
-///
-class Writer : public lld::Writer {
-public:
- std::error_code writeFile(const lld::File &file, StringRef outPath) override {
- // reserve first byte for unnamed atoms
- _stringPool.push_back('\0');
- // visit all atoms
- for ( const DefinedAtom *defAtom : file.defined() ) {
- this->addIVarsForDefinedAtom(*defAtom);
- // We are trying to process all atoms, but the defined() iterator does not
- // return group children. So, when a group parent is found, we need to
- // handle each child atom.
- if (defAtom->isGroupParent()) {
- for (const Reference *r : *defAtom) {
- if (r->kindNamespace() != lld::Reference::KindNamespace::all)
- continue;
- if (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");
- this->addIVarsForDefinedAtom(*target);
- }
- }
- }
- }
- for ( const UndefinedAtom *undefAtom : file.undefined() ) {
- this->addIVarsForUndefinedAtom(*undefAtom);
- }
- for ( const SharedLibraryAtom *shlibAtom : file.sharedLibrary() ) {
- this->addIVarsForSharedLibraryAtom(*shlibAtom);
- }
- for ( const AbsoluteAtom *absAtom : file.absolute() ) {
- this->addIVarsForAbsoluteAtom(*absAtom);
- }
-
- maybeConvertReferencesToV1();
-
- // construct file header based on atom information accumulated
- this->makeHeader();
-
- std::error_code ec;
- llvm::raw_fd_ostream out(outPath, ec, llvm::sys::fs::F_None);
- if (ec)
- return ec;
-
- this->write(out);
-
- return std::error_code();
- }
-
- virtual ~Writer() {
- }
-
-private:
-
- // write the lld::File in native format to the specified stream
- void write(raw_ostream &out) {
- assert(out.tell() == 0);
- out.write((char*)_headerBuffer, _headerBufferSize);
-
- writeChunk(out, _definedAtomIvars, NCS_DefinedAtomsV1);
- writeChunk(out, _attributes, NCS_AttributesArrayV1);
- writeChunk(out, _undefinedAtomIvars, NCS_UndefinedAtomsV1);
- writeChunk(out, _sharedLibraryAtomIvars, NCS_SharedLibraryAtomsV1);
- writeChunk(out, _absoluteAtomIvars, NCS_AbsoluteAtomsV1);
- writeChunk(out, _absAttributes, NCS_AbsoluteAttributesV1);
- writeChunk(out, _stringPool, NCS_Strings);
- writeChunk(out, _referencesV1, NCS_ReferencesArrayV1);
- writeChunk(out, _referencesV2, NCS_ReferencesArrayV2);
-
- if (!_targetsTableIndex.empty()) {
- assert(out.tell() == findChunk(NCS_TargetsTable).fileOffset);
- writeTargetTable(out);
- }
-
- if (!_addendsTableIndex.empty()) {
- assert(out.tell() == findChunk(NCS_AddendsTable).fileOffset);
- writeAddendTable(out);
- }
-
- writeChunk(out, _contentPool, NCS_Content);
- }
-
- template<class T>
- void writeChunk(raw_ostream &out, std::vector<T> &vector, uint32_t signature) {
- if (vector.empty())
- return;
- assert(out.tell() == findChunk(signature).fileOffset);
- out.write((char*)&vector[0], vector.size() * sizeof(T));
- }
-
- void addIVarsForDefinedAtom(const DefinedAtom& atom) {
- _definedAtomIndex[&atom] = _definedAtomIvars.size();
- NativeDefinedAtomIvarsV1 ivar;
- unsigned refsCount;
- ivar.nameOffset = getNameOffset(atom);
- ivar.attributesOffset = getAttributeOffset(atom);
- ivar.referencesStartIndex = getReferencesIndex(atom, refsCount);
- ivar.referencesCount = refsCount;
- ivar.contentOffset = getContentOffset(atom);
- ivar.contentSize = atom.size();
- ivar.sectionSize = atom.sectionSize();
- _definedAtomIvars.push_back(ivar);
- }
-
- void addIVarsForUndefinedAtom(const UndefinedAtom& atom) {
- _undefinedAtomIndex[&atom] = _undefinedAtomIvars.size();
- NativeUndefinedAtomIvarsV1 ivar;
- ivar.nameOffset = getNameOffset(atom);
- ivar.flags = (atom.canBeNull() & 0x03);
- ivar.fallbackNameOffset = 0;
- if (atom.fallback())
- ivar.fallbackNameOffset = getNameOffset(*atom.fallback());
- _undefinedAtomIvars.push_back(ivar);
- }
-
- void addIVarsForSharedLibraryAtom(const SharedLibraryAtom& atom) {
- _sharedLibraryAtomIndex[&atom] = _sharedLibraryAtomIvars.size();
- NativeSharedLibraryAtomIvarsV1 ivar;
- ivar.size = atom.size();
- ivar.nameOffset = getNameOffset(atom);
- ivar.loadNameOffset = getSharedLibraryNameOffset(atom.loadName());
- ivar.type = (uint32_t)atom.type();
- ivar.flags = atom.canBeNullAtRuntime();
- _sharedLibraryAtomIvars.push_back(ivar);
- }
-
- void addIVarsForAbsoluteAtom(const AbsoluteAtom& atom) {
- _absoluteAtomIndex[&atom] = _absoluteAtomIvars.size();
- NativeAbsoluteAtomIvarsV1 ivar;
- ivar.nameOffset = getNameOffset(atom);
- ivar.attributesOffset = getAttributeOffset(atom);
- ivar.reserved = 0;
- ivar.value = atom.value();
- _absoluteAtomIvars.push_back(ivar);
- }
-
- void convertReferencesToV1() {
- for (const NativeReferenceIvarsV2 &v2 : _referencesV2) {
- NativeReferenceIvarsV1 v1;
- v1.offsetInAtom = v2.offsetInAtom;
- v1.kindNamespace = v2.kindNamespace;
- v1.kindArch = v2.kindArch;
- v1.kindValue = v2.kindValue;
- v1.targetIndex = (v2.targetIndex == NativeReferenceIvarsV2::noTarget) ?
- (uint16_t)NativeReferenceIvarsV1::noTarget : v2.targetIndex;
- v1.addendIndex = this->getAddendIndex(v2.addend);
- _referencesV1.push_back(v1);
- }
- _referencesV2.clear();
- }
-
- bool canConvertReferenceToV1(const NativeReferenceIvarsV2 &ref) {
- bool validOffset = (ref.offsetInAtom == NativeReferenceIvarsV2::noTarget) ||
- ref.offsetInAtom < NativeReferenceIvarsV1::noTarget;
- return validOffset && ref.targetIndex < UINT16_MAX;
- }
-
- // Convert vector of NativeReferenceIvarsV2 to NativeReferenceIvarsV1 if
- // possible.
- void maybeConvertReferencesToV1() {
- std::set<int64_t> addends;
- for (const NativeReferenceIvarsV2 &ref : _referencesV2) {
- if (!canConvertReferenceToV1(ref))
- return;
- addends.insert(ref.addend);
- if (addends.size() >= UINT16_MAX)
- return;
- }
- convertReferencesToV1();
- }
-
- // fill out native file header and chunk directory
- void makeHeader() {
- const bool hasDefines = !_definedAtomIvars.empty();
- const bool hasUndefines = !_undefinedAtomIvars.empty();
- const bool hasSharedLibraries = !_sharedLibraryAtomIvars.empty();
- const bool hasAbsolutes = !_absoluteAtomIvars.empty();
- const bool hasReferencesV1 = !_referencesV1.empty();
- const bool hasReferencesV2 = !_referencesV2.empty();
- const bool hasTargetsTable = !_targetsTableIndex.empty();
- const bool hasAddendTable = !_addendsTableIndex.empty();
- const bool hasContent = !_contentPool.empty();
-
- int chunkCount = 1; // always have string pool chunk
- if ( hasDefines ) chunkCount += 2;
- if ( hasUndefines ) ++chunkCount;
- if ( hasSharedLibraries ) ++chunkCount;
- if ( hasAbsolutes ) chunkCount += 2;
- if ( hasReferencesV1 ) ++chunkCount;
- if ( hasReferencesV2 ) ++chunkCount;
- if ( hasTargetsTable ) ++chunkCount;
- if ( hasAddendTable ) ++chunkCount;
- if ( hasContent ) ++chunkCount;
-
- _headerBufferSize = sizeof(NativeFileHeader)
- + chunkCount*sizeof(NativeChunk);
- _headerBuffer = reinterpret_cast<NativeFileHeader*>
- (operator new(_headerBufferSize, std::nothrow));
- NativeChunk *chunks =
- reinterpret_cast<NativeChunk*>(reinterpret_cast<char*>(_headerBuffer)
- + sizeof(NativeFileHeader));
- memcpy(_headerBuffer->magic, NATIVE_FILE_HEADER_MAGIC,
- sizeof(_headerBuffer->magic));
- _headerBuffer->endian = NFH_LittleEndian;
- _headerBuffer->architecture = 0;
- _headerBuffer->fileSize = 0;
- _headerBuffer->chunkCount = chunkCount;
-
- // create chunk for defined atom ivar array
- int nextIndex = 0;
- uint32_t nextFileOffset = _headerBufferSize;
- if (hasDefines) {
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _definedAtomIvars,
- NCS_DefinedAtomsV1);
-
- // create chunk for attributes
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _attributes,
- NCS_AttributesArrayV1);
- }
-
- // create chunk for undefined atom array
- if (hasUndefines)
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _undefinedAtomIvars,
- NCS_UndefinedAtomsV1);
-
- // create chunk for shared library atom array
- if (hasSharedLibraries)
- fillChunkHeader(chunks[nextIndex++], nextFileOffset,
- _sharedLibraryAtomIvars, NCS_SharedLibraryAtomsV1);
-
- // create chunk for shared library atom array
- if (hasAbsolutes) {
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _absoluteAtomIvars,
- NCS_AbsoluteAtomsV1);
-
- // create chunk for attributes
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _absAttributes,
- NCS_AbsoluteAttributesV1);
- }
-
- // create chunk for symbol strings
- // pad end of string pool to 4-bytes
- while ((_stringPool.size() % 4) != 0)
- _stringPool.push_back('\0');
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _stringPool,
- NCS_Strings);
-
- // create chunk for referencesV2
- if (hasReferencesV1)
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _referencesV1,
- NCS_ReferencesArrayV1);
-
- // create chunk for referencesV2
- if (hasReferencesV2)
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _referencesV2,
- NCS_ReferencesArrayV2);
-
- // create chunk for target table
- if (hasTargetsTable) {
- NativeChunk& cht = chunks[nextIndex++];
- cht.signature = NCS_TargetsTable;
- cht.fileOffset = nextFileOffset;
- cht.fileSize = _targetsTableIndex.size() * sizeof(uint32_t);
- cht.elementCount = _targetsTableIndex.size();
- nextFileOffset = cht.fileOffset + cht.fileSize;
- }
-
- // create chunk for addend table
- if (hasAddendTable) {
- NativeChunk& chad = chunks[nextIndex++];
- chad.signature = NCS_AddendsTable;
- chad.fileOffset = nextFileOffset;
- chad.fileSize = _addendsTableIndex.size() * sizeof(Reference::Addend);
- chad.elementCount = _addendsTableIndex.size();
- nextFileOffset = chad.fileOffset + chad.fileSize;
- }
-
- // create chunk for content
- if (hasContent)
- fillChunkHeader(chunks[nextIndex++], nextFileOffset, _contentPool,
- NCS_Content);
-
- _headerBuffer->fileSize = nextFileOffset;
- }
-
- template<class T>
- void fillChunkHeader(NativeChunk &chunk, uint32_t &nextFileOffset,
- const std::vector<T> &data, uint32_t signature) {
- chunk.signature = signature;
- chunk.fileOffset = nextFileOffset;
- chunk.fileSize = data.size() * sizeof(T);
- chunk.elementCount = data.size();
- nextFileOffset = chunk.fileOffset + chunk.fileSize;
- }
-
- // scan header to find particular chunk
- NativeChunk& findChunk(uint32_t signature) {
- const uint32_t chunkCount = _headerBuffer->chunkCount;
- NativeChunk* chunks =
- reinterpret_cast<NativeChunk*>(reinterpret_cast<char*>(_headerBuffer)
- + sizeof(NativeFileHeader));
- for (uint32_t i=0; i < chunkCount; ++i) {
- if ( chunks[i].signature == signature )
- return chunks[i];
- }
- llvm_unreachable("findChunk() signature not found");
- }
-
- // append atom name to string pool and return offset
- uint32_t getNameOffset(const Atom& atom) {
- return this->getNameOffset(atom.name());
- }
-
- // check if name is already in pool or append and return offset
- uint32_t getSharedLibraryNameOffset(StringRef name) {
- assert(!name.empty());
- // look to see if this library name was used by another atom
- for (auto &it : _sharedLibraryNames)
- if (name.equals(it.first))
- return it.second;
- // first use of this library name
- uint32_t result = this->getNameOffset(name);
- _sharedLibraryNames.push_back(std::make_pair(name, result));
- return result;
- }
-
- // append atom name to string pool and return offset
- uint32_t getNameOffset(StringRef name) {
- if ( name.empty() )
- return 0;
- uint32_t result = _stringPool.size();
- _stringPool.insert(_stringPool.end(), name.begin(), name.end());
- _stringPool.push_back(0);
- return result;
- }
-
- // append atom cotent to content pool and return offset
- uint32_t getContentOffset(const DefinedAtom& atom) {
- if (!atom.occupiesDiskSpace())
- return 0;
- uint32_t result = _contentPool.size();
- ArrayRef<uint8_t> cont = atom.rawContent();
- _contentPool.insert(_contentPool.end(), cont.begin(), cont.end());
- return result;
- }
-
- // reuse existing attributes entry or create a new one and return offet
- uint32_t getAttributeOffset(const DefinedAtom& atom) {
- NativeAtomAttributesV1 attrs = computeAttributesV1(atom);
- return getOrPushAttribute(_attributes, attrs);
- }
-
- uint32_t getAttributeOffset(const AbsoluteAtom& atom) {
- NativeAtomAttributesV1 attrs = computeAbsoluteAttributes(atom);
- return getOrPushAttribute(_absAttributes, attrs);
- }
-
- uint32_t getOrPushAttribute(std::vector<NativeAtomAttributesV1> &dest,
- const NativeAtomAttributesV1 &attrs) {
- for (size_t i = 0, e = dest.size(); i < e; ++i) {
- if (!memcmp(&dest[i], &attrs, sizeof(attrs))) {
- // found that this set of attributes already used, so re-use
- return i * sizeof(attrs);
- }
- }
- // append new attribute set to end
- uint32_t result = dest.size() * sizeof(attrs);
- dest.push_back(attrs);
- return result;
- }
-
- uint32_t sectionNameOffset(const DefinedAtom& atom) {
- // if section based on content, then no custom section name available
- if (atom.sectionChoice() == DefinedAtom::sectionBasedOnContent)
- return 0;
- StringRef name = atom.customSectionName();
- assert(!name.empty());
- // look to see if this section name was used by another atom
- for (auto &it : _sectionNames)
- if (name.equals(it.first))
- return it.second;
- // first use of this section name
- uint32_t result = this->getNameOffset(name);
- _sectionNames.push_back(std::make_pair(name, result));
- return result;
- }
-
- NativeAtomAttributesV1 computeAttributesV1(const DefinedAtom& atom) {
- NativeAtomAttributesV1 attrs;
- attrs.sectionNameOffset = sectionNameOffset(atom);
- attrs.align2 = atom.alignment().powerOf2;
- attrs.alignModulus = atom.alignment().modulus;
- attrs.scope = atom.scope();
- attrs.interposable = atom.interposable();
- attrs.merge = atom.merge();
- attrs.contentType = atom.contentType();
- attrs.sectionChoice = atom.sectionChoice();
- attrs.deadStrip = atom.deadStrip();
- attrs.dynamicExport = atom.dynamicExport();
- attrs.codeModel = atom.codeModel();
- attrs.permissions = atom.permissions();
- return attrs;
- }
-
- NativeAtomAttributesV1 computeAbsoluteAttributes(const AbsoluteAtom& atom) {
- NativeAtomAttributesV1 attrs;
- attrs.scope = atom.scope();
- return attrs;
- }
-
- // add references for this atom in a contiguous block in NCS_ReferencesArrayV2
- uint32_t getReferencesIndex(const DefinedAtom& atom, unsigned& refsCount) {
- size_t startRefSize = _referencesV2.size();
- uint32_t result = startRefSize;
- for (const Reference *ref : atom) {
- NativeReferenceIvarsV2 nref;
- nref.offsetInAtom = ref->offsetInAtom();
- nref.kindNamespace = (uint8_t)ref->kindNamespace();
- nref.kindArch = (uint8_t)ref->kindArch();
- nref.kindValue = ref->kindValue();
- nref.targetIndex = this->getTargetIndex(ref->target());
- nref.addend = ref->addend();
- nref.tag = ref->tag();
- _referencesV2.push_back(nref);
- }
- refsCount = _referencesV2.size() - startRefSize;
- return (refsCount == 0) ? 0 : result;
- }
-
- uint32_t getTargetIndex(const Atom* target) {
- if ( target == nullptr )
- return NativeReferenceIvarsV2::noTarget;
- TargetToIndex::const_iterator pos = _targetsTableIndex.find(target);
- if ( pos != _targetsTableIndex.end() ) {
- return pos->second;
- }
- uint32_t result = _targetsTableIndex.size();
- _targetsTableIndex[target] = result;
- return result;
- }
-
- void writeTargetTable(raw_ostream &out) {
- // Build table of target indexes
- uint32_t maxTargetIndex = _targetsTableIndex.size();
- assert(maxTargetIndex > 0);
- std::vector<uint32_t> targetIndexes(maxTargetIndex);
- for (auto &it : _targetsTableIndex) {
- const Atom* atom = it.first;
- uint32_t targetIndex = it.second;
- assert(targetIndex < maxTargetIndex);
-
- TargetToIndex::iterator pos = _definedAtomIndex.find(atom);
- if (pos != _definedAtomIndex.end()) {
- targetIndexes[targetIndex] = pos->second;
- continue;
- }
- uint32_t base = _definedAtomIvars.size();
-
- pos = _undefinedAtomIndex.find(atom);
- if (pos != _undefinedAtomIndex.end()) {
- targetIndexes[targetIndex] = pos->second + base;
- continue;
- }
- base += _undefinedAtomIndex.size();
-
- pos = _sharedLibraryAtomIndex.find(atom);
- if (pos != _sharedLibraryAtomIndex.end()) {
- targetIndexes[targetIndex] = pos->second + base;
- continue;
- }
- base += _sharedLibraryAtomIndex.size();
-
- pos = _absoluteAtomIndex.find(atom);
- assert(pos != _absoluteAtomIndex.end());
- targetIndexes[targetIndex] = pos->second + base;
- }
- // write table
- out.write((char*)&targetIndexes[0], maxTargetIndex * sizeof(uint32_t));
- }
-
- uint32_t getAddendIndex(Reference::Addend addend) {
- if ( addend == 0 )
- return 0; // addend index zero is used to mean "no addend"
- AddendToIndex::const_iterator pos = _addendsTableIndex.find(addend);
- if ( pos != _addendsTableIndex.end() ) {
- return pos->second;
- }
- uint32_t result = _addendsTableIndex.size() + 1; // one-based index
- _addendsTableIndex[addend] = result;
- return result;
- }
-
- void writeAddendTable(raw_ostream &out) {
- // Build table of addends
- uint32_t maxAddendIndex = _addendsTableIndex.size();
- std::vector<Reference::Addend> addends(maxAddendIndex);
- for (auto &it : _addendsTableIndex) {
- Reference::Addend addend = it.first;
- uint32_t index = it.second;
- assert(index <= maxAddendIndex);
- addends[index-1] = addend;
- }
- // write table
- out.write((char*)&addends[0], maxAddendIndex*sizeof(Reference::Addend));
- }
-
- typedef std::vector<std::pair<StringRef, uint32_t>> NameToOffsetVector;
-
- typedef llvm::DenseMap<const Atom*, uint32_t> TargetToIndex;
- typedef llvm::DenseMap<Reference::Addend, uint32_t> AddendToIndex;
-
- NativeFileHeader* _headerBuffer;
- size_t _headerBufferSize;
- std::vector<char> _stringPool;
- std::vector<uint8_t> _contentPool;
- std::vector<NativeDefinedAtomIvarsV1> _definedAtomIvars;
- std::vector<NativeAtomAttributesV1> _attributes;
- std::vector<NativeAtomAttributesV1> _absAttributes;
- std::vector<NativeUndefinedAtomIvarsV1> _undefinedAtomIvars;
- std::vector<NativeSharedLibraryAtomIvarsV1> _sharedLibraryAtomIvars;
- std::vector<NativeAbsoluteAtomIvarsV1> _absoluteAtomIvars;
- std::vector<NativeReferenceIvarsV1> _referencesV1;
- std::vector<NativeReferenceIvarsV2> _referencesV2;
- TargetToIndex _targetsTableIndex;
- TargetToIndex _definedAtomIndex;
- TargetToIndex _undefinedAtomIndex;
- TargetToIndex _sharedLibraryAtomIndex;
- TargetToIndex _absoluteAtomIndex;
- AddendToIndex _addendsTableIndex;
- NameToOffsetVector _sectionNames;
- NameToOffsetVector _sharedLibraryNames;
-};
-} // end namespace native
-
-std::unique_ptr<Writer> createWriterNative() {
- return std::unique_ptr<Writer>(new native::Writer());
-}
-} // end namespace lld
diff --git a/lib/ReaderWriter/PECOFF/Atoms.h b/lib/ReaderWriter/PECOFF/Atoms.h
deleted file mode 100644
index 257edc17884b..000000000000
--- a/lib/ReaderWriter/PECOFF/Atoms.h
+++ /dev/null
@@ -1,312 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/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_PE_COFF_ATOMS_H
-#define LLD_READER_WRITER_PE_COFF_ATOMS_H
-
-#include "lld/Core/File.h"
-#include "lld/Core/Simple.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Object/COFF.h"
-#include <vector>
-
-namespace lld {
-namespace pecoff {
-class COFFDefinedAtom;
-
-class COFFUndefinedAtom : public UndefinedAtom {
-public:
- COFFUndefinedAtom(const File &file, StringRef name,
- const UndefinedAtom *fallback = nullptr)
- : _owningFile(file), _name(name), _fallback(fallback) {}
-
- const File &file() const override { return _owningFile; }
- StringRef name() const override { return _name; }
- CanBeNull canBeNull() const override { return CanBeNull::canBeNullNever; }
- const UndefinedAtom *fallback() const override { return _fallback; }
-
-private:
- const File &_owningFile;
- StringRef _name;
- const UndefinedAtom *_fallback;
-};
-
-/// The base class of all COFF defined atoms. A derived class of
-/// COFFBaseDefinedAtom may represent atoms read from a file or atoms created
-/// by the linker. An example of the latter case is the jump table for symbols
-/// in a DLL.
-class COFFBaseDefinedAtom : public DefinedAtom {
-public:
- enum class Kind {
- File,
- Internal
- };
-
- const File &file() const override { return _file; }
- StringRef name() const override { return _name; }
- Interposable interposable() const override { return interposeNo; }
- Merge merge() const override { return mergeNo; }
- Alignment alignment() const override { return Alignment(0); }
- StringRef customSectionName() const override { return ""; }
- DeadStripKind deadStrip() const override { return deadStripNormal; }
-
- Kind getKind() const { return _kind; }
-
- void addReference(std::unique_ptr<SimpleReference> reference) {
- _references.push_back(std::move(reference));
- }
-
- reference_iterator begin() const override {
- return reference_iterator(*this, reinterpret_cast<const void *>(0));
- }
-
- reference_iterator end() const override {
- return reference_iterator(
- *this, reinterpret_cast<const void *>(_references.size()));
- }
-
-protected:
- COFFBaseDefinedAtom(const File &file, StringRef name, Kind kind)
- : _file(file), _name(name), _kind(kind) {}
-
-private:
- const Reference *derefIterator(const void *iter) const override {
- size_t index = reinterpret_cast<size_t>(iter);
- return _references[index].get();
- }
-
- void incrementIterator(const void *&iter) const override {
- size_t index = reinterpret_cast<size_t>(iter);
- iter = reinterpret_cast<const void *>(index + 1);
- }
-
- const File &_file;
- StringRef _name;
- Kind _kind;
- std::vector<std::unique_ptr<SimpleReference>> _references;
-};
-
-/// This is the root class of the atom read from a file. This class have two
-/// subclasses; one for the regular atom and another for the BSS atom.
-class COFFDefinedFileAtom : public COFFBaseDefinedAtom {
-public:
- COFFDefinedFileAtom(const File &file, StringRef name, StringRef sectionName,
- uint64_t sectionSize, Scope scope,
- ContentType contentType, ContentPermissions perms,
- uint64_t ordinal)
- : COFFBaseDefinedAtom(file, name, Kind::File), _sectionName(sectionName),
- _sectionSize(sectionSize), _scope(scope), _contentType(contentType),
- _permissions(perms), _ordinal(ordinal), _alignment(0) {}
-
- static bool classof(const COFFBaseDefinedAtom *atom) {
- return atom->getKind() == Kind::File;
- }
-
- void setAlignment(Alignment val) { _alignment = val; }
- SectionChoice sectionChoice() const override { return sectionCustomRequired; }
- StringRef customSectionName() const override { return _sectionName; }
- uint64_t sectionSize() const override { return _sectionSize; }
- Scope scope() const override { return _scope; }
- ContentType contentType() const override { return _contentType; }
- ContentPermissions permissions() const override { return _permissions; }
- uint64_t ordinal() const override { return _ordinal; }
- Alignment alignment() const override { return _alignment; }
-
- void addAssociate(const DefinedAtom *other) {
- auto *ref = new SimpleReference(Reference::KindNamespace::all,
- Reference::KindArch::all,
- lld::Reference::kindAssociate, 0, other, 0);
- addReference(std::unique_ptr<SimpleReference>(ref));
- }
-
-private:
- StringRef _sectionName;
- uint64_t _sectionSize;
- Scope _scope;
- ContentType _contentType;
- ContentPermissions _permissions;
- uint64_t _ordinal;
- Alignment _alignment;
- std::vector<std::unique_ptr<SimpleReference>> _references;
-};
-
-// A COFFDefinedAtom represents an atom read from a file and has contents.
-class COFFDefinedAtom : public COFFDefinedFileAtom {
-public:
- COFFDefinedAtom(const File &file, StringRef name, StringRef sectionName,
- uint64_t sectionSize, Scope scope, ContentType type,
- bool isComdat, ContentPermissions perms, Merge merge,
- ArrayRef<uint8_t> data, uint64_t ordinal)
- : COFFDefinedFileAtom(file, name, sectionName, sectionSize,
- scope, type, perms, ordinal),
- _isComdat(isComdat), _merge(merge), _dataref(data) {}
-
- Merge merge() const override { return _merge; }
- uint64_t size() const override { return _dataref.size(); }
- ArrayRef<uint8_t> rawContent() const override { return _dataref; }
-
- DeadStripKind deadStrip() const override {
- // Only COMDAT symbols would be dead-stripped.
- return _isComdat ? deadStripNormal : deadStripNever;
- }
-
-private:
- bool _isComdat;
- Merge _merge;
- ArrayRef<uint8_t> _dataref;
-};
-
-// A COFFDefinedAtom represents an atom for BSS section.
-class COFFBSSAtom : public COFFDefinedFileAtom {
-public:
- COFFBSSAtom(const File &file, StringRef name, Scope scope,
- ContentPermissions perms, Merge merge, uint32_t size,
- uint64_t ordinal)
- : COFFDefinedFileAtom(file, name, ".bss", 0, scope, typeZeroFill,
- perms, ordinal),
- _merge(merge), _size(size) {}
-
- Merge merge() const override { return _merge; }
- uint64_t size() const override { return _size; }
- ArrayRef<uint8_t> rawContent() const override { return _contents; }
-
-private:
- Merge _merge;
- uint32_t _size;
- std::vector<uint8_t> _contents;
-};
-
-/// A COFFLinkerInternalAtom represents a defined atom created by the linker,
-/// not read from file.
-class COFFLinkerInternalAtom : public COFFBaseDefinedAtom {
-public:
- SectionChoice sectionChoice() const override { return sectionBasedOnContent; }
- uint64_t ordinal() const override { return _ordinal; }
- Scope scope() const override { return scopeGlobal; }
- Alignment alignment() const override { return Alignment(0); }
- uint64_t size() const override { return _data.size(); }
- ArrayRef<uint8_t> rawContent() const override { return _data; }
-
-protected:
- COFFLinkerInternalAtom(const File &file, uint64_t ordinal,
- std::vector<uint8_t> data, StringRef symbolName = "")
- : COFFBaseDefinedAtom(file, symbolName, Kind::Internal),
- _ordinal(ordinal), _data(std::move(data)) {}
-
-private:
- uint64_t _ordinal;
- std::vector<uint8_t> _data;
-};
-
-class COFFStringAtom : public COFFLinkerInternalAtom {
-public:
- COFFStringAtom(const File &file, uint64_t ordinal, StringRef sectionName,
- StringRef contents)
- : COFFLinkerInternalAtom(file, ordinal, stringRefToVector(contents)),
- _sectionName(sectionName) {}
-
- SectionChoice sectionChoice() const override { return sectionCustomRequired; }
- StringRef customSectionName() const override { return _sectionName; }
- ContentType contentType() const override { return typeData; }
- ContentPermissions permissions() const override { return permR__; }
-
-private:
- StringRef _sectionName;
-
- std::vector<uint8_t> stringRefToVector(StringRef name) const {
- std::vector<uint8_t> ret(name.size() + 1);
- memcpy(&ret[0], name.data(), name.size());
- ret[name.size()] = 0;
- return ret;
- }
-};
-
-// A COFFSharedLibraryAtom represents a symbol for data in an import library. A
-// reference to a COFFSharedLibraryAtom will be transformed to a real reference
-// to an import address table entry in Idata pass.
-class COFFSharedLibraryAtom : public SharedLibraryAtom {
-public:
- COFFSharedLibraryAtom(const File &file, uint16_t hint, StringRef symbolName,
- StringRef importName, StringRef dllName)
- : _file(file), _hint(hint), _mangledName(addImpPrefix(symbolName)),
- _importName(importName), _dllName(dllName), _importTableEntry(nullptr) {
- }
-
- const File &file() const override { return _file; }
- uint16_t hint() const { return _hint; }
-
- /// Returns the symbol name to be used by the core linker.
- StringRef name() const override { return _mangledName; }
-
- /// Returns the symbol name to be used in the import description table in the
- /// COFF header.
- virtual StringRef importName() const { return _importName; }
-
- StringRef loadName() const override { return _dllName; }
- bool canBeNullAtRuntime() const override { return false; }
- Type type() const override { return Type::Unknown; }
- uint64_t size() const override { return 0; }
-
- void setImportTableEntry(const DefinedAtom *atom) {
- _importTableEntry = atom;
- }
-
- const DefinedAtom *getImportTableEntry() const { return _importTableEntry; }
-
-private:
- /// Mangle the symbol name by adding "__imp_" prefix. See the file comment of
- /// ReaderImportHeader.cpp for details about the prefix.
- std::string addImpPrefix(StringRef symbolName) {
- std::string ret("__imp_");
- ret.append(symbolName);
- return ret;
- }
-
- const File &_file;
- uint16_t _hint;
- std::string _mangledName;
- std::string _importName;
- StringRef _dllName;
- const DefinedAtom *_importTableEntry;
-};
-
-// An instance of this class represents "input file" for atoms created in a
-// pass. Atoms need to be associated to an input file even if it's not read from
-// a file, so we use this class for that.
-class VirtualFile : public SimpleFile {
-public:
- VirtualFile(const LinkingContext &ctx)
- : SimpleFile("<virtual-file>"), _nextOrdinal(0) {
- setOrdinal(ctx.getNextOrdinalAndIncrement());
- }
-
- uint64_t getNextOrdinal() { return _nextOrdinal++; }
-
-private:
- uint64_t _nextOrdinal;
-};
-
-//===----------------------------------------------------------------------===//
-//
-// Utility functions to handle layout edges.
-//
-//===----------------------------------------------------------------------===//
-
-template <typename T, typename U>
-void addLayoutEdge(T *a, U *b, uint32_t which) {
- auto ref = new SimpleReference(Reference::KindNamespace::all,
- Reference::KindArch::all,
- which, 0, b, 0);
- a->addReference(std::unique_ptr<SimpleReference>(ref));
-}
-
-} // namespace pecoff
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/PECOFF/CMakeLists.txt b/lib/ReaderWriter/PECOFF/CMakeLists.txt
deleted file mode 100644
index 86b49b79f194..000000000000
--- a/lib/ReaderWriter/PECOFF/CMakeLists.txt
+++ /dev/null
@@ -1,16 +0,0 @@
-add_llvm_library(lldPECOFF
- EdataPass.cpp
- IdataPass.cpp
- LinkerGeneratedSymbolFile.cpp
- LoadConfigPass.cpp
- PECOFFLinkingContext.cpp
- Pass.cpp
- ReaderCOFF.cpp
- ReaderImportHeader.cpp
- WriterImportLibrary.cpp
- WriterPECOFF.cpp
- LINK_LIBS
- lldCore
- LLVMObject
- LLVMSupport
- )
diff --git a/lib/ReaderWriter/PECOFF/EdataPass.cpp b/lib/ReaderWriter/PECOFF/EdataPass.cpp
deleted file mode 100644
index ad79f171f3c9..000000000000
--- a/lib/ReaderWriter/PECOFF/EdataPass.cpp
+++ /dev/null
@@ -1,227 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/EdataPass.cpp ------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Pass.h"
-#include "EdataPass.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Pass.h"
-#include "lld/Core/Simple.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Path.h"
-#include <climits>
-#include <ctime>
-#include <utility>
-
-using lld::pecoff::edata::EdataAtom;
-using lld::pecoff::edata::TableEntry;
-using llvm::object::export_address_table_entry;
-using llvm::object::export_directory_table_entry;
-
-namespace lld {
-namespace pecoff {
-
-typedef PECOFFLinkingContext::ExportDesc ExportDesc;
-
-// dedupExports removes duplicate export entries. If two exports are
-// referring the same symbol, they are considered duplicates.
-// This could happen if the same symbol name is specified as an argument
-// to /export more than once, or an unmangled and mangled name of the
-// same symbol are given to /export. In the latter case, we choose
-// unmangled (shorter) name.
-static void dedupExports(PECOFFLinkingContext &ctx) {
- std::vector<ExportDesc> &exports = ctx.getDllExports();
- // Pass 1: find duplicate entries
- std::set<const ExportDesc *> dup;
- std::map<StringRef, ExportDesc *> map;
- for (ExportDesc &exp : exports) {
- if (!exp.externalName.empty())
- continue;
- StringRef symbol = exp.getRealName();
- auto it = map.find(symbol);
- if (it == map.end()) {
- map[symbol] = &exp;
- } else if (symbol.size() < it->second->getRealName().size()) {
- map[symbol] = &exp;
- dup.insert(it->second);
- } else {
- dup.insert(&exp);
- }
- }
- // Pass 2: remove duplicate entries
- auto pred = [&](const ExportDesc &exp) {
- return dup.count(&exp) == 1;
- };
- exports.erase(std::remove_if(exports.begin(), exports.end(), pred),
- exports.end());
-}
-
-static void assignOrdinals(PECOFFLinkingContext &ctx) {
- std::vector<ExportDesc> &exports = ctx.getDllExports();
- int maxOrdinal = -1;
- for (ExportDesc &desc : exports)
- maxOrdinal = std::max(maxOrdinal, desc.ordinal);
-
- std::sort(exports.begin(), exports.end(),
- [](const ExportDesc &a, const ExportDesc &b) {
- return a.getExternalName().compare(b.getExternalName()) < 0;
- });
-
- int nextOrdinal = (maxOrdinal == -1) ? 1 : (maxOrdinal + 1);
- for (ExportDesc &desc : exports)
- if (desc.ordinal == -1)
- desc.ordinal = nextOrdinal++;
-}
-
-static bool getExportedAtoms(PECOFFLinkingContext &ctx, MutableFile *file,
- std::vector<TableEntry> &ret) {
- std::map<StringRef, const DefinedAtom *> definedAtoms;
- for (const DefinedAtom *atom : file->defined())
- definedAtoms[atom->name()] = atom;
-
- for (PECOFFLinkingContext::ExportDesc &desc : ctx.getDllExports()) {
- auto it = definedAtoms.find(desc.getRealName());
- if (it == definedAtoms.end()) {
- llvm::errs() << "Symbol <" << desc.name
- << "> is exported but not defined.\n";
- return false;
- }
- const DefinedAtom *atom = it->second;
-
- // One can export a symbol with a different name than the symbol
- // name used in DLL. If such name is specified, use it in the
- // .edata section.
- ret.push_back(TableEntry(ctx.undecorateSymbol(desc.getExternalName()),
- desc.ordinal, atom, desc.noname));
- }
- std::sort(ret.begin(), ret.end(),
- [](const TableEntry &a, const TableEntry &b) {
- return a.exportName.compare(b.exportName) < 0;
- });
-
- return true;
-}
-
-static std::pair<int, int> getOrdinalBase(std::vector<TableEntry> &entries) {
- int ordinalBase = INT_MAX;
- int maxOrdinal = -1;
- for (TableEntry &e : entries) {
- ordinalBase = std::min(ordinalBase, e.ordinal);
- maxOrdinal = std::max(maxOrdinal, e.ordinal);
- }
- return std::pair<int, int>(ordinalBase, maxOrdinal);
-}
-
-edata::EdataAtom *
-EdataPass::createAddressTable(const std::vector<TableEntry> &entries,
- int ordinalBase, int maxOrdinal) {
- EdataAtom *addressTable =
- new (_alloc) EdataAtom(_file, sizeof(export_address_table_entry) *
- (maxOrdinal - ordinalBase + 1));
-
- for (const TableEntry &e : entries) {
- int index = e.ordinal - ordinalBase;
- size_t offset = index * sizeof(export_address_table_entry);
- addDir32NBReloc(addressTable, e.atom, _ctx.getMachineType(), offset);
- }
- return addressTable;
-}
-
-edata::EdataAtom *
-EdataPass::createNamePointerTable(const PECOFFLinkingContext &ctx,
- const std::vector<TableEntry> &entries,
- MutableFile *file) {
- EdataAtom *table =
- new (_alloc) EdataAtom(_file, sizeof(uint32_t) * entries.size());
-
- size_t offset = 0;
- for (const TableEntry &e : entries) {
- auto *stringAtom = new (_alloc) COFFStringAtom(
- _file, _stringOrdinal++, ".edata", e.exportName);
- file->addAtom(*stringAtom);
- addDir32NBReloc(table, stringAtom, _ctx.getMachineType(), offset);
- offset += sizeof(uint32_t);
- }
- return table;
-}
-
-edata::EdataAtom *EdataPass::createExportDirectoryTable(
- const std::vector<edata::TableEntry> &namedEntries, int ordinalBase,
- int maxOrdinal) {
- EdataAtom *ret =
- new (_alloc) EdataAtom(_file, sizeof(export_directory_table_entry));
- auto *data = ret->getContents<export_directory_table_entry>();
- data->TimeDateStamp = time(nullptr);
- data->OrdinalBase = ordinalBase;
- data->AddressTableEntries = maxOrdinal - ordinalBase + 1;
- data->NumberOfNamePointers = namedEntries.size();
- return ret;
-}
-
-edata::EdataAtom *
-EdataPass::createOrdinalTable(const std::vector<TableEntry> &entries,
- int ordinalBase) {
- EdataAtom *ret =
- new (_alloc) EdataAtom(_file, sizeof(uint16_t) * entries.size());
- uint16_t *data = ret->getContents<uint16_t>();
- int i = 0;
- for (const TableEntry &e : entries)
- data[i++] = e.ordinal - ordinalBase;
- return ret;
-}
-
-void EdataPass::perform(std::unique_ptr<MutableFile> &file) {
- dedupExports(_ctx);
- assignOrdinals(_ctx);
-
- std::vector<TableEntry> entries;
- if (!getExportedAtoms(_ctx, file.get(), entries))
- return;
- if (entries.empty())
- return;
-
- int ordinalBase, maxOrdinal;
- std::tie(ordinalBase, maxOrdinal) = getOrdinalBase(entries);
-
- std::vector<TableEntry> namedEntries;
- for (TableEntry &e : entries)
- if (!e.noname)
- namedEntries.push_back(e);
-
- EdataAtom *table =
- createExportDirectoryTable(namedEntries, ordinalBase, maxOrdinal);
- file->addAtom(*table);
-
- COFFStringAtom *dllName =
- new (_alloc) COFFStringAtom(_file, _stringOrdinal++, ".edata",
- llvm::sys::path::filename(_ctx.outputPath()));
- file->addAtom(*dllName);
- addDir32NBReloc(table, dllName, _ctx.getMachineType(),
- offsetof(export_directory_table_entry, NameRVA));
-
- EdataAtom *addressTable =
- createAddressTable(entries, ordinalBase, maxOrdinal);
- file->addAtom(*addressTable);
- addDir32NBReloc(
- table, addressTable, _ctx.getMachineType(),
- offsetof(export_directory_table_entry, ExportAddressTableRVA));
-
- EdataAtom *namePointerTable =
- createNamePointerTable(_ctx, namedEntries, file.get());
- file->addAtom(*namePointerTable);
- addDir32NBReloc(table, namePointerTable, _ctx.getMachineType(),
- offsetof(export_directory_table_entry, NamePointerRVA));
-
- EdataAtom *ordinalTable = createOrdinalTable(namedEntries, ordinalBase);
- file->addAtom(*ordinalTable);
- addDir32NBReloc(table, ordinalTable, _ctx.getMachineType(),
- offsetof(export_directory_table_entry, OrdinalTableRVA));
-}
-
-} // namespace pecoff
-} // namespace lld
diff --git a/lib/ReaderWriter/PECOFF/EdataPass.h b/lib/ReaderWriter/PECOFF/EdataPass.h
deleted file mode 100644
index 442be3ca24aa..000000000000
--- a/lib/ReaderWriter/PECOFF/EdataPass.h
+++ /dev/null
@@ -1,99 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/EdataPass.h --------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file \brief This linker pass creates atoms for the DLL export
-/// information. The defined atoms constructed in this pass will go into .edata
-/// section.
-///
-/// For the details of the .edata section format, see Microsoft PE/COFF
-/// Specification section 5.3, The .edata Section.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_PE_COFF_EDATA_PASS_H
-#define LLD_READER_WRITER_PE_COFF_EDATA_PASS_H
-
-#include "Atoms.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Pass.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/PECOFFLinkingContext.h"
-#include "llvm/Support/COFF.h"
-#include <map>
-
-using llvm::COFF::ImportDirectoryTableEntry;
-
-namespace lld {
-namespace pecoff {
-namespace edata {
-
-struct TableEntry {
- TableEntry(StringRef exp, int ord, const DefinedAtom *a, bool n)
- : exportName(exp), ordinal(ord), atom(a), noname(n) {}
- std::string exportName;
- int ordinal;
- const DefinedAtom *atom;
- bool noname;
-};
-
-/// The root class of all edata atoms.
-class EdataAtom : public COFFLinkerInternalAtom {
-public:
- EdataAtom(VirtualFile &file, size_t size)
- : COFFLinkerInternalAtom(file, file.getNextOrdinal(),
- std::vector<uint8_t>(size)) {}
-
- SectionChoice sectionChoice() const override { return sectionCustomRequired; }
- StringRef customSectionName() const override { return ".edata"; }
- ContentType contentType() const override { return typeData; }
- ContentPermissions permissions() const override { return permR__; }
-
- template <typename T> T *getContents() const {
- return (T *)const_cast<uint8_t *>(rawContent().data());
- }
-};
-
-} // namespace edata
-
-class EdataPass : public lld::Pass {
-public:
- EdataPass(PECOFFLinkingContext &ctx)
- : _ctx(ctx), _file(ctx), _is64(ctx.is64Bit()), _stringOrdinal(1024) {}
-
- void perform(std::unique_ptr<MutableFile> &file) override;
-
-private:
- edata::EdataAtom *
- createExportDirectoryTable(const std::vector<edata::TableEntry> &namedEntries,
- int ordinalBase, int maxOrdinal);
-
- edata::EdataAtom *
- createAddressTable(const std::vector<edata::TableEntry> &entries,
- int ordinalBase, int maxOrdinal);
-
- edata::EdataAtom *
- createNamePointerTable(const PECOFFLinkingContext &ctx,
- const std::vector<edata::TableEntry> &entries,
- MutableFile *file);
-
- edata::EdataAtom *
- createOrdinalTable(const std::vector<edata::TableEntry> &entries,
- int ordinalBase);
-
- PECOFFLinkingContext &_ctx;
- VirtualFile _file;
- bool _is64;
- int _stringOrdinal;
- mutable llvm::BumpPtrAllocator _alloc;
-};
-
-} // namespace pecoff
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/PECOFF/IdataPass.cpp b/lib/ReaderWriter/PECOFF/IdataPass.cpp
deleted file mode 100644
index d41ef581f7fa..000000000000
--- a/lib/ReaderWriter/PECOFF/IdataPass.cpp
+++ /dev/null
@@ -1,345 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/IdataPass.cpp ------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "IdataPass.h"
-#include "Pass.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Pass.h"
-#include "lld/Core/Simple.h"
-#include "llvm/Support/COFF.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Endian.h"
-#include <algorithm>
-#include <cstddef>
-#include <cstring>
-#include <map>
-#include <vector>
-
-using namespace llvm::support::endian;
-using llvm::object::delay_import_directory_table_entry;
-
-namespace lld {
-namespace pecoff {
-namespace idata {
-
-IdataAtom::IdataAtom(IdataContext &context, std::vector<uint8_t> data)
- : COFFLinkerInternalAtom(context.dummyFile,
- context.dummyFile.getNextOrdinal(), data) {
- context.file.addAtom(*this);
-}
-
-HintNameAtom::HintNameAtom(IdataContext &context, uint16_t hint,
- StringRef importName)
- : IdataAtom(context, assembleRawContent(hint, importName)),
- _importName(importName) {}
-
-std::vector<uint8_t> HintNameAtom::assembleRawContent(uint16_t hint,
- StringRef importName) {
- size_t size =
- llvm::RoundUpToAlignment(sizeof(hint) + importName.size() + 1, 2);
- std::vector<uint8_t> ret(size);
- ret[importName.size()] = 0;
- ret[importName.size() - 1] = 0;
- write16le(&ret[0], hint);
- std::memcpy(&ret[2], importName.data(), importName.size());
- return ret;
-}
-
-std::vector<uint8_t>
-ImportTableEntryAtom::assembleRawContent(uint64_t rva, bool is64) {
- // The element size of the import table is 32 bit in PE and 64 bit
- // in PE+. In PE+, bits 62-31 are filled with zero.
- if (is64) {
- std::vector<uint8_t> ret(8);
- write64le(&ret[0], rva);
- return ret;
- }
- std::vector<uint8_t> ret(4);
- write32le(&ret[0], rva);
- return ret;
-}
-
-static std::vector<ImportTableEntryAtom *>
-createImportTableAtoms(IdataContext &context,
- const std::vector<COFFSharedLibraryAtom *> &sharedAtoms,
- bool shouldAddReference, StringRef sectionName,
- llvm::BumpPtrAllocator &alloc) {
- std::vector<ImportTableEntryAtom *> ret;
- for (COFFSharedLibraryAtom *atom : sharedAtoms) {
- ImportTableEntryAtom *entry = nullptr;
- if (atom->importName().empty()) {
- // Import by ordinal
- uint64_t hint = atom->hint();
- hint |= context.ctx.is64Bit() ? (uint64_t(1) << 63) : (uint64_t(1) << 31);
- entry = new (alloc) ImportTableEntryAtom(context, hint, sectionName);
- } else {
- // Import by name
- entry = new (alloc) ImportTableEntryAtom(context, 0, sectionName);
- HintNameAtom *hintName =
- new (alloc) HintNameAtom(context, atom->hint(), atom->importName());
- addDir32NBReloc(entry, hintName, context.ctx.getMachineType(), 0);
- }
- ret.push_back(entry);
- if (shouldAddReference)
- atom->setImportTableEntry(entry);
- }
- // Add the NULL entry.
- ret.push_back(new (alloc) ImportTableEntryAtom(context, 0, sectionName));
- return ret;
-}
-
-// Creates atoms for an import lookup table. The import lookup table is an
-// array of pointers to hint/name atoms. The array needs to be terminated with
-// the NULL entry.
-void ImportDirectoryAtom::addRelocations(
- IdataContext &context, StringRef loadName,
- const std::vector<COFFSharedLibraryAtom *> &sharedAtoms) {
- // Create parallel arrays. The contents of the two are initially the
- // same. The PE/COFF loader overwrites the import address tables with the
- // pointers to the referenced items after loading the executable into
- // memory.
- std::vector<ImportTableEntryAtom *> importLookupTables =
- createImportTableAtoms(context, sharedAtoms, false, ".idata.t", _alloc);
- std::vector<ImportTableEntryAtom *> importAddressTables =
- createImportTableAtoms(context, sharedAtoms, true, ".idata.a", _alloc);
-
- addDir32NBReloc(this, importLookupTables[0], context.ctx.getMachineType(),
- offsetof(ImportDirectoryTableEntry, ImportLookupTableRVA));
- addDir32NBReloc(this, importAddressTables[0], context.ctx.getMachineType(),
- offsetof(ImportDirectoryTableEntry, ImportAddressTableRVA));
- auto *atom = new (_alloc)
- COFFStringAtom(context.dummyFile, context.dummyFile.getNextOrdinal(),
- ".idata", loadName);
- context.file.addAtom(*atom);
- addDir32NBReloc(this, atom, context.ctx.getMachineType(),
- offsetof(ImportDirectoryTableEntry, NameRVA));
-}
-
-// Create the contents for the delay-import table.
-std::vector<uint8_t> DelayImportDirectoryAtom::createContent() {
- std::vector<uint8_t> r(sizeof(delay_import_directory_table_entry), 0);
- auto entry = reinterpret_cast<delay_import_directory_table_entry *>(&r[0]);
- // link.exe seems to set 1 to Attributes field, so do we.
- entry->Attributes = 1;
- return r;
-}
-
-// Find "___delayLoadHelper2@8" (or "__delayLoadHelper2" on x64).
-// This is not efficient but should be OK for now.
-static const Atom *
-findDelayLoadHelper(MutableFile &file, const PECOFFLinkingContext &ctx) {
- StringRef sym = ctx.getDelayLoadHelperName();
- for (const DefinedAtom *atom : file.defined())
- if (atom->name() == sym)
- return atom;
- std::string msg = (sym + " was not found").str();
- llvm_unreachable(msg.c_str());
-}
-
-// Create the data referred by the delay-import table.
-void DelayImportDirectoryAtom::addRelocations(
- IdataContext &context, StringRef loadName,
- const std::vector<COFFSharedLibraryAtom *> &sharedAtoms) {
- // "ModuleHandle" field. This points to an array of pointer-size data
- // in ".data" section. Initially the array is initialized with zero.
- // The delay-load import helper will set DLL base address at runtime.
- auto *hmodule = new (_alloc) DelayImportAddressAtom(context);
- addDir32NBReloc(this, hmodule, context.ctx.getMachineType(),
- offsetof(delay_import_directory_table_entry, ModuleHandle));
-
- // "NameTable" field. The data structure of this field is the same
- // as (non-delay) import table's Import Lookup Table. Contains
- // imported function names. This is a parallel array of AddressTable
- // field.
- std::vector<ImportTableEntryAtom *> nameTable =
- createImportTableAtoms(context, sharedAtoms, false, ".didat", _alloc);
- addDir32NBReloc(
- this, nameTable[0], context.ctx.getMachineType(),
- offsetof(delay_import_directory_table_entry, DelayImportNameTable));
-
- // "Name" field. This points to the NUL-terminated DLL name string.
- auto *name = new (_alloc)
- COFFStringAtom(context.dummyFile, context.dummyFile.getNextOrdinal(),
- ".didat", loadName);
- context.file.addAtom(*name);
- addDir32NBReloc(this, name, context.ctx.getMachineType(),
- offsetof(delay_import_directory_table_entry, Name));
-
- // "AddressTable" field. This points to an array of pointers, which
- // in turn pointing to delay-load functions.
- std::vector<DelayImportAddressAtom *> addrTable;
- for (int i = 0, e = sharedAtoms.size() + 1; i < e; ++i)
- addrTable.push_back(new (_alloc) DelayImportAddressAtom(context));
- for (int i = 0, e = sharedAtoms.size(); i < e; ++i)
- sharedAtoms[i]->setImportTableEntry(addrTable[i]);
- addDir32NBReloc(
- this, addrTable[0], context.ctx.getMachineType(),
- offsetof(delay_import_directory_table_entry, DelayImportAddressTable));
-
- const Atom *delayLoadHelper = findDelayLoadHelper(context.file, context.ctx);
- for (int i = 0, e = sharedAtoms.size(); i < e; ++i) {
- const DefinedAtom *loader = new (_alloc) DelayLoaderAtom(
- context, addrTable[i], this, delayLoadHelper);
- if (context.ctx.is64Bit())
- addDir64Reloc(addrTable[i], loader, context.ctx.getMachineType(), 0);
- else
- addDir32Reloc(addrTable[i], loader, context.ctx.getMachineType(), 0);
- }
-}
-
-DelayLoaderAtom::DelayLoaderAtom(IdataContext &context, const Atom *impAtom,
- const Atom *descAtom, const Atom *delayLoadHelperAtom)
- : IdataAtom(context, createContent(context.ctx.getMachineType())) {
- MachineTypes machine = context.ctx.getMachineType();
- switch (machine) {
- case llvm::COFF::IMAGE_FILE_MACHINE_I386:
- addDir32Reloc(this, impAtom, machine, 3);
- addDir32Reloc(this, descAtom, machine, 8);
- addRel32Reloc(this, delayLoadHelperAtom, machine, 13);
- break;
- case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
- addRel32Reloc(this, impAtom, machine, 36);
- addRel32Reloc(this, descAtom, machine, 43);
- addRel32Reloc(this, delayLoadHelperAtom, machine, 48);
- break;
- default:
- llvm::report_fatal_error("unsupported machine type");
- }
-}
-
-// DelayLoaderAtom contains a wrapper function for __delayLoadHelper2.
-//
-// __delayLoadHelper2 takes two pointers: a pointer to the delay-load
-// table descripter and a pointer to _imp_ symbol for the function
-// to be resolved.
-//
-// __delayLoadHelper2 looks at the table descriptor to know the DLL
-// name, calls dlopen()-like function to load it, resolves all
-// imported symbols, and then writes the resolved addresses to the
-// import address table. It returns a pointer to the resolved
-// function.
-//
-// __delayLoadHelper2 is defined in delayimp.lib.
-std::vector<uint8_t>
-DelayLoaderAtom::createContent(MachineTypes machine) const {
- static const uint8_t x86[] = {
- 0x51, // push ecx
- 0x52, // push edx
- 0x68, 0, 0, 0, 0, // push offset ___imp__<FUNCNAME>
- 0x68, 0, 0, 0, 0, // push offset ___DELAY_IMPORT_DESCRIPTOR_<DLLNAME>_dll
- 0xE8, 0, 0, 0, 0, // call ___delayLoadHelper2@8
- 0x5A, // pop edx
- 0x59, // pop ecx
- 0xFF, 0xE0, // jmp eax
- };
- static const uint8_t x64[] = {
- 0x51, // push rcx
- 0x52, // push rdx
- 0x41, 0x50, // push r8
- 0x41, 0x51, // push r9
- 0x48, 0x83, 0xEC, 0x48, // sub rsp, 48h
- 0x66, 0x0F, 0x7F, 0x04, 0x24, // movdqa xmmword ptr [rsp], xmm0
- 0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa xmmword ptr [rsp+10h], xmm1
- 0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h], xmm2
- 0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h], xmm3
- 0x48, 0x8D, 0x15, 0, 0, 0, 0, // lea rdx, [__imp_<FUNCNAME>]
- 0x48, 0x8D, 0x0D, 0, 0, 0, 0, // lea rcx, [___DELAY_IMPORT_...]
- 0xE8, 0, 0, 0, 0, // call __delayLoadHelper2
- 0x66, 0x0F, 0x6F, 0x04, 0x24, // movdqa xmm0, xmmword ptr [rsp]
- 0x66, 0x0F, 0x6F, 0x4C, 0x24, 0x10, // movdqa xmm1, xmmword ptr [rsp+10h]
- 0x66, 0x0F, 0x6F, 0x54, 0x24, 0x20, // movdqa xmm2, xmmword ptr [rsp+20h]
- 0x66, 0x0F, 0x6F, 0x5C, 0x24, 0x30, // movdqa xmm3, xmmword ptr [rsp+30h]
- 0x48, 0x83, 0xC4, 0x48, // add rsp, 48h
- 0x41, 0x59, // pop r9
- 0x41, 0x58, // pop r8
- 0x5A, // pop rdx
- 0x59, // pop rcx
- 0xFF, 0xE0, // jmp rax
- };
- switch (machine) {
- case llvm::COFF::IMAGE_FILE_MACHINE_I386:
- return std::vector<uint8_t>(x86, x86 + sizeof(x86));
- case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
- return std::vector<uint8_t>(x64, x64 + sizeof(x64));
- default:
- llvm::report_fatal_error("unsupported machine type");
- }
-}
-
-} // namespace idata
-
-void IdataPass::perform(std::unique_ptr<MutableFile> &file) {
- if (file->sharedLibrary().empty())
- return;
-
- idata::IdataContext context(*file, _dummyFile, _ctx);
- std::map<StringRef, std::vector<COFFSharedLibraryAtom *>> sharedAtoms =
- groupByLoadName(*file);
- bool hasImports = false;
- bool hasDelayImports = false;
-
- // Create the import table and terminate it with the null entry.
- for (auto i : sharedAtoms) {
- StringRef loadName = i.first;
- if (_ctx.isDelayLoadDLL(loadName))
- continue;
- hasImports = true;
- std::vector<COFFSharedLibraryAtom *> &atoms = i.second;
- new (_alloc) idata::ImportDirectoryAtom(context, loadName, atoms);
- }
- if (hasImports)
- new (_alloc) idata::NullImportDirectoryAtom(context);
-
- // Create the delay import table and terminate it with the null entry.
- for (auto i : sharedAtoms) {
- StringRef loadName = i.first;
- if (!_ctx.isDelayLoadDLL(loadName))
- continue;
- hasDelayImports = true;
- std::vector<COFFSharedLibraryAtom *> &atoms = i.second;
- new (_alloc) idata::DelayImportDirectoryAtom(context, loadName, atoms);
- }
- if (hasDelayImports)
- new (_alloc) idata::DelayNullImportDirectoryAtom(context);
-
- replaceSharedLibraryAtoms(*file);
-}
-
-std::map<StringRef, std::vector<COFFSharedLibraryAtom *> >
-IdataPass::groupByLoadName(MutableFile &file) {
- std::map<StringRef, COFFSharedLibraryAtom *> uniqueAtoms;
- for (const SharedLibraryAtom *atom : file.sharedLibrary())
- uniqueAtoms[atom->name()] =
- (COFFSharedLibraryAtom *)const_cast<SharedLibraryAtom *>(atom);
-
- std::map<StringRef, std::vector<COFFSharedLibraryAtom *> > ret;
- for (auto i : uniqueAtoms) {
- COFFSharedLibraryAtom *atom = i.second;
- ret[atom->loadName()].push_back(atom);
- }
- return ret;
-}
-
-/// Transforms a reference to a COFFSharedLibraryAtom to a real reference.
-void IdataPass::replaceSharedLibraryAtoms(MutableFile &file) {
- for (const DefinedAtom *atom : file.defined()) {
- for (const Reference *ref : *atom) {
- const Atom *target = ref->target();
- auto *sharedAtom = dyn_cast<SharedLibraryAtom>(target);
- if (!sharedAtom)
- continue;
- const auto *coffSharedAtom = (const COFFSharedLibraryAtom *)sharedAtom;
- const DefinedAtom *entry = coffSharedAtom->getImportTableEntry();
- const_cast<Reference *>(ref)->setTarget(entry);
- }
- }
-}
-
-} // namespace pecoff
-} // namespace lld
diff --git a/lib/ReaderWriter/PECOFF/IdataPass.h b/lib/ReaderWriter/PECOFF/IdataPass.h
deleted file mode 100644
index 9db82160339a..000000000000
--- a/lib/ReaderWriter/PECOFF/IdataPass.h
+++ /dev/null
@@ -1,218 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/IdataPass.h---------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file \brief This linker pass creates atoms for the DLL import
-/// information. The defined atoms constructed in this pass will go into .idata
-/// section, unless .idata section is merged with other section such as .data.
-///
-/// For the details of the .idata section format, see Microsoft PE/COFF
-/// Specification section 5.4, The .idata Section.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_PE_COFF_IDATA_PASS_H
-#define LLD_READER_WRITER_PE_COFF_IDATA_PASS_H
-
-#include "Atoms.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Pass.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/PECOFFLinkingContext.h"
-#include "llvm/Support/COFF.h"
-#include <algorithm>
-#include <map>
-
-using llvm::COFF::ImportDirectoryTableEntry;
-
-namespace lld {
-namespace pecoff {
-namespace idata {
-
-class DLLNameAtom;
-class HintNameAtom;
-class ImportTableEntryAtom;
-
-// A state object of this pass.
-struct IdataContext {
- IdataContext(MutableFile &f, VirtualFile &g, const PECOFFLinkingContext &c)
- : file(f), dummyFile(g), ctx(c) {}
- MutableFile &file;
- VirtualFile &dummyFile;
- const PECOFFLinkingContext &ctx;
-};
-
-/// The root class of all idata atoms.
-class IdataAtom : public COFFLinkerInternalAtom {
-public:
- SectionChoice sectionChoice() const override { return sectionCustomRequired; }
- StringRef customSectionName() const override { return ".idata"; }
- ContentType contentType() const override { return typeData; }
- ContentPermissions permissions() const override { return permR__; }
-
-protected:
- IdataAtom(IdataContext &context, std::vector<uint8_t> data);
-};
-
-/// A HintNameAtom represents a symbol that will be imported from a DLL at
-/// runtime. It consists with an optional hint, which is a small integer, and a
-/// symbol name.
-///
-/// A hint is an index of the export pointer table in a DLL. If the import
-/// library and DLL is in sync (i.e., ".lib" and ".dll" is for the same version
-/// or the symbol ordinal is maintained by hand with ".exp" file), the PE/COFF
-/// loader can find the symbol quickly.
-class HintNameAtom : public IdataAtom {
-public:
- HintNameAtom(IdataContext &context, uint16_t hint, StringRef importName);
-
- StringRef getContentString() { return _importName; }
-
-private:
- std::vector<uint8_t> assembleRawContent(uint16_t hint, StringRef importName);
- StringRef _importName;
-};
-
-class ImportTableEntryAtom : public IdataAtom {
-public:
- ImportTableEntryAtom(IdataContext &ctx, uint64_t contents,
- StringRef sectionName)
- : IdataAtom(ctx, assembleRawContent(contents, ctx.ctx.is64Bit())),
- _sectionName(sectionName) {}
-
- StringRef customSectionName() const override {
- return _sectionName;
- };
-
-private:
- std::vector<uint8_t> assembleRawContent(uint64_t contents, bool is64);
- StringRef _sectionName;
-};
-
-/// An ImportDirectoryAtom includes information to load a DLL, including a DLL
-/// name, symbols that will be resolved from the DLL, and the import address
-/// table that are overwritten by the loader with the pointers to the referenced
-/// items. The executable has one ImportDirectoryAtom per one imported DLL.
-class ImportDirectoryAtom : public IdataAtom {
-public:
- ImportDirectoryAtom(IdataContext &context, StringRef loadName,
- const std::vector<COFFSharedLibraryAtom *> &sharedAtoms)
- : IdataAtom(context, std::vector<uint8_t>(20, 0)) {
- addRelocations(context, loadName, sharedAtoms);
- }
-
- StringRef customSectionName() const override { return ".idata.d"; }
-
-private:
- void addRelocations(IdataContext &context, StringRef loadName,
- const std::vector<COFFSharedLibraryAtom *> &sharedAtoms);
-
- mutable llvm::BumpPtrAllocator _alloc;
-};
-
-/// The last NULL entry in the import directory.
-class NullImportDirectoryAtom : public IdataAtom {
-public:
- explicit NullImportDirectoryAtom(IdataContext &context)
- : IdataAtom(context, std::vector<uint8_t>(20, 0)) {}
-
- StringRef customSectionName() const override { return ".idata.d"; }
-};
-
-/// The class for the the delay-load import table.
-class DelayImportDirectoryAtom : public IdataAtom {
-public:
- DelayImportDirectoryAtom(
- IdataContext &context, StringRef loadName,
- const std::vector<COFFSharedLibraryAtom *> &sharedAtoms)
- : IdataAtom(context, createContent()) {
- addRelocations(context, loadName, sharedAtoms);
- }
-
- StringRef customSectionName() const override { return ".didat.d"; }
-
-private:
- std::vector<uint8_t> createContent();
- void addRelocations(IdataContext &context, StringRef loadName,
- const std::vector<COFFSharedLibraryAtom *> &sharedAtoms);
-
- mutable llvm::BumpPtrAllocator _alloc;
-};
-
-/// Terminator of the delay-load import table. The content of this atom is all
-/// zero.
-class DelayNullImportDirectoryAtom : public IdataAtom {
-public:
- explicit DelayNullImportDirectoryAtom(IdataContext &context)
- : IdataAtom(context, createContent()) {}
- StringRef customSectionName() const override { return ".didat.d"; }
-
-private:
- std::vector<uint8_t> createContent() const {
- return std::vector<uint8_t>(
- sizeof(llvm::object::delay_import_directory_table_entry), 0);
- }
-};
-
-class DelayImportAddressAtom : public IdataAtom {
-public:
- explicit DelayImportAddressAtom(IdataContext &context)
- : IdataAtom(context, createContent(context.ctx)),
- _align(Alignment(context.ctx.is64Bit() ? 3 : 2)) {}
- StringRef customSectionName() const override { return ".data"; }
- ContentPermissions permissions() const override { return permRW_; }
- Alignment alignment() const override { return _align; }
-
-private:
- std::vector<uint8_t> createContent(const PECOFFLinkingContext &ctx) const {
- return std::vector<uint8_t>(ctx.is64Bit() ? 8 : 4, 0);
- }
-
- Alignment _align;
-};
-
-// DelayLoaderAtom contains a wrapper function for __delayLoadHelper2.
-class DelayLoaderAtom : public IdataAtom {
-public:
- DelayLoaderAtom(IdataContext &context, const Atom *impAtom,
- const Atom *descAtom, const Atom *delayLoadHelperAtom);
- StringRef customSectionName() const override { return ".text"; }
- ContentPermissions permissions() const override { return permR_X; }
- Alignment alignment() const override { return Alignment(0); }
-
-private:
- std::vector<uint8_t> createContent(MachineTypes machine) const;
-};
-
-} // namespace idata
-
-class IdataPass : public lld::Pass {
-public:
- IdataPass(const PECOFFLinkingContext &ctx) : _dummyFile(ctx), _ctx(ctx) {}
-
- void perform(std::unique_ptr<MutableFile> &file) override;
-
-private:
- std::map<StringRef, std::vector<COFFSharedLibraryAtom *>>
- groupByLoadName(MutableFile &file);
-
- void replaceSharedLibraryAtoms(MutableFile &file);
-
- // A dummy file with which all the atoms created in the pass will be
- // associated. Atoms need to be associated to an input file even if it's not
- // read from a file, so we use this object.
- VirtualFile _dummyFile;
-
- const PECOFFLinkingContext &_ctx;
- llvm::BumpPtrAllocator _alloc;
-};
-
-} // namespace pecoff
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/PECOFF/InferSubsystemPass.h b/lib/ReaderWriter/PECOFF/InferSubsystemPass.h
deleted file mode 100644
index cbf863ee4784..000000000000
--- a/lib/ReaderWriter/PECOFF/InferSubsystemPass.h
+++ /dev/null
@@ -1,66 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/InferSubsystemPass.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_PE_COFF_INFER_SUBSYSTEM_PASS_H
-#define LLD_READER_WRITER_PE_COFF_INFER_SUBSYSTEM_PASS_H
-
-#include "Atoms.h"
-#include "lld/Core/Pass.h"
-#include <vector>
-
-namespace lld {
-namespace pecoff {
-
-// Infers subsystem from entry point function name.
-class InferSubsystemPass : public lld::Pass {
-public:
- InferSubsystemPass(PECOFFLinkingContext &ctx) : _ctx(ctx) {}
-
- void perform(std::unique_ptr<MutableFile> &file) override {
- if (_ctx.getSubsystem() != WindowsSubsystem::IMAGE_SUBSYSTEM_UNKNOWN)
- return;
-
- if (_ctx.isDll()) {
- _ctx.setSubsystem(WindowsSubsystem::IMAGE_SUBSYSTEM_WINDOWS_GUI);
- return;
- }
-
- // Scan the resolved symbols to infer the subsystem.
- const std::string wWinMain = _ctx.decorateSymbol("wWinMainCRTStartup");
- const std::string wWinMainAt = _ctx.decorateSymbol("wWinMainCRTStartup@");
- const std::string winMain = _ctx.decorateSymbol("WinMainCRTStartup");
- const std::string winMainAt = _ctx.decorateSymbol("WinMainCRTStartup@");
- const std::string wmain = _ctx.decorateSymbol("wmainCRTStartup");
- const std::string wmainAt = _ctx.decorateSymbol("wmainCRTStartup@");
- const std::string main = _ctx.decorateSymbol("mainCRTStartup");
- const std::string mainAt = _ctx.decorateSymbol("mainCRTStartup@");
-
- for (const DefinedAtom *atom : file->definedAtoms()) {
- if (atom->name() == wWinMain || atom->name().startswith(wWinMainAt) ||
- atom->name() == winMain || atom->name().startswith(winMainAt)) {
- _ctx.setSubsystem(WindowsSubsystem::IMAGE_SUBSYSTEM_WINDOWS_GUI);
- return;
- }
- if (atom->name() == wmain || atom->name().startswith(wmainAt) ||
- atom->name() == main || atom->name().startswith(mainAt)) {
- _ctx.setSubsystem(WindowsSubsystem::IMAGE_SUBSYSTEM_WINDOWS_CUI);
- return;
- }
- }
- llvm::report_fatal_error("Failed to infer subsystem");
- }
-
-private:
- PECOFFLinkingContext &_ctx;
-};
-
-} // namespace pecoff
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.cpp b/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.cpp
deleted file mode 100644
index a11410784b8c..000000000000
--- a/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.cpp --------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "LinkerGeneratedSymbolFile.h"
-
-namespace lld {
-namespace pecoff {
-
-// Find decorated symbol, namely /sym@[0-9]+/ or /\?sym@@.+/.
-bool findDecoratedSymbol(PECOFFLinkingContext *ctx,
- std::string sym, std::string &res) {
- const std::set<std::string> &defined = ctx->definedSymbols();
- // Search for /sym@[0-9]+/
- {
- std::string s = sym + '@';
- auto it = defined.lower_bound(s);
- for (auto e = defined.end(); it != e; ++it) {
- if (!StringRef(*it).startswith(s))
- break;
- if (it->size() == s.size())
- continue;
- StringRef suffix = StringRef(*it).substr(s.size());
- if (suffix.find_first_not_of("0123456789") != StringRef::npos)
- continue;
- res = *it;
- return true;
- }
- }
- // Search for /\?sym@@.+/
- {
- std::string s = "?" + ctx->undecorateSymbol(sym).str() + "@@";
- auto it = defined.lower_bound(s);
- if (it != defined.end() && StringRef(*it).startswith(s)) {
- res = *it;
- return true;
- }
- }
- return false;
-}
-
-} // namespace pecoff
-} // namespace lld
diff --git a/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h b/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h
deleted file mode 100644
index b9764d70bb3b..000000000000
--- a/lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h
+++ /dev/null
@@ -1,309 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/LinkerGeneratedSymbolFile.h ----------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Atoms.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/PECOFFLinkingContext.h"
-#include "llvm/Support/Allocator.h"
-#include <algorithm>
-#include <mutex>
-
-using llvm::COFF::WindowsSubsystem;
-
-namespace lld {
-namespace pecoff {
-
-bool findDecoratedSymbol(PECOFFLinkingContext *ctx,
- std::string sym, std::string &res);
-
-namespace impl {
-
-/// The defined atom for dllexported symbols with __imp_ prefix.
-class ImpPointerAtom : public COFFLinkerInternalAtom {
-public:
- ImpPointerAtom(const File &file, StringRef symbolName, uint64_t ordinal)
- : COFFLinkerInternalAtom(file, /*oridnal*/ 0, std::vector<uint8_t>(4),
- symbolName),
- _ordinal(ordinal) {}
-
- uint64_t ordinal() const override { return _ordinal; }
- Scope scope() const override { return scopeGlobal; }
- ContentType contentType() const override { return typeData; }
- Alignment alignment() const override { return Alignment(4); }
- ContentPermissions permissions() const override { return permR__; }
-
-private:
- uint64_t _ordinal;
-};
-
-class ImpSymbolFile : public SimpleFile {
-public:
- ImpSymbolFile(StringRef defsym, StringRef undefsym, uint64_t ordinal,
- bool is64)
- : SimpleFile(defsym), _undefined(*this, undefsym),
- _defined(*this, defsym, ordinal) {
- SimpleReference *ref;
- if (is64) {
- ref = new SimpleReference(Reference::KindNamespace::COFF,
- Reference::KindArch::x86_64,
- llvm::COFF::IMAGE_REL_AMD64_ADDR32,
- 0, &_undefined, 0);
- } else {
- ref = new SimpleReference(Reference::KindNamespace::COFF,
- Reference::KindArch::x86,
- llvm::COFF::IMAGE_REL_I386_DIR32,
- 0, &_undefined, 0);
- }
- _defined.addReference(std::unique_ptr<SimpleReference>(ref));
- addAtom(_defined);
- addAtom(_undefined);
- };
-
-private:
- SimpleUndefinedAtom _undefined;
- ImpPointerAtom _defined;
-};
-
-// A file to make Resolver to resolve a symbol TO instead of a symbol FROM,
-// using fallback mechanism for an undefined symbol. One can virtually rename an
-// undefined symbol using this file.
-class SymbolRenameFile : public SimpleFile {
-public:
- SymbolRenameFile(StringRef from, StringRef to)
- : SimpleFile("<symbol-rename>"), _fromSym(from), _toSym(to),
- _from(*this, _fromSym, &_to), _to(*this, _toSym) {
- addAtom(_from);
- };
-
-private:
- std::string _fromSym;
- std::string _toSym;
- COFFUndefinedAtom _from;
- COFFUndefinedAtom _to;
-};
-
-} // namespace impl
-
-// A virtual file containing absolute symbol __ImageBase. __ImageBase (or
-// ___ImageBase on x86) is a linker-generated symbol whose address is the same
-// as the image base address.
-class LinkerGeneratedSymbolFile : public SimpleFile {
-public:
- LinkerGeneratedSymbolFile(const PECOFFLinkingContext &ctx)
- : SimpleFile("<linker-internal-file>"),
- _imageBaseAtom(*this, ctx.decorateSymbol("__ImageBase"),
- Atom::scopeGlobal, ctx.getBaseAddress()) {
- addAtom(_imageBaseAtom);
- };
-
-private:
- SimpleAbsoluteAtom _imageBaseAtom;
-};
-
-// A LocallyImporteSymbolFile is an archive file containing __imp_
-// symbols for local use.
-//
-// For each defined symbol, linker creates an implicit defined symbol
-// by appending "__imp_" prefix to the original name. The content of
-// the implicit symbol is a pointer to the original symbol
-// content. This feature allows one to compile and link the following
-// code without error, although _imp__hello is not defined in the
-// code. (the leading "_" in this example is automatically appended,
-// assuming it's x86.)
-//
-// void hello() { printf("Hello\n"); }
-// extern void (*_imp__hello)();
-// int main() {
-// _imp__hello();
-// return 0;
-// }
-//
-// This odd feature is for the compatibility with MSVC link.exe.
-class LocallyImportedSymbolFile : public SimpleArchiveLibraryFile {
-public:
- LocallyImportedSymbolFile(const PECOFFLinkingContext &ctx)
- : SimpleArchiveLibraryFile("__imp_"), _is64(ctx.is64Bit()),
- _ordinal(0) {}
-
- File *find(StringRef sym, bool dataSymbolOnly) override {
- std::string prefix = "__imp_";
- if (!sym.startswith(prefix))
- return nullptr;
- StringRef undef = sym.substr(prefix.size());
- return new (_alloc) impl::ImpSymbolFile(sym, undef, _ordinal++, _is64);
- }
-
-private:
- bool _is64;
- uint64_t _ordinal;
- llvm::BumpPtrAllocator _alloc;
-};
-
-// A ExportedSymbolRenameFile is a virtual archive file for dllexported symbols.
-//
-// One usually has to specify the exact symbol name to resolve it. That's true
-// in most cases for PE/COFF, except the one described below.
-//
-// DLLExported symbols can be specified using a module definition file. In a
-// file, one can write an EXPORT directive followed by symbol names. Such
-// symbols may not be fully decorated.
-//
-// If a symbol FOO is specified to be dllexported by a module definition file,
-// linker has to search not only for /FOO/ but also for /FOO@[0-9]+/ for stdcall
-// and for /\?FOO@@.+/ for C++. This ambiguous matching semantics does not fit
-// well with Resolver.
-//
-// We could probably modify Resolver to resolve ambiguous symbols, but I think
-// we don't want to do that because it'd be rarely used, and only this Windows
-// specific feature would use it. It's probably not a good idea to make the core
-// linker to be able to deal with it.
-//
-// So, instead of tweaking Resolver, we chose to do some hack here. An
-// ExportedSymbolRenameFile maintains a set containing all possibly defined
-// symbol names. That set would be a union of (1) all the defined symbols that
-// are already parsed and read and (2) all the defined symbols in archive files
-// that are not yet be parsed.
-//
-// If Resolver asks this file to return an atom for a dllexported symbol, find()
-// looks up the set, doing ambiguous matching. If there's a symbol with @
-// prefix, it returns an atom to rename the dllexported symbol, hoping that
-// Resolver will find the new symbol with atsign from an archive file at the
-// next visit.
-class ExportedSymbolRenameFile : public SimpleArchiveLibraryFile {
-public:
- ExportedSymbolRenameFile(const PECOFFLinkingContext &ctx)
- : SimpleArchiveLibraryFile("<export>"),
- _ctx(const_cast<PECOFFLinkingContext *>(&ctx)) {
- for (PECOFFLinkingContext::ExportDesc &desc : _ctx->getDllExports())
- _exportedSyms.insert(desc.name);
- }
-
- File *find(StringRef sym, bool dataSymbolOnly) override {
- typedef PECOFFLinkingContext::ExportDesc ExportDesc;
- if (_exportedSyms.count(sym) == 0)
- return nullptr;
- std::string replace;
- if (!findDecoratedSymbol(_ctx, sym.str(), replace))
- return nullptr;
-
- for (ExportDesc &exp : _ctx->getDllExports())
- if (exp.name == sym)
- exp.mangledName = replace;
- if (_ctx->deadStrip())
- _ctx->addDeadStripRoot(_ctx->allocate(replace));
- return new (_alloc) impl::SymbolRenameFile(sym, replace);
- }
-
-private:
- std::set<std::string> _exportedSyms;
- llvm::BumpPtrAllocator _alloc;
- PECOFFLinkingContext *_ctx;
-};
-
-// Windows has not only one but many entry point functions. The
-// appropriate one is automatically selected based on the subsystem
-// setting and the user-supplied entry point function.
-//
-// http://msdn.microsoft.com/en-us/library/f9t8842e.aspx
-class EntryPointFile : public SimpleFile {
-public:
- EntryPointFile(const PECOFFLinkingContext &ctx)
- : SimpleFile("<entry>"), _ctx(const_cast<PECOFFLinkingContext *>(&ctx)),
- _firstTime(true) {}
-
- const atom_collection<UndefinedAtom> &undefined() const override {
- return const_cast<EntryPointFile *>(this)->getUndefinedAtoms();
- }
-
-private:
- const atom_collection<UndefinedAtom> &getUndefinedAtoms() {
- std::lock_guard<std::mutex> lock(_mutex);
- if (!_firstTime)
- return _undefinedAtoms;
- _firstTime = false;
-
- if (_ctx->hasEntry()) {
- StringRef entrySym = _ctx->allocate(getEntry());
- _undefinedAtoms._atoms.push_back(
- new (_alloc) SimpleUndefinedAtom(*this, entrySym));
- _ctx->setHasEntry(true);
- _ctx->setEntrySymbolName(entrySym);
- if (_ctx->deadStrip())
- _ctx->addDeadStripRoot(entrySym);
- }
- return _undefinedAtoms;
- }
-
- // Returns the entry point function name.
- std::string getEntry() const {
- StringRef opt = _ctx->getEntrySymbolName();
- if (!opt.empty()) {
- std::string mangled;
- if (findDecoratedSymbol(_ctx, opt, mangled))
- return mangled;
- return _ctx->decorateSymbol(opt);
- }
- return _ctx->decorateSymbol(getDefaultEntry());
- }
-
- std::string getDefaultEntry() const {
- const std::string wWinMainCRTStartup = "wWinMainCRTStartup";
- const std::string WinMainCRTStartup = "WinMainCRTStartup";
- const std::string wmainCRTStartup = "wmainCRTStartup";
- const std::string mainCRTStartup = "mainCRTStartup";
-
- if (_ctx->isDll()) {
- if (_ctx->getMachineType() == llvm::COFF::IMAGE_FILE_MACHINE_I386)
- return "_DllMainCRTStartup@12";
- return "_DllMainCRTStartup";
- }
-
- // Returns true if a given name exists in an input object file.
- auto defined = [&](StringRef name) -> bool {
- StringRef sym = _ctx->decorateSymbol(name);
- if (_ctx->definedSymbols().count(sym))
- return true;
- std::string ignore;
- return findDecoratedSymbol(_ctx, sym, ignore);
- };
-
- switch (_ctx->getSubsystem()) {
- case WindowsSubsystem::IMAGE_SUBSYSTEM_UNKNOWN: {
- if (defined("wWinMain"))
- return wWinMainCRTStartup;
- if (defined("WinMain"))
- return WinMainCRTStartup;
- if (defined("wmain"))
- return wmainCRTStartup;
- if (!defined("main"))
- llvm::errs() << "Cannot infer subsystem; assuming /subsystem:console\n";
- return mainCRTStartup;
- }
- case WindowsSubsystem::IMAGE_SUBSYSTEM_WINDOWS_GUI:
- if (defined("WinMain"))
- return WinMainCRTStartup;
- return wWinMainCRTStartup;
- case WindowsSubsystem::IMAGE_SUBSYSTEM_WINDOWS_CUI:
- if (defined("wmain"))
- return wmainCRTStartup;
- return mainCRTStartup;
- default:
- return mainCRTStartup;
- }
- }
-
- PECOFFLinkingContext *_ctx;
- atom_collection_vector<UndefinedAtom> _undefinedAtoms;
- std::mutex _mutex;
- llvm::BumpPtrAllocator _alloc;
- bool _firstTime;
-};
-
-} // end namespace pecoff
-} // end namespace lld
diff --git a/lib/ReaderWriter/PECOFF/LoadConfigPass.cpp b/lib/ReaderWriter/PECOFF/LoadConfigPass.cpp
deleted file mode 100644
index be2f5627f4ea..000000000000
--- a/lib/ReaderWriter/PECOFF/LoadConfigPass.cpp
+++ /dev/null
@@ -1,75 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/LoadConfigPass.cpp -------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// A Load Configuration is a data structure for x86 containing an address of the
-// SEH handler table. The Data Directory in the file header points to a load
-// configuration. Technically that indirection is not needed but exists for
-// historical reasons.
-//
-// If the file being handled has .sxdata section containing SEH handler table,
-// this pass will create a Load Configuration atom.
-//
-//===----------------------------------------------------------------------===//
-
-#include "Pass.h"
-#include "LoadConfigPass.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Pass.h"
-#include "lld/Core/Simple.h"
-#include "llvm/Object/COFF.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Path.h"
-#include <climits>
-#include <ctime>
-#include <utility>
-
-using llvm::object::coff_load_configuration32;
-
-namespace lld {
-namespace pecoff {
-namespace loadcfg {
-
-LoadConfigAtom::LoadConfigAtom(VirtualFile &file, const DefinedAtom *sxdata,
- int count)
- : COFFLinkerInternalAtom(
- file, file.getNextOrdinal(),
- std::vector<uint8_t>(sizeof(coff_load_configuration32))) {
- addDir32Reloc(
- this, sxdata, llvm::COFF::IMAGE_FILE_MACHINE_I386,
- offsetof(llvm::object::coff_load_configuration32, SEHandlerTable));
- auto *data = getContents<llvm::object::coff_load_configuration32>();
- data->SEHandlerCount = count;
-}
-
-} // namespace loadcfg
-
-void LoadConfigPass::perform(std::unique_ptr<MutableFile> &file) {
- if (_ctx.noSEH())
- return;
-
- // Find the first atom in .sxdata section.
- const DefinedAtom *sxdata = nullptr;
- int sectionSize = 0;
- for (const DefinedAtom *atom : file->defined()) {
- if (atom->customSectionName() == ".sxdata") {
- if (!sxdata)
- sxdata = atom;
- sectionSize += sxdata->size();
- }
- }
- if (!sxdata)
- return;
-
- auto *loadcfg = new (_alloc)
- loadcfg::LoadConfigAtom(_file, sxdata, sectionSize / sizeof(uint32_t));
- file->addAtom(*loadcfg);
-}
-
-} // namespace pecoff
-} // namespace lld
diff --git a/lib/ReaderWriter/PECOFF/LoadConfigPass.h b/lib/ReaderWriter/PECOFF/LoadConfigPass.h
deleted file mode 100644
index 9f4a25f2b10e..000000000000
--- a/lib/ReaderWriter/PECOFF/LoadConfigPass.h
+++ /dev/null
@@ -1,63 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/LoadConfigPass.h ---------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file \brief This linker pass creates an atom for Load Configuration
-/// structure.
-///
-/// For the details of the Load Configuration structure, see Microsoft PE/COFF
-/// Specification section 5.8. The Load Configuration Structure (Image Only).
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_PE_COFF_LOAD_CONFIG_PASS_H
-#define LLD_READER_WRITER_PE_COFF_LOAD_CONFIG_PASS_H
-
-#include "Atoms.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Pass.h"
-#include "lld/Core/Simple.h"
-#include "lld/ReaderWriter/PECOFFLinkingContext.h"
-#include <map>
-
-namespace lld {
-namespace pecoff {
-namespace loadcfg {
-
-class LoadConfigAtom : public COFFLinkerInternalAtom {
-public:
- LoadConfigAtom(VirtualFile &file, const DefinedAtom *sxdata, int count);
-
- SectionChoice sectionChoice() const override { return sectionCustomRequired; }
- StringRef customSectionName() const override { return ".loadcfg"; }
- ContentType contentType() const override { return typeData; }
- ContentPermissions permissions() const override { return permR__; }
-
- template <typename T> T *getContents() const {
- return (T *)const_cast<uint8_t *>(rawContent().data());
- }
-};
-
-} // namespace loadcfg
-
-class LoadConfigPass : public lld::Pass {
-public:
- LoadConfigPass(PECOFFLinkingContext &ctx) : _ctx(ctx), _file(ctx) {}
-
- void perform(std::unique_ptr<MutableFile> &file) override;
-
-private:
- PECOFFLinkingContext &_ctx;
- VirtualFile _file;
- mutable llvm::BumpPtrAllocator _alloc;
-};
-
-} // namespace pecoff
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/PECOFF/Makefile b/lib/ReaderWriter/PECOFF/Makefile
deleted file mode 100644
index 3ad16969bba7..000000000000
--- a/lib/ReaderWriter/PECOFF/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-##===- lld/lib/ReaderWriter/PECOFF/Makefile --------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL := ../../..
-LIBRARYNAME := lldPECOFF
-USEDLIBS = lldCore.a
-
-include $(LLD_LEVEL)/Makefile
diff --git a/lib/ReaderWriter/PECOFF/OrderPass.h b/lib/ReaderWriter/PECOFF/OrderPass.h
deleted file mode 100644
index 73133ff73638..000000000000
--- a/lib/ReaderWriter/PECOFF/OrderPass.h
+++ /dev/null
@@ -1,67 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/OrderPass.h -------------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file \brief This pass sorts atoms by section name, so that they will appear
-/// in the correct order in the output.
-///
-/// In COFF, sections will be merged into one section by the linker if their
-/// names are the same after discarding the "$" character and all characters
-/// follow it from their names. The characters following the "$" character
-/// determines the merge order. Assume there's an object file containing four
-/// data sections in the following order.
-///
-/// - .data$2
-/// - .data$3
-/// - .data$1
-/// - .data
-///
-/// In this case, the resulting binary should have ".data" section with the
-/// contents of ".data", ".data$1", ".data$2" and ".data$3" in that order.
-///
-//===----------------------------------------------------------------------===//
-
-#ifndef LLD_READER_WRITER_PE_COFF_ORDER_PASS_H
-#define LLD_READER_WRITER_PE_COFF_ORDER_PASS_H
-
-#include "Atoms.h"
-#include "lld/Core/Parallel.h"
-#include "lld/Core/Pass.h"
-#include <algorithm>
-
-namespace lld {
-namespace pecoff {
-
-static bool compare(const DefinedAtom *lhs, const DefinedAtom *rhs) {
- bool lhsCustom = (lhs->sectionChoice() == DefinedAtom::sectionCustomRequired);
- bool rhsCustom = (rhs->sectionChoice() == DefinedAtom::sectionCustomRequired);
- if (lhsCustom && rhsCustom) {
- int cmp = lhs->customSectionName().compare(rhs->customSectionName());
- if (cmp != 0)
- return cmp < 0;
- return DefinedAtom::compareByPosition(lhs, rhs);
- }
- if (lhsCustom && !rhsCustom)
- return true;
- if (!lhsCustom && rhsCustom)
- return false;
- return DefinedAtom::compareByPosition(lhs, rhs);
-}
-
-class OrderPass : public lld::Pass {
-public:
- void perform(std::unique_ptr<MutableFile> &file) override {
- MutableFile::DefinedAtomRange defined = file->definedAtoms();
- parallel_sort(defined.begin(), defined.end(), compare);
- }
-};
-
-} // namespace pecoff
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/PECOFF/PDBPass.h b/lib/ReaderWriter/PECOFF/PDBPass.h
deleted file mode 100644
index 0efa054db823..000000000000
--- a/lib/ReaderWriter/PECOFF/PDBPass.h
+++ /dev/null
@@ -1,43 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/PDBPass.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_PE_COFF_PDB_PASS_H
-#define LLD_READER_WRITER_PE_COFF_PDB_PASS_H
-
-#include "lld/Core/Pass.h"
-#include "llvm/ADT/StringRef.h"
-#include "llvm/Support/Process.h"
-
-namespace lld {
-namespace pecoff {
-
-class PDBPass : public lld::Pass {
-public:
- PDBPass(PECOFFLinkingContext &ctx) : _ctx(ctx) {}
-
- void perform(std::unique_ptr<MutableFile> &file) override {
- if (_ctx.getDebug())
- touch(_ctx.getPDBFilePath());
- }
-
-private:
- void touch(StringRef path) {
- int fd;
- if (llvm::sys::fs::openFileForWrite(path, fd, llvm::sys::fs::F_Append))
- llvm::report_fatal_error("failed to create a PDB file");
- llvm::sys::Process::SafelyCloseFileDescriptor(fd);
- }
-
- PECOFFLinkingContext &_ctx;
-};
-
-} // namespace pecoff
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp b/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
deleted file mode 100644
index 6a657e33541d..000000000000
--- a/lib/ReaderWriter/PECOFF/PECOFFLinkingContext.cpp
+++ /dev/null
@@ -1,352 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/PECOFFLinkingContext.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 "EdataPass.h"
-#include "IdataPass.h"
-#include "InferSubsystemPass.h"
-#include "LinkerGeneratedSymbolFile.h"
-#include "LoadConfigPass.h"
-#include "OrderPass.h"
-#include "PDBPass.h"
-#include "lld/Core/PassManager.h"
-#include "lld/Core/Reader.h"
-#include "lld/Core/Simple.h"
-#include "lld/Core/Writer.h"
-#include "lld/ReaderWriter/PECOFFLinkingContext.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/SmallString.h"
-#include "llvm/Support/Allocator.h"
-#include "llvm/Support/Path.h"
-#include <bitset>
-#include <climits>
-#include <set>
-
-namespace lld {
-
-bool PECOFFLinkingContext::validateImpl(raw_ostream &diagnostics) {
- if (_stackReserve < _stackCommit) {
- diagnostics << "Invalid stack size: reserve size must be equal to or "
- << "greater than commit size, but got " << _stackCommit
- << " and " << _stackReserve << ".\n";
- return false;
- }
-
- if (_heapReserve < _heapCommit) {
- diagnostics << "Invalid heap size: reserve size must be equal to or "
- << "greater than commit size, but got " << _heapCommit
- << " and " << _heapReserve << ".\n";
- return false;
- }
-
- // It's an error if the base address is not multiple of 64K.
- if (getBaseAddress() & 0xffff) {
- diagnostics << "Base address have to be multiple of 64K, but got "
- << getBaseAddress() << "\n";
- return false;
- }
-
- // Specifing /noentry without /dll is an error.
- if (!hasEntry() && !isDll()) {
- diagnostics << "/noentry must be specified with /dll\n";
- return false;
- }
-
- // Check for duplicate export ordinals.
- std::set<int> exports;
- for (const PECOFFLinkingContext::ExportDesc &desc : getDllExports()) {
- if (desc.ordinal == -1)
- continue;
- if (exports.count(desc.ordinal) == 1) {
- diagnostics << "Duplicate export ordinals: " << desc.ordinal << "\n";
- return false;
- }
- exports.insert(desc.ordinal);
- }
-
- // Check for /align.
- std::bitset<64> alignment(_sectionDefaultAlignment);
- if (alignment.count() != 1) {
- diagnostics << "Section alignment must be a power of 2, but got "
- << _sectionDefaultAlignment << "\n";
- return false;
- }
-
- _writer = createWriterPECOFF(*this);
- return true;
-}
-
-const std::set<std::string> &PECOFFLinkingContext::definedSymbols() {
- std::lock_guard<std::recursive_mutex> lock(_mutex);
- for (std::unique_ptr<Node> &node : getNodes()) {
- if (_seen.count(node.get()) > 0)
- continue;
- FileNode *fnode = dyn_cast<FileNode>(node.get());
- if (!fnode)
- continue;
- File *file = fnode->getFile();
- if (file->parse())
- continue;
- if (auto *archive = dyn_cast<ArchiveLibraryFile>(file)) {
- for (const std::string &sym : archive->getDefinedSymbols())
- _definedSyms.insert(sym);
- continue;
- }
- for (const DefinedAtom *atom : file->defined())
- if (!atom->name().empty())
- _definedSyms.insert(atom->name());
- }
- return _definedSyms;
-}
-
-std::unique_ptr<File> PECOFFLinkingContext::createEntrySymbolFile() const {
- return LinkingContext::createEntrySymbolFile("<command line option /entry>");
-}
-
-std::unique_ptr<File> PECOFFLinkingContext::createUndefinedSymbolFile() const {
- return LinkingContext::createUndefinedSymbolFile(
- "<command line option /include>");
-}
-
-static int getGroupStartPos(std::vector<std::unique_ptr<Node>> &nodes) {
- for (int i = 0, e = nodes.size(); i < e; ++i)
- if (GroupEnd *group = dyn_cast<GroupEnd>(nodes[i].get()))
- return i - group->getSize();
- llvm::report_fatal_error("internal error");
-}
-
-void PECOFFLinkingContext::addLibraryFile(std::unique_ptr<FileNode> file) {
- GroupEnd *currentGroupEnd;
- int pos = -1;
- std::vector<std::unique_ptr<Node>> &elements = getNodes();
- for (int i = 0, e = elements.size(); i < e; ++i) {
- if ((currentGroupEnd = dyn_cast<GroupEnd>(elements[i].get()))) {
- pos = i;
- break;
- }
- }
- assert(pos >= 0);
- elements.insert(elements.begin() + pos, std::move(file));
- elements[pos + 1] = llvm::make_unique<GroupEnd>(
- currentGroupEnd->getSize() + 1);
-}
-
-bool PECOFFLinkingContext::createImplicitFiles(
- std::vector<std::unique_ptr<File>> &) {
- std::vector<std::unique_ptr<Node>> &members = getNodes();
-
- // Create a file for the entry point function.
- std::unique_ptr<FileNode> entry(new FileNode(
- llvm::make_unique<pecoff::EntryPointFile>(*this)));
- members.insert(members.begin() + getGroupStartPos(members), std::move(entry));
-
- // Create a file for __ImageBase.
- std::unique_ptr<FileNode> fileNode(new FileNode(
- llvm::make_unique<pecoff::LinkerGeneratedSymbolFile>(*this)));
- members.push_back(std::move(fileNode));
-
- // Create a file for _imp_ symbols.
- std::unique_ptr<FileNode> impFileNode(new FileNode(
- llvm::make_unique<pecoff::LocallyImportedSymbolFile>(*this)));
- members.push_back(std::move(impFileNode));
-
- // Create a file for dllexported symbols.
- std::unique_ptr<FileNode> exportNode(new FileNode(
- llvm::make_unique<pecoff::ExportedSymbolRenameFile>(*this)));
- addLibraryFile(std::move(exportNode));
-
- return true;
-}
-
-/// Returns the section name in the resulting executable.
-///
-/// Sections in object files are usually output to the executable with the same
-/// name, but you can rename by command line option. /merge:from=to makes the
-/// linker to combine "from" section contents to "to" section in the
-/// executable. We have a mapping for the renaming. This method looks up the
-/// table and returns a new section name if renamed.
-StringRef
-PECOFFLinkingContext::getOutputSectionName(StringRef sectionName) const {
- auto it = _renamedSections.find(sectionName);
- if (it == _renamedSections.end())
- return sectionName;
- return getOutputSectionName(it->second);
-}
-
-/// Adds a mapping to the section renaming table. This method will be used for
-/// /merge command line option.
-bool PECOFFLinkingContext::addSectionRenaming(raw_ostream &diagnostics,
- StringRef from, StringRef to) {
- auto it = _renamedSections.find(from);
- if (it != _renamedSections.end()) {
- if (it->second == to)
- // There's already the same mapping.
- return true;
- diagnostics << "Section \"" << from << "\" is already mapped to \""
- << it->second << ", so it cannot be mapped to \"" << to << "\".";
- return true;
- }
-
- // Add a mapping, and check if there's no cycle in the renaming mapping. The
- // cycle detection algorithm we use here is naive, but that's OK because the
- // number of mapping is usually less than 10.
- _renamedSections[from] = to;
- for (auto elem : _renamedSections) {
- StringRef sectionName = elem.first;
- std::set<StringRef> visited;
- visited.insert(sectionName);
- for (;;) {
- auto pos = _renamedSections.find(sectionName);
- if (pos == _renamedSections.end())
- break;
- if (visited.count(pos->second)) {
- diagnostics << "/merge:" << from << "=" << to << " makes a cycle";
- return false;
- }
- sectionName = pos->second;
- visited.insert(sectionName);
- }
- }
- return true;
-}
-
-/// Try to find the input library file from the search paths and append it to
-/// the input file list. Returns true if the library file is found.
-StringRef PECOFFLinkingContext::searchLibraryFile(StringRef filename) const {
- // Current directory always takes precedence over the search paths.
- if (llvm::sys::path::is_absolute(filename) || llvm::sys::fs::exists(filename))
- return filename;
- // Iterate over the search paths.
- for (StringRef dir : _inputSearchPaths) {
- SmallString<128> path = dir;
- llvm::sys::path::append(path, filename);
- if (llvm::sys::fs::exists(path.str()))
- return allocate(path.str());
- }
- return filename;
-}
-
-/// Returns the decorated name of the given symbol name. On 32-bit x86, it
-/// adds "_" at the beginning of the string. On other architectures, the
-/// return value is the same as the argument.
-StringRef PECOFFLinkingContext::decorateSymbol(StringRef name) const {
- if (_machineType != llvm::COFF::IMAGE_FILE_MACHINE_I386)
- return name;
- std::string str = "_";
- str.append(name);
- return allocate(str);
-}
-
-StringRef PECOFFLinkingContext::undecorateSymbol(StringRef name) const {
- if (_machineType != llvm::COFF::IMAGE_FILE_MACHINE_I386)
- return name;
- if (!name.startswith("_"))
- return name;
- return name.substr(1);
-}
-
-uint64_t PECOFFLinkingContext::getBaseAddress() const {
- if (_baseAddress == invalidBaseAddress)
- return is64Bit() ? pe32PlusDefaultBaseAddress : pe32DefaultBaseAddress;
- return _baseAddress;
-}
-
-Writer &PECOFFLinkingContext::writer() const { return *_writer; }
-
-void PECOFFLinkingContext::setSectionSetMask(StringRef sectionName,
- uint32_t newFlags) {
- _sectionSetMask[sectionName] |= newFlags;
- _sectionClearMask[sectionName] &= ~newFlags;
- const uint32_t rwx = (llvm::COFF::IMAGE_SCN_MEM_READ |
- llvm::COFF::IMAGE_SCN_MEM_WRITE |
- llvm::COFF::IMAGE_SCN_MEM_EXECUTE);
- if (newFlags & rwx)
- _sectionClearMask[sectionName] |= ~_sectionSetMask[sectionName] & rwx;
- assert((_sectionSetMask[sectionName] & _sectionClearMask[sectionName]) == 0);
-}
-
-void PECOFFLinkingContext::setSectionClearMask(StringRef sectionName,
- uint32_t newFlags) {
- _sectionClearMask[sectionName] |= newFlags;
- _sectionSetMask[sectionName] &= ~newFlags;
- assert((_sectionSetMask[sectionName] & _sectionClearMask[sectionName]) == 0);
-}
-
-uint32_t PECOFFLinkingContext::getSectionAttributes(StringRef sectionName,
- uint32_t flags) const {
- auto si = _sectionSetMask.find(sectionName);
- uint32_t setMask = (si == _sectionSetMask.end()) ? 0 : si->second;
- auto ci = _sectionClearMask.find(sectionName);
- uint32_t clearMask = (ci == _sectionClearMask.end()) ? 0 : ci->second;
- return (flags | setMask) & ~clearMask;
-}
-
-// Returns true if two export descriptors are the same.
-static bool sameExportDesc(const PECOFFLinkingContext::ExportDesc &a,
- const PECOFFLinkingContext::ExportDesc &b) {
- return a.ordinal == b.ordinal && a.ordinal == b.ordinal &&
- a.noname == b.noname && a.isData == b.isData;
-}
-
-void PECOFFLinkingContext::addDllExport(ExportDesc &desc) {
- addInitialUndefinedSymbol(allocate(desc.name));
-
- // MSVC link.exe silently drops characters after the first atsign.
- // For example, /export:foo@4=bar is equivalent to /export:foo=bar.
- // We do the same thing for compatibility.
- if (!desc.externalName.empty()) {
- StringRef s(desc.externalName);
- size_t pos = s.find('@');
- if (pos != s.npos)
- desc.externalName = s.substr(0, pos);
- }
-
- // Scan the vector to look for existing entry. It's not very fast,
- // but because the number of exported symbol is usually not that
- // much, it should be okay.
- for (ExportDesc &e : _dllExports) {
- if (e.name != desc.name)
- continue;
- if (!sameExportDesc(e, desc))
- llvm::errs() << "Export symbol '" << desc.name
- << "' specified more than once.\n";
- return;
- }
- _dllExports.push_back(desc);
-}
-
-static std::string replaceExtension(StringRef path, StringRef ext) {
- SmallString<128> ss = path;
- llvm::sys::path::replace_extension(ss, ext);
- return ss.str();
-}
-
-std::string PECOFFLinkingContext::getOutputImportLibraryPath() const {
- if (!_implib.empty())
- return _implib;
- return replaceExtension(outputPath(), ".lib");
-}
-
-std::string PECOFFLinkingContext::getPDBFilePath() const {
- assert(_debug);
- if (!_pdbFilePath.empty())
- return _pdbFilePath;
- return replaceExtension(outputPath(), ".pdb");
-}
-
-void PECOFFLinkingContext::addPasses(PassManager &pm) {
- pm.add(llvm::make_unique<pecoff::PDBPass>(*this));
- pm.add(llvm::make_unique<pecoff::EdataPass>(*this));
- pm.add(llvm::make_unique<pecoff::IdataPass>(*this));
- pm.add(llvm::make_unique<pecoff::OrderPass>());
- pm.add(llvm::make_unique<pecoff::LoadConfigPass>(*this));
- pm.add(llvm::make_unique<pecoff::InferSubsystemPass>(*this));
-}
-
-} // end namespace lld
diff --git a/lib/ReaderWriter/PECOFF/Pass.cpp b/lib/ReaderWriter/PECOFF/Pass.cpp
deleted file mode 100644
index ed731984e378..000000000000
--- a/lib/ReaderWriter/PECOFF/Pass.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/Pass.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 "Pass.h"
-#include "lld/Core/File.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Support/COFF.h"
-
-namespace lld {
-namespace pecoff {
-
-static void addReloc(COFFBaseDefinedAtom *atom, const Atom *target,
- size_t offsetInAtom, Reference::KindArch arch,
- Reference::KindValue relType) {
- atom->addReference(llvm::make_unique<SimpleReference>(
- Reference::KindNamespace::COFF, arch, relType, offsetInAtom, target, 0));
-}
-
-void addDir64Reloc(COFFBaseDefinedAtom *atom, const Atom *target,
- llvm::COFF::MachineTypes machine, size_t offsetInAtom) {
- switch (machine) {
- case llvm::COFF::IMAGE_FILE_MACHINE_I386:
- addReloc(atom, target, offsetInAtom, Reference::KindArch::x86,
- llvm::COFF::IMAGE_REL_I386_DIR32);
- return;
- case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
- addReloc(atom, target, offsetInAtom, Reference::KindArch::x86_64,
- llvm::COFF::IMAGE_REL_AMD64_ADDR64);
- return;
- default:
- llvm_unreachable("unsupported machine type");
- }
-}
-
-void addDir32Reloc(COFFBaseDefinedAtom *atom, const Atom *target,
- llvm::COFF::MachineTypes machine, size_t offsetInAtom) {
- switch (machine) {
- case llvm::COFF::IMAGE_FILE_MACHINE_I386:
- addReloc(atom, target, offsetInAtom, Reference::KindArch::x86,
- llvm::COFF::IMAGE_REL_I386_DIR32);
- return;
- case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
- addReloc(atom, target, offsetInAtom, Reference::KindArch::x86_64,
- llvm::COFF::IMAGE_REL_AMD64_ADDR32);
- return;
- default:
- llvm_unreachable("unsupported machine type");
- }
-}
-
-void addDir32NBReloc(COFFBaseDefinedAtom *atom, const Atom *target,
- llvm::COFF::MachineTypes machine, size_t offsetInAtom) {
- switch (machine) {
- case llvm::COFF::IMAGE_FILE_MACHINE_I386:
- addReloc(atom, target, offsetInAtom, Reference::KindArch::x86,
- llvm::COFF::IMAGE_REL_I386_DIR32NB);
- return;
- case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
- addReloc(atom, target, offsetInAtom, Reference::KindArch::x86_64,
- llvm::COFF::IMAGE_REL_AMD64_ADDR32NB);
- return;
- case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
- addReloc(atom, target, offsetInAtom, Reference::KindArch::ARM,
- llvm::COFF::IMAGE_REL_ARM_ADDR32NB);
- return;
- default:
- llvm_unreachable("unsupported machine type");
- }
-}
-
-void addRel32Reloc(COFFBaseDefinedAtom *atom, const Atom *target,
- llvm::COFF::MachineTypes machine, size_t offsetInAtom) {
- switch (machine) {
- case llvm::COFF::IMAGE_FILE_MACHINE_I386:
- addReloc(atom, target, offsetInAtom, Reference::KindArch::x86,
- llvm::COFF::IMAGE_REL_I386_REL32);
- return;
- case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
- addReloc(atom, target, offsetInAtom, Reference::KindArch::x86_64,
- llvm::COFF::IMAGE_REL_AMD64_REL32);
- return;
- default:
- llvm_unreachable("unsupported machine type");
- }
-}
-
-} // end namespace pecoff
-} // end namespace lld
diff --git a/lib/ReaderWriter/PECOFF/Pass.h b/lib/ReaderWriter/PECOFF/Pass.h
deleted file mode 100644
index 22466f77859e..000000000000
--- a/lib/ReaderWriter/PECOFF/Pass.h
+++ /dev/null
@@ -1,34 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/Pass.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_PE_COFF_PASS_H
-#define LLD_READER_WRITER_PE_COFF_PASS_H
-
-#include "Atoms.h"
-#include "llvm/Support/COFF.h"
-
-namespace lld {
-namespace pecoff {
-
-void addDir64Reloc(COFFBaseDefinedAtom *atom, const Atom *target,
- llvm::COFF::MachineTypes machine, size_t offsetInAtom);
-
-void addDir32Reloc(COFFBaseDefinedAtom *atom, const Atom *target,
- llvm::COFF::MachineTypes machine, size_t offsetInAtom);
-
-void addDir32NBReloc(COFFBaseDefinedAtom *atom, const Atom *target,
- llvm::COFF::MachineTypes machine, size_t offsetInAtom);
-
-void addRel32Reloc(COFFBaseDefinedAtom *atom, const Atom *target,
- llvm::COFF::MachineTypes machine, size_t offsetInAtom);
-
-} // namespace pecoff
-} // namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp b/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
deleted file mode 100644
index f060bd8dc0bc..000000000000
--- a/lib/ReaderWriter/PECOFF/ReaderCOFF.cpp
+++ /dev/null
@@ -1,1140 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/ReaderCOFF.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 "lld/Core/Alias.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Reader.h"
-#include "lld/Driver/Driver.h"
-#include "lld/ReaderWriter/PECOFFLinkingContext.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/ADT/StringExtras.h"
-#include "llvm/Object/COFF.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/Errc.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/Memory.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Program.h"
-#include "llvm/Support/raw_ostream.h"
-#include <algorithm>
-#include <map>
-#include <mutex>
-#include <set>
-#include <system_error>
-#include <vector>
-
-#define DEBUG_TYPE "ReaderCOFF"
-
-using lld::pecoff::COFFBSSAtom;
-using lld::pecoff::COFFDefinedAtom;
-using lld::pecoff::COFFDefinedFileAtom;
-using lld::pecoff::COFFUndefinedAtom;
-using llvm::object::coff_aux_section_definition;
-using llvm::object::coff_aux_weak_external;
-using llvm::object::coff_relocation;
-using llvm::object::coff_section;
-using llvm::object::coff_symbol;
-using llvm::support::ulittle32_t;
-
-using namespace lld;
-
-namespace {
-
-class BumpPtrStringSaver : public llvm::cl::StringSaver {
-public:
- const char *SaveString(const char *str) override {
- size_t len = strlen(str);
- std::lock_guard<std::mutex> lock(_allocMutex);
- char *copy = _alloc.Allocate<char>(len + 1);
- memcpy(copy, str, len + 1);
- return copy;
- }
-
-private:
- llvm::BumpPtrAllocator _alloc;
- std::mutex _allocMutex;
-};
-
-class FileCOFF : public File {
-private:
- typedef std::vector<llvm::object::COFFSymbolRef> SymbolVectorT;
- typedef std::map<const coff_section *, SymbolVectorT> SectionToSymbolsT;
-
-public:
- FileCOFF(std::unique_ptr<MemoryBuffer> mb, PECOFFLinkingContext &ctx)
- : File(mb->getBufferIdentifier(), kindObject), _mb(std::move(mb)),
- _compatibleWithSEH(false), _ordinal(1),
- _machineType(llvm::COFF::MT_Invalid), _ctx(ctx) {}
-
- std::error_code doParse() override;
- bool isCompatibleWithSEH() const { return _compatibleWithSEH; }
- llvm::COFF::MachineTypes getMachineType() { return _machineType; }
-
- const atom_collection<DefinedAtom> &defined() const override {
- return _definedAtoms;
- }
-
- const atom_collection<UndefinedAtom> &undefined() const override {
- return _undefinedAtoms;
- }
-
- const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
- return _sharedLibraryAtoms;
- }
-
- const atom_collection<AbsoluteAtom> &absolute() const override {
- return _absoluteAtoms;
- }
-
- void beforeLink() override;
-
- void addUndefinedSymbol(StringRef sym) {
- _undefinedAtoms._atoms.push_back(new (_alloc) COFFUndefinedAtom(*this, sym));
- }
-
- AliasAtom *createAlias(StringRef name, const DefinedAtom *target, int cnt);
- void createAlternateNameAtoms();
- std::error_code parseDirectiveSection(StringRef directives);
-
- mutable llvm::BumpPtrAllocator _alloc;
-
-private:
- std::error_code readSymbolTable(SymbolVectorT &result);
-
- void createAbsoluteAtoms(const SymbolVectorT &symbols,
- std::vector<const AbsoluteAtom *> &result);
-
- std::error_code
- createUndefinedAtoms(const SymbolVectorT &symbols,
- std::vector<const UndefinedAtom *> &result);
-
- std::error_code
- createDefinedSymbols(const SymbolVectorT &symbols,
- std::vector<const DefinedAtom *> &result);
-
- std::error_code cacheSectionAttributes();
- std::error_code maybeCreateSXDataAtoms();
-
- std::error_code
- AtomizeDefinedSymbolsInSection(const coff_section *section,
- SymbolVectorT &symbols,
- std::vector<COFFDefinedFileAtom *> &atoms);
-
- std::error_code
- AtomizeDefinedSymbols(SectionToSymbolsT &definedSymbols,
- std::vector<const DefinedAtom *> &definedAtoms);
-
- std::error_code findAtomAt(const coff_section *section,
- uint32_t targetAddress,
- COFFDefinedFileAtom *&result,
- uint32_t &offsetInAtom);
-
- std::error_code getAtomBySymbolIndex(uint32_t index, Atom *&ret);
-
- std::error_code
- addRelocationReference(const coff_relocation *rel,
- const coff_section *section);
-
- std::error_code getSectionContents(StringRef sectionName,
- ArrayRef<uint8_t> &result);
- std::error_code getReferenceArch(Reference::KindArch &result);
- std::error_code addRelocationReferenceToAtoms();
- std::error_code findSection(StringRef name, const coff_section *&result);
- StringRef ArrayRefToString(ArrayRef<uint8_t> array);
- uint64_t getNextOrdinal();
-
- std::unique_ptr<const llvm::object::COFFObjectFile> _obj;
- std::unique_ptr<MemoryBuffer> _mb;
- atom_collection_vector<DefinedAtom> _definedAtoms;
- atom_collection_vector<UndefinedAtom> _undefinedAtoms;
- atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
- atom_collection_vector<AbsoluteAtom> _absoluteAtoms;
-
- // The target type of the object.
- Reference::KindArch _referenceArch;
-
- // True if the object has "@feat.00" symbol.
- bool _compatibleWithSEH;
-
- // A map from symbol to its name. All symbols should be in this map except
- // unnamed ones.
- std::map<llvm::object::COFFSymbolRef, StringRef> _symbolName;
-
- // A map from symbol to its resultant atom.
- std::map<llvm::object::COFFSymbolRef, Atom *> _symbolAtom;
-
- // A map from symbol to its aux symbol.
- std::map<llvm::object::COFFSymbolRef, llvm::object::COFFSymbolRef> _auxSymbol;
-
- // A map from section to its atoms.
- std::map<const coff_section *, std::vector<COFFDefinedFileAtom *>>
- _sectionAtoms;
-
- // A set of COMDAT sections.
- std::set<const coff_section *> _comdatSections;
-
- // A map to get whether the section allows its contents to be merged or not.
- std::map<const coff_section *, DefinedAtom::Merge> _merge;
-
- // COMDAT associative sections
- std::multimap<const coff_section *, const coff_section *> _association;
-
- // A sorted map to find an atom from a section and an offset within
- // the section.
- std::map<const coff_section *, std::multimap<uint32_t, COFFDefinedAtom *>>
- _definedAtomLocations;
-
- uint64_t _ordinal;
- llvm::COFF::MachineTypes _machineType;
- PECOFFLinkingContext &_ctx;
- mutable BumpPtrStringSaver _stringSaver;
-};
-
-// Converts the COFF symbol attribute to the LLD's atom attribute.
-Atom::Scope getScope(llvm::object::COFFSymbolRef symbol) {
- switch (symbol.getStorageClass()) {
- case llvm::COFF::IMAGE_SYM_CLASS_EXTERNAL:
- return Atom::scopeGlobal;
- case llvm::COFF::IMAGE_SYM_CLASS_STATIC:
- case llvm::COFF::IMAGE_SYM_CLASS_LABEL:
- return Atom::scopeTranslationUnit;
- }
- llvm_unreachable("Unknown scope");
-}
-
-DefinedAtom::ContentType getContentType(const coff_section *section) {
- if (section->Characteristics & llvm::COFF::IMAGE_SCN_CNT_CODE)
- return DefinedAtom::typeCode;
- if (section->Characteristics & llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA)
- return DefinedAtom::typeData;
- if (section->Characteristics & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
- return DefinedAtom::typeZeroFill;
- return DefinedAtom::typeUnknown;
-}
-
-DefinedAtom::ContentPermissions getPermissions(const coff_section *section) {
- if (section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_READ &&
- section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_WRITE)
- return DefinedAtom::permRW_;
- if (section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_READ &&
- section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_EXECUTE)
- return DefinedAtom::permR_X;
- if (section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_READ)
- return DefinedAtom::permR__;
- return DefinedAtom::perm___;
-}
-
-/// Returns the alignment of the section. The contents of the section must be
-/// aligned by this value in the resulting executable/DLL.
-DefinedAtom::Alignment getAlignment(const coff_section *section) {
- if (section->Characteristics & llvm::COFF::IMAGE_SCN_TYPE_NO_PAD)
- return DefinedAtom::Alignment(0);
-
- // Bit [20:24] contains section alignment information. We need to decrease
- // the value stored by 1 in order to get the real exponent (e.g, ALIGN_1BYTE
- // is 0x00100000, but the exponent should be 0)
- uint32_t characteristics = (section->Characteristics >> 20) & 0xf;
-
- // If all bits are off, we treat it as if ALIGN_1BYTE was on. The PE/COFF spec
- // does not say anything about this case, but CVTRES.EXE does not set any bit
- // in characteristics[20:24], and its output is intended to be copied to .rsrc
- // section with no padding, so I think doing this is the right thing.
- if (characteristics == 0)
- return DefinedAtom::Alignment(0);
-
- uint32_t powerOf2 = characteristics - 1;
- return DefinedAtom::Alignment(powerOf2);
-}
-
-DefinedAtom::Merge getMerge(const coff_aux_section_definition *auxsym) {
- switch (auxsym->Selection) {
- case llvm::COFF::IMAGE_COMDAT_SELECT_NODUPLICATES:
- return DefinedAtom::mergeNo;
- case llvm::COFF::IMAGE_COMDAT_SELECT_ANY:
- return DefinedAtom::mergeAsWeakAndAddressUsed;
- case llvm::COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH:
- // TODO: This mapping is wrong. Fix it.
- return DefinedAtom::mergeByContent;
- case llvm::COFF::IMAGE_COMDAT_SELECT_SAME_SIZE:
- return DefinedAtom::mergeSameNameAndSize;
- case llvm::COFF::IMAGE_COMDAT_SELECT_LARGEST:
- return DefinedAtom::mergeByLargestSection;
- case llvm::COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE:
- case llvm::COFF::IMAGE_COMDAT_SELECT_NEWEST:
- // FIXME: These attributes has more complicated semantics than the regular
- // weak symbol. These are mapped to mergeAsWeakAndAddressUsed for now
- // because the core linker does not support them yet. We eventually have
- // to implement them for full COFF support.
- return DefinedAtom::mergeAsWeakAndAddressUsed;
- default:
- llvm_unreachable("Unknown merge type");
- }
-}
-
-StringRef getMachineName(llvm::COFF::MachineTypes Type) {
- switch (Type) {
- default: llvm_unreachable("unsupported machine type");
- case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
- return "ARM";
- case llvm::COFF::IMAGE_FILE_MACHINE_I386:
- return "X86";
- case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
- return "X64";
- }
-}
-
-std::error_code FileCOFF::doParse() {
- auto binaryOrErr = llvm::object::createBinary(_mb->getMemBufferRef());
- if (std::error_code ec = binaryOrErr.getError())
- return ec;
- std::unique_ptr<llvm::object::Binary> bin = std::move(binaryOrErr.get());
-
- _obj.reset(dyn_cast<const llvm::object::COFFObjectFile>(bin.get()));
- if (!_obj)
- return make_error_code(llvm::object::object_error::invalid_file_type);
- bin.release();
-
- _machineType = static_cast<llvm::COFF::MachineTypes>(_obj->getMachine());
-
- if (getMachineType() != llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
- getMachineType() != _ctx.getMachineType()) {
- llvm::errs() << "module machine type '"
- << getMachineName(getMachineType())
- << "' conflicts with target machine type '"
- << getMachineName(_ctx.getMachineType()) << "'\n";
- return NativeReaderError::conflicting_target_machine;
- }
-
- if (std::error_code ec = getReferenceArch(_referenceArch))
- return ec;
-
- // Read the symbol table and atomize them if possible. Defined atoms
- // cannot be atomized in one pass, so they will be not be atomized but
- // added to symbolToAtom.
- SymbolVectorT symbols;
- if (std::error_code ec = readSymbolTable(symbols))
- return ec;
-
- createAbsoluteAtoms(symbols, _absoluteAtoms._atoms);
- if (std::error_code ec =
- createUndefinedAtoms(symbols, _undefinedAtoms._atoms))
- return ec;
- if (std::error_code ec = createDefinedSymbols(symbols, _definedAtoms._atoms))
- return ec;
- if (std::error_code ec = addRelocationReferenceToAtoms())
- return ec;
- if (std::error_code ec = maybeCreateSXDataAtoms())
- return ec;
-
- // Check for /SAFESEH.
- if (_ctx.requireSEH() && !isCompatibleWithSEH()) {
- llvm::errs() << "/SAFESEH is specified, but "
- << _mb->getBufferIdentifier()
- << " is not compatible with SEH.\n";
- return llvm::object::object_error::parse_failed;
- }
- return std::error_code();
-}
-
-void FileCOFF::beforeLink() {
- // Acquire the mutex to mutate _ctx.
- std::lock_guard<std::recursive_mutex> lock(_ctx.getMutex());
- std::set<StringRef> undefSyms;
-
- // Interpret .drectve section if the section has contents.
- ArrayRef<uint8_t> directives;
- if (getSectionContents(".drectve", directives))
- return;
- if (!directives.empty()) {
- std::set<StringRef> orig;
- for (StringRef sym : _ctx.initialUndefinedSymbols())
- orig.insert(sym);
- if (parseDirectiveSection(ArrayRefToString(directives)))
- return;
- for (StringRef sym : _ctx.initialUndefinedSymbols())
- if (orig.count(sym) == 0)
- undefSyms.insert(sym);
- }
-
- // Add /INCLUDE'ed symbols to the file as if they existed in the
- // file as undefined symbols.
- for (StringRef sym : undefSyms) {
- addUndefinedSymbol(sym);
- _ctx.addDeadStripRoot(sym);
- }
-
- // One can define alias symbols using /alternatename:<sym>=<sym> option.
- // The mapping for /alternatename is in the context object. This helper
- // function iterate over defined atoms and create alias atoms if needed.
- createAlternateNameAtoms();
-
- // In order to emit SEH table, all input files need to be compatible with
- // SEH. Disable SEH if the file being read is not compatible.
- if (!isCompatibleWithSEH())
- _ctx.setSafeSEH(false);
-}
-
-/// Iterate over the symbol table to retrieve all symbols.
-std::error_code
-FileCOFF::readSymbolTable(SymbolVectorT &result) {
- for (uint32_t i = 0, e = _obj->getNumberOfSymbols(); i != e; ++i) {
- // Retrieve the symbol.
- ErrorOr<llvm::object::COFFSymbolRef> sym = _obj->getSymbol(i);
- StringRef name;
- if (std::error_code ec = sym.getError())
- return ec;
- if (sym->getSectionNumber() == llvm::COFF::IMAGE_SYM_DEBUG)
- goto next;
- result.push_back(*sym);
-
- if (std::error_code ec = _obj->getSymbolName(*sym, name))
- return ec;
-
- // Existence of the symbol @feat.00 indicates that object file is compatible
- // with Safe Exception Handling.
- if (name == "@feat.00") {
- _compatibleWithSEH = true;
- goto next;
- }
-
- // Cache the name.
- _symbolName[*sym] = name;
-
- // Symbol may be followed by auxiliary symbol table records. The aux
- // record can be in any format, but the size is always the same as the
- // regular symbol. The aux record supplies additional information for the
- // standard symbol. We do not interpret the aux record here, but just
- // store it to _auxSymbol.
- if (sym->getNumberOfAuxSymbols() > 0) {
- ErrorOr<llvm::object::COFFSymbolRef> aux = _obj->getSymbol(i + 1);
- if (std::error_code ec = aux.getError())
- return ec;
- _auxSymbol[*sym] = *aux;
- }
- next:
- i += sym->getNumberOfAuxSymbols();
- }
- return std::error_code();
-}
-
-/// Create atoms for the absolute symbols.
-void FileCOFF::createAbsoluteAtoms(const SymbolVectorT &symbols,
- std::vector<const AbsoluteAtom *> &result) {
- for (llvm::object::COFFSymbolRef sym : symbols) {
- if (sym.getSectionNumber() != llvm::COFF::IMAGE_SYM_ABSOLUTE)
- continue;
- auto *atom = new (_alloc) SimpleAbsoluteAtom(*this, _symbolName[sym],
- getScope(sym), sym.getValue());
- result.push_back(atom);
- _symbolAtom[sym] = atom;
- }
-}
-
-/// Create atoms for the undefined symbols. This code is bit complicated
-/// because it supports "weak externals" mechanism of COFF. If an undefined
-/// symbol (sym1) has auxiliary data, the data contains a symbol table index
-/// at which the "second symbol" (sym2) for sym1 exists. If sym1 is resolved,
-/// it's linked normally. If not, sym1 is resolved as if it has sym2's
-/// name. This relationship between sym1 and sym2 is represented using
-/// fallback mechanism of undefined symbol.
-std::error_code
-FileCOFF::createUndefinedAtoms(const SymbolVectorT &symbols,
- std::vector<const UndefinedAtom *> &result) {
- std::map<llvm::object::COFFSymbolRef, llvm::object::COFFSymbolRef>
- weakExternal;
- std::set<llvm::object::COFFSymbolRef> fallback;
- for (llvm::object::COFFSymbolRef sym : symbols) {
- if (sym.getSectionNumber() != llvm::COFF::IMAGE_SYM_UNDEFINED)
- continue;
- // Create a mapping from sym1 to sym2, if the undefined symbol has
- // auxiliary data.
- auto iter = _auxSymbol.find(sym);
- if (iter == _auxSymbol.end())
- continue;
- const coff_aux_weak_external *aux =
- reinterpret_cast<const coff_aux_weak_external *>(
- iter->second.getRawPtr());
- ErrorOr<llvm::object::COFFSymbolRef> sym2 = _obj->getSymbol(aux->TagIndex);
- if (std::error_code ec = sym2.getError())
- return ec;
- weakExternal[sym] = *sym2;
- fallback.insert(*sym2);
- }
-
- // Create atoms for the undefined symbols.
- for (llvm::object::COFFSymbolRef sym : symbols) {
- if (sym.getSectionNumber() != llvm::COFF::IMAGE_SYM_UNDEFINED)
- continue;
- if (fallback.count(sym) > 0)
- continue;
-
- // If the symbol has sym2, create an undefiend atom for sym2, so that we
- // can pass it as a fallback atom.
- UndefinedAtom *fallback = nullptr;
- auto iter = weakExternal.find(sym);
- if (iter != weakExternal.end()) {
- llvm::object::COFFSymbolRef sym2 = iter->second;
- fallback = new (_alloc) COFFUndefinedAtom(*this, _symbolName[sym2]);
- _symbolAtom[sym2] = fallback;
- }
-
- // Create an atom for the symbol.
- auto *atom =
- new (_alloc) COFFUndefinedAtom(*this, _symbolName[sym], fallback);
- result.push_back(atom);
- _symbolAtom[sym] = atom;
- }
- return std::error_code();
-}
-
-/// Create atoms for the defined symbols. This pass is a bit complicated than
-/// the other two, because in order to create the atom for the defined symbol
-/// we need to know the adjacent symbols.
-std::error_code
-FileCOFF::createDefinedSymbols(const SymbolVectorT &symbols,
- std::vector<const DefinedAtom *> &result) {
- // A defined atom can be merged if its section attribute allows its contents
- // to be merged. In COFF, it's not very easy to get the section attribute
- // for the symbol, so scan all sections in advance and cache the attributes
- // for later use.
- if (std::error_code ec = cacheSectionAttributes())
- return ec;
-
- // Filter non-defined atoms, and group defined atoms by its section.
- SectionToSymbolsT definedSymbols;
- for (llvm::object::COFFSymbolRef sym : symbols) {
- // A symbol with section number 0 and non-zero value represents a common
- // symbol. The MS COFF spec did not give a definition of what the common
- // symbol is. We should probably follow ELF's definition shown below.
- //
- // - If one object file has a common symbol and another has a definition,
- // the common symbol is treated as an undefined reference.
- // - If there is no definition for a common symbol, the program linker
- // acts as though it saw a definition initialized to zero of the
- // appropriate size.
- // - Two object files may have common symbols of
- // different sizes, in which case the program linker will use the
- // largest size.
- //
- // FIXME: We are currently treating the common symbol as a normal
- // mergeable atom. Implement the above semantcis.
- if (sym.getSectionNumber() == llvm::COFF::IMAGE_SYM_UNDEFINED &&
- sym.getValue() > 0) {
- StringRef name = _symbolName[sym];
- uint32_t size = sym.getValue();
- auto *atom = new (_alloc)
- COFFBSSAtom(*this, name, getScope(sym), DefinedAtom::permRW_,
- DefinedAtom::mergeAsWeakAndAddressUsed, size, getNextOrdinal());
-
- // Common symbols should be aligned on natural boundaries with the maximum
- // of 32 byte. It's not documented anywhere, but it's what MSVC link.exe
- // seems to be doing.
- uint64_t alignment = std::min((uint64_t)32, llvm::NextPowerOf2(size));
- atom->setAlignment(
- DefinedAtom::Alignment(llvm::countTrailingZeros(alignment)));
- result.push_back(atom);
- continue;
- }
-
- // Skip if it's not for defined atom.
- if (sym.getSectionNumber() == llvm::COFF::IMAGE_SYM_DEBUG ||
- sym.getSectionNumber() == llvm::COFF::IMAGE_SYM_ABSOLUTE ||
- sym.getSectionNumber() == llvm::COFF::IMAGE_SYM_UNDEFINED)
- continue;
-
- const coff_section *sec;
- if (std::error_code ec = _obj->getSection(sym.getSectionNumber(), sec))
- return ec;
- assert(sec && "SectionIndex > 0, Sec must be non-null!");
-
- uint8_t sc = sym.getStorageClass();
- if (sc != llvm::COFF::IMAGE_SYM_CLASS_EXTERNAL &&
- sc != llvm::COFF::IMAGE_SYM_CLASS_STATIC &&
- sc != llvm::COFF::IMAGE_SYM_CLASS_FUNCTION &&
- sc != llvm::COFF::IMAGE_SYM_CLASS_LABEL) {
- llvm::errs() << "Unable to create atom for: " << _symbolName[sym] << " ("
- << static_cast<int>(sc) << ")\n";
- return llvm::object::object_error::parse_failed;
- }
-
- definedSymbols[sec].push_back(sym);
- }
-
- // Atomize the defined symbols.
- if (std::error_code ec = AtomizeDefinedSymbols(definedSymbols, result))
- return ec;
-
- return std::error_code();
-}
-
-// Cache the COMDAT attributes, which indicate whether the symbols in the
-// section can be merged or not.
-std::error_code FileCOFF::cacheSectionAttributes() {
- // The COMDAT section attribute is not an attribute of coff_section, but is
- // stored in the auxiliary symbol for the first symbol referring a COMDAT
- // section. It feels to me that it's unnecessarily complicated, but this is
- // how COFF works.
- for (auto i : _auxSymbol) {
- // Read a section from the file
- llvm::object::COFFSymbolRef sym = i.first;
- if (sym.getSectionNumber() == llvm::COFF::IMAGE_SYM_ABSOLUTE ||
- sym.getSectionNumber() == llvm::COFF::IMAGE_SYM_UNDEFINED)
- continue;
-
- const coff_section *sec;
- if (std::error_code ec = _obj->getSection(sym.getSectionNumber(), sec))
- return ec;
- const coff_aux_section_definition *aux =
- reinterpret_cast<const coff_aux_section_definition *>(
- i.second.getRawPtr());
-
- if (sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_COMDAT) {
- // Read aux symbol data.
- _comdatSections.insert(sec);
- _merge[sec] = getMerge(aux);
- }
-
- // Handle associative sections.
- if (aux->Selection == llvm::COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
- const coff_section *parent;
- if (std::error_code ec =
- _obj->getSection(aux->getNumber(sym.isBigObj()), parent))
- return ec;
- _association.insert(std::make_pair(parent, sec));
- }
- }
-
- // The sections that does not have auxiliary symbol are regular sections, in
- // which symbols are not allowed to be merged.
- for (const auto &section : _obj->sections()) {
- const coff_section *sec = _obj->getCOFFSection(section);
- if (!_merge.count(sec))
- _merge[sec] = DefinedAtom::mergeNo;
- }
- return std::error_code();
-}
-
-/// Atomize \p symbols and append the results to \p atoms. The symbols are
-/// assumed to have been defined in the \p section.
-std::error_code FileCOFF::AtomizeDefinedSymbolsInSection(
- const coff_section *section, SymbolVectorT &symbols,
- std::vector<COFFDefinedFileAtom *> &atoms) {
- // Sort symbols by position.
- std::stable_sort(
- symbols.begin(), symbols.end(),
- [](llvm::object::COFFSymbolRef a, llvm::object::COFFSymbolRef b)
- -> bool { return a.getValue() < b.getValue(); });
-
- StringRef sectionName;
- if (std::error_code ec = _obj->getSectionName(section, sectionName))
- return ec;
-
- // BSS section does not have contents. If this is the BSS section, create
- // COFFBSSAtom instead of COFFDefinedAtom.
- if (section->Characteristics & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
- for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) {
- llvm::object::COFFSymbolRef sym = *si;
- uint32_t size = (si + 1 == se) ? section->SizeOfRawData - sym.getValue()
- : si[1].getValue() - sym.getValue();
- auto *atom = new (_alloc) COFFBSSAtom(
- *this, _symbolName[sym], getScope(sym), getPermissions(section),
- DefinedAtom::mergeAsWeakAndAddressUsed, size, getNextOrdinal());
- atoms.push_back(atom);
- _symbolAtom[sym] = atom;
- }
- return std::error_code();
- }
-
- ArrayRef<uint8_t> secData;
- if (std::error_code ec = _obj->getSectionContents(section, secData))
- return ec;
-
- // A section with IMAGE_SCN_LNK_{INFO,REMOVE} attribute will never become
- // a part of the output image. That's what the COFF spec says.
- if (section->Characteristics & llvm::COFF::IMAGE_SCN_LNK_INFO ||
- section->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE)
- return std::error_code();
-
- // Supporting debug info needs more work than just linking and combining
- // .debug sections. We don't support it yet. Let's discard .debug sections at
- // the very beginning of the process so that we don't spend time on linking
- // blobs that nobody would understand.
- if ((section->Characteristics & llvm::COFF::IMAGE_SCN_MEM_DISCARDABLE) &&
- (sectionName == ".debug" || sectionName.startswith(".debug$"))) {
- return std::error_code();
- }
-
- DefinedAtom::ContentType type = getContentType(section);
- DefinedAtom::ContentPermissions perms = getPermissions(section);
- uint64_t sectionSize = section->SizeOfRawData;
- bool isComdat = (_comdatSections.count(section) == 1);
-
- // Create an atom for the entire section.
- if (symbols.empty()) {
- ArrayRef<uint8_t> data(secData.data(), secData.size());
- auto *atom = new (_alloc) COFFDefinedAtom(
- *this, "", sectionName, sectionSize, Atom::scopeTranslationUnit,
- type, isComdat, perms, _merge[section], data, getNextOrdinal());
- atoms.push_back(atom);
- _definedAtomLocations[section].insert(std::make_pair(0, atom));
- return std::error_code();
- }
-
- // Create an unnamed atom if the first atom isn't at the start of the
- // section.
- if (symbols[0].getValue() != 0) {
- uint64_t size = symbols[0].getValue();
- ArrayRef<uint8_t> data(secData.data(), size);
- auto *atom = new (_alloc) COFFDefinedAtom(
- *this, "", sectionName, sectionSize, Atom::scopeTranslationUnit,
- type, isComdat, perms, _merge[section], data, getNextOrdinal());
- atoms.push_back(atom);
- _definedAtomLocations[section].insert(std::make_pair(0, atom));
- }
-
- for (auto si = symbols.begin(), se = symbols.end(); si != se; ++si) {
- const uint8_t *start = secData.data() + si->getValue();
- // if this is the last symbol, take up the remaining data.
- const uint8_t *end = (si + 1 == se) ? secData.data() + secData.size()
- : secData.data() + (si + 1)->getValue();
- ArrayRef<uint8_t> data(start, end);
- auto *atom = new (_alloc) COFFDefinedAtom(
- *this, _symbolName[*si], sectionName, sectionSize, getScope(*si),
- type, isComdat, perms, _merge[section], data, getNextOrdinal());
- atoms.push_back(atom);
- _symbolAtom[*si] = atom;
- _definedAtomLocations[section].insert(std::make_pair(si->getValue(), atom));
- }
- return std::error_code();
-}
-
-std::error_code FileCOFF::AtomizeDefinedSymbols(
- SectionToSymbolsT &definedSymbols,
- std::vector<const DefinedAtom *> &definedAtoms) {
- // For each section, make atoms for all the symbols defined in the
- // section, and append the atoms to the result objects.
- for (auto &i : definedSymbols) {
- const coff_section *section = i.first;
- SymbolVectorT &symbols = i.second;
- std::vector<COFFDefinedFileAtom *> atoms;
- if (std::error_code ec =
- AtomizeDefinedSymbolsInSection(section, symbols, atoms))
- return ec;
-
- // Set alignment to the first atom so that the section contents
- // will be aligned as specified by the object section header.
- if (atoms.size() > 0)
- atoms[0]->setAlignment(getAlignment(section));
-
- // Connect atoms with layout-after edges. It prevents atoms
- // from being GC'ed if there is a reference to one of the atoms
- // in the same layout-after chain. In such case we want to emit
- // all the atoms appeared in the same chain, because the "live"
- // atom may reference other atoms in the same chain.
- if (atoms.size() >= 2)
- for (auto it = atoms.begin(), e = atoms.end(); it + 1 != e; ++it)
- addLayoutEdge(*it, *(it + 1), lld::Reference::kindLayoutAfter);
-
- for (COFFDefinedFileAtom *atom : atoms) {
- _sectionAtoms[section].push_back(atom);
- definedAtoms.push_back(atom);
- }
- }
-
- // A COMDAT section with SELECT_ASSOCIATIVE attribute refer to other
- // section. If the referred section is linked to a binary, the
- // referring section needs to be linked too. A typical use case of
- // this attribute is a static initializer; a parent is a comdat BSS
- // section, and a child is a static initializer code for the data.
- //
- // We add referring section contents to the referred section's
- // associate list, so that Resolver takes care of them.
- for (auto i : _association) {
- const coff_section *parent = i.first;
- const coff_section *child = i.second;
- if (_sectionAtoms.count(child)) {
- COFFDefinedFileAtom *p = _sectionAtoms[parent][0];
- p->addAssociate(_sectionAtoms[child][0]);
- }
- }
-
- return std::error_code();
-}
-
-/// Find the atom that is at \p targetAddress in \p section.
-std::error_code FileCOFF::findAtomAt(const coff_section *section,
- uint32_t targetAddress,
- COFFDefinedFileAtom *&result,
- uint32_t &offsetInAtom) {
- auto loc = _definedAtomLocations.find(section);
- if (loc == _definedAtomLocations.end())
- return llvm::object::object_error::parse_failed;
- std::multimap<uint32_t, COFFDefinedAtom *> &map = loc->second;
-
- auto it = map.upper_bound(targetAddress);
- if (it == map.begin())
- return llvm::object::object_error::parse_failed;
- --it;
- uint32_t atomAddress = it->first;
- result = it->second;
- offsetInAtom = targetAddress - atomAddress;
- return std::error_code();
-}
-
-/// Find the atom for the symbol that was at the \p index in the symbol
-/// table.
-std::error_code FileCOFF::getAtomBySymbolIndex(uint32_t index, Atom *&ret) {
- ErrorOr<llvm::object::COFFSymbolRef> symbol = _obj->getSymbol(index);
- if (std::error_code ec = symbol.getError())
- return ec;
- ret = _symbolAtom[*symbol];
- assert(ret);
- return std::error_code();
-}
-
-/// Add relocation information to an atom based on \p rel. \p rel is an
-/// relocation entry for the \p section, and \p atoms are all the atoms
-/// defined in the \p section.
-std::error_code FileCOFF::addRelocationReference(
- const coff_relocation *rel, const coff_section *section) {
- // The address of the item which relocation is applied. Section's
- // VirtualAddress needs to be added for historical reasons, but the value
- // is usually just zero, so adding it is usually no-op.
- uint32_t itemAddress = rel->VirtualAddress + section->VirtualAddress;
-
- Atom *targetAtom = nullptr;
- if (std::error_code ec =
- getAtomBySymbolIndex(rel->SymbolTableIndex, targetAtom))
- return ec;
-
- COFFDefinedFileAtom *atom;
- uint32_t offsetInAtom;
- if (std::error_code ec = findAtomAt(section, itemAddress, atom, offsetInAtom))
- return ec;
- atom->addReference(llvm::make_unique<SimpleReference>(
- Reference::KindNamespace::COFF, _referenceArch, rel->Type, offsetInAtom,
- targetAtom, 0));
- return std::error_code();
-}
-
-// Read section contents.
-std::error_code FileCOFF::getSectionContents(StringRef sectionName,
- ArrayRef<uint8_t> &result) {
- const coff_section *section = nullptr;
- if (std::error_code ec = findSection(sectionName, section))
- return ec;
- if (!section)
- return std::error_code();
- if (std::error_code ec = _obj->getSectionContents(section, result))
- return ec;
- return std::error_code();
-}
-
-AliasAtom *
-FileCOFF::createAlias(StringRef name, const DefinedAtom *target, int cnt) {
- AliasAtom *alias = new (_alloc) AliasAtom(*this, name);
- alias->addReference(Reference::KindNamespace::all, Reference::KindArch::all,
- Reference::kindLayoutAfter, 0, target, 0);
- alias->setMerge(DefinedAtom::mergeAsWeak);
- if (target->contentType() == DefinedAtom::typeCode)
- alias->setDeadStrip(DefinedAtom::deadStripNever);
- alias->setOrdinal(target->ordinal() - cnt);
- return alias;
-}
-
-void FileCOFF::createAlternateNameAtoms() {
- std::vector<AliasAtom *> aliases;
- for (const DefinedAtom *atom : defined()) {
- int cnt = 1;
- for (StringRef alias : _ctx.getAlternateNames(atom->name()))
- aliases.push_back(createAlias(alias, atom, cnt++));
- }
- for (AliasAtom *alias : aliases)
- _definedAtoms._atoms.push_back(alias);
-}
-
-// Interpret the contents of .drectve section. If exists, the section contains
-// a string containing command line options. The linker is expected to
-// interpret the options as if they were given via the command line.
-//
-// The section mainly contains /defaultlib (-l in Unix), but can contain any
-// options as long as they are valid.
-std::error_code
-FileCOFF::parseDirectiveSection(StringRef directives) {
- DEBUG(llvm::dbgs() << ".drectve: " << directives << "\n");
-
- // Split the string into tokens, as the shell would do for argv.
- SmallVector<const char *, 16> tokens;
- tokens.push_back("link"); // argv[0] is the command name. Will be ignored.
- llvm::cl::TokenizeWindowsCommandLine(directives, _stringSaver, tokens);
- tokens.push_back(nullptr);
-
- // Calls the command line parser to interpret the token string as if they
- // were given via the command line.
- int argc = tokens.size() - 1;
- const char **argv = &tokens[0];
- std::string errorMessage;
- llvm::raw_string_ostream stream(errorMessage);
- PECOFFLinkingContext::ParseDirectives parseDirectives =
- _ctx.getParseDirectives();
- bool parseFailed = !parseDirectives(argc, argv, _ctx, stream);
- stream.flush();
- // Print error message if error.
- if (parseFailed) {
- return make_dynamic_error_code(
- Twine("Failed to parse '") + directives + "'\n"
- + "Reason: " + errorMessage);
- }
- if (!errorMessage.empty()) {
- llvm::errs() << "lld warning: " << errorMessage << "\n";
- }
- return std::error_code();
-}
-
-/// Returns the target machine type of the current object file.
-std::error_code FileCOFF::getReferenceArch(Reference::KindArch &result) {
- switch (_obj->getMachine()) {
- case llvm::COFF::IMAGE_FILE_MACHINE_I386:
- result = Reference::KindArch::x86;
- return std::error_code();
- case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
- result = Reference::KindArch::x86_64;
- return std::error_code();
- case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
- result = Reference::KindArch::ARM;
- return std::error_code();
- case llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN:
- result = Reference::KindArch::all;
- return std::error_code();
- }
- llvm::errs() << "Unsupported machine type: 0x"
- << llvm::utohexstr(_obj->getMachine()) << '\n';
- return llvm::object::object_error::parse_failed;
-}
-
-/// Add relocation information to atoms.
-std::error_code FileCOFF::addRelocationReferenceToAtoms() {
- // Relocation entries are defined for each section.
- for (const auto &sec : _obj->sections()) {
- const coff_section *section = _obj->getCOFFSection(sec);
-
- // Skip if there's no atom for the section. Currently we do not create any
- // atoms for some sections, such as "debug$S", and such sections need to
- // be skipped here too.
- if (_sectionAtoms.find(section) == _sectionAtoms.end())
- continue;
-
- for (const auto &reloc : sec.relocations()) {
- const coff_relocation *rel = _obj->getCOFFRelocation(reloc);
- if (auto ec = addRelocationReference(rel, section))
- return ec;
- }
- }
- return std::error_code();
-}
-
-// Read .sxdata section if exists. .sxdata is a x86-only section that contains a
-// vector of symbol offsets. The symbols pointed by this section are SEH handler
-// functions contained in the same object file. The linker needs to construct a
-// SEH table and emit it to executable.
-//
-// On x86, exception handler addresses are in stack, so they are vulnerable to
-// stack overflow attack. In order to protect against it, Windows runtime uses
-// the SEH table to check if a SEH handler address in stack is a real address of
-// a handler created by compiler.
-//
-// What we want to emit from the linker is a vector of SEH handler VAs, but here
-// we have a vector of offsets to the symbol table. So we convert the latter to
-// the former.
-std::error_code FileCOFF::maybeCreateSXDataAtoms() {
- ArrayRef<uint8_t> sxdata;
- if (std::error_code ec = getSectionContents(".sxdata", sxdata))
- return ec;
- if (sxdata.empty())
- return std::error_code();
-
- auto *atom = new (_alloc) COFFDefinedAtom(
- *this, "", ".sxdata", 0, Atom::scopeTranslationUnit,
- DefinedAtom::typeData, false /*isComdat*/, DefinedAtom::permR__,
- DefinedAtom::mergeNo, sxdata, getNextOrdinal());
-
- const ulittle32_t *symbolIndex =
- reinterpret_cast<const ulittle32_t *>(sxdata.data());
- int numSymbols = sxdata.size() / sizeof(uint32_t);
-
- for (int i = 0; i < numSymbols; ++i) {
- Atom *handlerFunc;
- if (std::error_code ec = getAtomBySymbolIndex(symbolIndex[i], handlerFunc))
- return ec;
- int offsetInAtom = i * sizeof(uint32_t);
-
- uint16_t rtype;
- switch (_obj->getMachine()) {
- case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
- rtype = llvm::COFF::IMAGE_REL_AMD64_ADDR32;
- break;
- case llvm::COFF::IMAGE_FILE_MACHINE_I386:
- rtype = llvm::COFF::IMAGE_REL_I386_DIR32;
- break;
- default:
- llvm_unreachable("unsupported machine type");
- }
-
- atom->addReference(llvm::make_unique<SimpleReference>(
- Reference::KindNamespace::COFF, _referenceArch, rtype, offsetInAtom,
- handlerFunc, 0));
- }
-
- _definedAtoms._atoms.push_back(atom);
- return std::error_code();
-}
-
-/// Find a section by name.
-std::error_code FileCOFF::findSection(StringRef name,
- const coff_section *&result) {
- for (const auto &sec : _obj->sections()) {
- const coff_section *section = _obj->getCOFFSection(sec);
- StringRef sectionName;
- if (auto ec = _obj->getSectionName(section, sectionName))
- return ec;
- if (sectionName == name) {
- result = section;
- return std::error_code();
- }
- }
- // Section was not found, but it's not an error. This method returns
- // an error only when there's a read error.
- return std::error_code();
-}
-
-// Convert ArrayRef<uint8_t> to std::string. The array contains a string which
-// may not be terminated by NUL.
-StringRef FileCOFF::ArrayRefToString(ArrayRef<uint8_t> array) {
- // .drectve sections are encoded in either ASCII or UTF-8 with BOM.
- // The PE/COFF spec allows ANSI (Windows-1252 encoding), but seems
- // it's no longer in use.
- // Skip a UTF-8 byte marker if exists.
- if (array.size() >= 3 && array[0] == 0xEF && array[1] == 0xBB &&
- array[2] == 0xBF) {
- array = array.slice(3);
- }
- if (array.empty())
- return "";
- StringRef s(reinterpret_cast<const char *>(array.data()), array.size());
- s = s.substr(0, s.find_first_of('\0'));
- std::string *contents = new (_alloc) std::string(s.data(), s.size());
- return StringRef(*contents).trim();
-}
-
-// getNextOrdinal returns a monotonically increasaing uint64_t number
-// starting from 1. There's a large gap between two numbers returned
-// from this function, so that you can put other atoms between them.
-uint64_t FileCOFF::getNextOrdinal() {
- return _ordinal++ << 32;
-}
-
-class COFFObjectReader : public Reader {
-public:
- COFFObjectReader(PECOFFLinkingContext &ctx) : _ctx(ctx) {}
-
- bool canParse(file_magic magic, StringRef ext,
- const MemoryBuffer &) const override {
- return magic == llvm::sys::fs::file_magic::coff_object;
- }
-
- std::error_code
- loadFile(std::unique_ptr<MemoryBuffer> mb, const Registry &,
- std::vector<std::unique_ptr<File>> &result) const override {
- // Parse the memory buffer as PECOFF file.
- auto *file = new FileCOFF(std::move(mb), _ctx);
- result.push_back(std::unique_ptr<File>(file));
- return std::error_code();
- }
-
-private:
- PECOFFLinkingContext &_ctx;
-};
-
-using namespace llvm::COFF;
-
-const Registry::KindStrings kindStringsI386[] = {
- LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_ABSOLUTE),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_DIR16),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_REL16),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_DIR32),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_DIR32NB),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_SEG12),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_SECTION),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_SECREL),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_TOKEN),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_SECREL7),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_I386_REL32),
- LLD_KIND_STRING_END};
-
-const Registry::KindStrings kindStringsAMD64[] = {
- LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_ABSOLUTE),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_ADDR64),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_ADDR32),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_ADDR32NB),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_REL32),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_REL32_1),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_REL32_2),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_REL32_3),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_REL32_4),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_REL32_5),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_SECTION),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_SECREL),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_SECREL7),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_TOKEN),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_SREL32),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_PAIR),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_AMD64_SSPAN32),
- LLD_KIND_STRING_END};
-
-const Registry::KindStrings kindStringsARMNT[] = {
- LLD_KIND_STRING_ENTRY(IMAGE_REL_ARM_ABSOLUTE),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_ARM_ADDR32),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_ARM_ADDR32NB),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_ARM_BRANCH24),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_ARM_BRANCH11),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_ARM_TOKEN),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_ARM_BLX24),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_ARM_BLX11),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_ARM_SECTION),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_ARM_SECREL),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_ARM_MOV32A),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_ARM_MOV32T),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_ARM_BRANCH20T),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_ARM_BRANCH24T),
- LLD_KIND_STRING_ENTRY(IMAGE_REL_ARM_BLX23T),
-};
-
-} // end namespace anonymous
-
-namespace lld {
-
-void Registry::addSupportCOFFObjects(PECOFFLinkingContext &ctx) {
- add(std::unique_ptr<Reader>(new COFFObjectReader(ctx)));
- addKindTable(Reference::KindNamespace::COFF, Reference::KindArch::x86,
- kindStringsI386);
- addKindTable(Reference::KindNamespace::COFF, Reference::KindArch::x86_64,
- kindStringsAMD64);
- addKindTable(Reference::KindNamespace::COFF, Reference::KindArch::ARM,
- kindStringsARMNT);
-}
-
-}
diff --git a/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp b/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp
deleted file mode 100644
index 8c9641376a0d..000000000000
--- a/lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp
+++ /dev/null
@@ -1,389 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/ReaderImportHeader.cpp ---------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file \brief This file provides a way to read an import library member in a
-/// .lib file.
-///
-/// Archive Files in Windows
-/// ========================
-///
-/// In Windows, archive files with .lib file extension serve two different
-/// purposes.
-///
-/// - For static linking: An archive file in this use case contains multiple
-/// regular .obj files and is used for static linking. This is the same
-/// usage as .a file in Unix.
-///
-/// - For dynamic linking: An archive file in this use case contains pseudo
-/// .obj files to describe exported symbols of a DLL. Each pseudo .obj file
-/// in an archive has a name of an exported symbol and a DLL filename from
-/// which the symbol can be imported. When you link a DLL on Windows, you
-/// pass the name of the .lib file for the DLL instead of the DLL filename
-/// itself. That is the Windows way of linking against a shared library.
-///
-/// This file contains a function to handle the pseudo object file.
-///
-/// Windows Loader and Import Address Table
-/// =======================================
-///
-/// Windows supports a GOT-like mechanism for DLLs. The executable using DLLs
-/// contains a list of DLL names and list of symbols that need to be resolved by
-/// the loader. Windows loader maps the executable and all the DLLs to memory,
-/// resolves the symbols referencing items in DLLs, and updates the import
-/// address table (IAT) in memory. The IAT is an array of pointers to all of the
-/// data or functions in DLL referenced by the executable. You cannot access
-/// items in DLLs directly. They have to be accessed through an extra level of
-/// indirection.
-///
-/// So, if you want to access an item in DLL, you have to go through a
-/// pointer. How do you actually do that? You need a symbol for a pointer in the
-/// IAT. For each symbol defined in a DLL, a symbol with "__imp_" prefix is
-/// exported from the DLL for an IAT entry. For example, if you have a global
-/// variable "foo" in a DLL, a pointer to the variable is available as
-/// "_imp__foo". The IAT is an array of _imp__ symbols.
-///
-/// Is this OK? That's not that complicated. Because items in a DLL are not
-/// directly accessible, you need to access through a pointer, and the pointer
-/// is available as a symbol with _imp__ prefix.
-///
-/// Note 1: Although you can write code with _imp__ prefix, today's compiler and
-/// linker let you write code as if there's no extra level of indirection.
-/// That's why you haven't seen lots of _imp__ in your code. A variable or a
-/// function declared with "dllimport" attribute is treated as an item in a DLL,
-/// and the compiler automatically mangles its name and inserts the extra level
-/// of indirection when accessing the item. Here are some examples:
-///
-/// __declspec(dllimport) int var_in_dll;
-/// var_in_dll = 3; // is equivalent to *_imp__var_in_dll = 3;
-///
-/// __declspec(dllimport) int fn_in_dll(void);
-/// fn_in_dll(); // is equivalent to (*_imp__fn_in_dll)();
-///
-/// It's just the compiler rewrites code for you so that you don't need to
-/// handle the indirection yourself.
-///
-/// Note 2: __declspec(dllimport) is mandatory for data but optional for
-/// function. For a function, the linker creates a jump table with the original
-/// symbol name, so that the function is accessible without _imp__ prefix. The
-/// same function in a DLL can be called through two different symbols if it's
-/// not dllimport'ed.
-///
-/// (*_imp__fn)()
-/// fn()
-///
-/// The above functions do the same thing. fn's content is a JMP instruction to
-/// branch to the address pointed by _imp__fn. The latter may be a little bit
-/// slower than the former because it will execute the extra JMP instruction,
-/// but that's usually negligible.
-///
-/// If a function is dllimport'ed, which is usually done in a header file,
-/// mangled name will be used at compile time so the jump table will not be
-/// used.
-///
-/// Because there's no way to hide the indirection for data access at link time,
-/// data has to be accessed through dllimport'ed symbols or explicit _imp__
-/// prefix.
-///
-/// Idata Sections in the Pseudo Object File
-/// ========================================
-///
-/// The object file created by cl.exe has several sections whose name starts
-/// with ".idata$" followed by a number. The contents of the sections seem the
-/// fragments of a complete ".idata" section. These sections has relocations for
-/// the data referenced from the idata secton. Generally, the linker discards
-/// "$" and all characters that follow from the section name and merges their
-/// contents to one section. So, it looks like if everything would work fine,
-/// the idata section would naturally be constructed without having any special
-/// code for doing that.
-///
-/// However, the LLD linker cannot do that. An idata section constructed in that
-/// way was never be in valid format. We don't know the reason yet. Our
-/// assumption on the idata fragment could simply be wrong, or the LLD linker is
-/// not powerful enough to do the job. Meanwhile, we construct the idata section
-/// ourselves. All the "idata$" sections in the pseudo object file are currently
-/// ignored.
-///
-/// Creating Atoms for the Import Address Table
-/// ===========================================
-///
-/// The function in this file reads a pseudo object file and creates at most two
-/// atoms. One is a shared library atom for _imp__ symbol. The another is a
-/// defined atom for the JMP instruction if the symbol is for a function.
-///
-//===----------------------------------------------------------------------===//
-
-#include "Atoms.h"
-#include "lld/Core/Error.h"
-#include "lld/Core/File.h"
-#include "lld/Core/SharedLibraryAtom.h"
-#include "lld/ReaderWriter/PECOFFLinkingContext.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/ADT/STLExtras.h"
-#include "llvm/Object/COFF.h"
-#include "llvm/Support/COFF.h"
-#include "llvm/Support/Casting.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/Memory.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include "llvm/Support/raw_ostream.h"
-#include <cstring>
-#include <map>
-#include <system_error>
-#include <vector>
-
-using namespace lld;
-using namespace lld::pecoff;
-using namespace llvm;
-using namespace llvm::support::endian;
-
-#define DEBUG_TYPE "ReaderImportHeader"
-
-namespace lld {
-
-namespace {
-
-// This code is valid both in x86 and x64.
-const uint8_t FuncAtomContentX86[] = {
- 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // JMP *0x0
- 0xcc, 0xcc // INT 3; INT 3
-};
-
-const uint8_t FuncAtomContentARMNT[] = {
- 0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0
- 0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0
- 0xdc, 0xf8, 0x00, 0xf0, // ldr.w pc, [ip]
-};
-
-static void setJumpInstTarget(COFFLinkerInternalAtom *src, const Atom *dst,
- int off, MachineTypes machine) {
- SimpleReference *ref;
-
- switch (machine) {
- default: llvm::report_fatal_error("unsupported machine type");
- case llvm::COFF::IMAGE_FILE_MACHINE_I386:
- ref = new SimpleReference(Reference::KindNamespace::COFF,
- Reference::KindArch::x86,
- llvm::COFF::IMAGE_REL_I386_DIR32,
- off, dst, 0);
- break;
- case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
- ref = new SimpleReference(Reference::KindNamespace::COFF,
- Reference::KindArch::x86_64,
- llvm::COFF::IMAGE_REL_AMD64_REL32,
- off, dst, 0);
- break;
- case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
- ref = new SimpleReference(Reference::KindNamespace::COFF,
- Reference::KindArch::ARM,
- llvm::COFF::IMAGE_REL_ARM_MOV32T,
- off, dst, 0);
- break;
- }
- src->addReference(std::unique_ptr<SimpleReference>(ref));
-}
-
-/// The defined atom for jump table.
-class FuncAtom : public COFFLinkerInternalAtom {
-public:
- FuncAtom(const File &file, StringRef symbolName,
- const COFFSharedLibraryAtom *impAtom, MachineTypes machine)
- : COFFLinkerInternalAtom(file, /*oridnal*/ 0, createContent(machine),
- symbolName) {
- size_t Offset;
-
- switch (machine) {
- default: llvm::report_fatal_error("unsupported machine type");
- case llvm::COFF::IMAGE_FILE_MACHINE_I386:
- case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
- Offset = 2;
- break;
- case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
- Offset = 0;
- break;
- }
-
- setJumpInstTarget(this, impAtom, Offset, machine);
- }
-
- uint64_t ordinal() const override { return 0; }
- Scope scope() const override { return scopeGlobal; }
- ContentType contentType() const override { return typeCode; }
- Alignment alignment() const override { return Alignment(1); }
- ContentPermissions permissions() const override { return permR_X; }
-
-private:
- std::vector<uint8_t> createContent(MachineTypes machine) const {
- const uint8_t *Data;
- size_t Size;
-
- switch (machine) {
- default: llvm::report_fatal_error("unsupported machine type");
- case llvm::COFF::IMAGE_FILE_MACHINE_I386:
- case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
- Data = FuncAtomContentX86;
- Size = sizeof(FuncAtomContentX86);
- break;
- case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
- Data = FuncAtomContentARMNT;
- Size = sizeof(FuncAtomContentARMNT);
- break;
- }
-
- return std::vector<uint8_t>(Data, Data + Size);
- }
-};
-
-class FileImportLibrary : public File {
-public:
- FileImportLibrary(std::unique_ptr<MemoryBuffer> mb, MachineTypes machine)
- : File(mb->getBufferIdentifier(), kindSharedLibrary),
- _mb(std::move(mb)), _machine(machine) {}
-
- std::error_code doParse() override {
- const char *buf = _mb->getBufferStart();
- const char *end = _mb->getBufferEnd();
-
- // The size of the string that follows the header.
- uint32_t dataSize
- = read32le(buf + offsetof(COFF::ImportHeader, SizeOfData));
-
- // Check if the total size is valid.
- if (std::size_t(end - buf) != sizeof(COFF::ImportHeader) + dataSize)
- return make_error_code(NativeReaderError::unknown_file_format);
-
- uint16_t hint = read16le(buf + offsetof(COFF::ImportHeader, OrdinalHint));
- StringRef symbolName(buf + sizeof(COFF::ImportHeader));
- StringRef dllName(buf + sizeof(COFF::ImportHeader) + symbolName.size() + 1);
-
- // TypeInfo is a bitfield. The least significant 2 bits are import
- // type, followed by 3 bit import name type.
- uint16_t typeInfo = read16le(buf + offsetof(COFF::ImportHeader, TypeInfo));
- int type = typeInfo & 0x3;
- int nameType = (typeInfo >> 2) & 0x7;
-
- // Symbol name used by the linker may be different from the symbol name used
- // by the loader. The latter may lack symbol decorations, or may not even
- // have name if it's imported by ordinal.
- StringRef importName = symbolNameToImportName(symbolName, nameType);
-
- const COFFSharedLibraryAtom *dataAtom =
- addSharedLibraryAtom(hint, symbolName, importName, dllName);
- if (type == llvm::COFF::IMPORT_CODE)
- addFuncAtom(symbolName, dllName, dataAtom);
-
- return std::error_code();
- }
-
- const atom_collection<DefinedAtom> &defined() const override {
- return _definedAtoms;
- }
-
- const atom_collection<UndefinedAtom> &undefined() const override {
- return _noUndefinedAtoms;
- }
-
- const atom_collection<SharedLibraryAtom> &sharedLibrary() const override {
- return _sharedLibraryAtoms;
- }
-
- const atom_collection<AbsoluteAtom> &absolute() const override {
- return _noAbsoluteAtoms;
- }
-
-private:
- const COFFSharedLibraryAtom *addSharedLibraryAtom(uint16_t hint,
- StringRef symbolName,
- StringRef importName,
- StringRef dllName) {
- auto *atom = new (_alloc)
- COFFSharedLibraryAtom(*this, hint, symbolName, importName, dllName);
- _sharedLibraryAtoms._atoms.push_back(atom);
- return atom;
- }
-
- void addFuncAtom(StringRef symbolName, StringRef dllName,
- const COFFSharedLibraryAtom *impAtom) {
- auto *atom = new (_alloc) FuncAtom(*this, symbolName, impAtom, _machine);
- _definedAtoms._atoms.push_back(atom);
- }
-
- atom_collection_vector<DefinedAtom> _definedAtoms;
- atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms;
- mutable llvm::BumpPtrAllocator _alloc;
-
- // Does the same thing as StringRef::ltrim() but removes at most one
- // character.
- StringRef ltrim1(StringRef str, const char *chars) const {
- if (!str.empty() && strchr(chars, str[0]))
- return str.substr(1);
- return str;
- }
-
- // Convert the given symbol name to the import symbol name exported by the
- // DLL.
- StringRef symbolNameToImportName(StringRef symbolName, int nameType) const {
- StringRef ret;
- switch (nameType) {
- case llvm::COFF::IMPORT_ORDINAL:
- // The import is by ordinal. No symbol name will be used to identify the
- // item in the DLL. Only its ordinal will be used.
- return "";
- case llvm::COFF::IMPORT_NAME:
- // The import name in this case is identical to the symbol name.
- return symbolName;
- case llvm::COFF::IMPORT_NAME_NOPREFIX:
- // The import name is the symbol name without leading ?, @ or _.
- ret = ltrim1(symbolName, "?@_");
- break;
- case llvm::COFF::IMPORT_NAME_UNDECORATE:
- // Similar to NOPREFIX, but we also need to truncate at the first @.
- ret = ltrim1(symbolName, "?@_");
- ret = ret.substr(0, ret.find('@'));
- break;
- }
- std::string *str = new (_alloc) std::string(ret);
- return *str;
- }
-
- std::unique_ptr<MemoryBuffer> _mb;
- MachineTypes _machine;
-};
-
-class COFFImportLibraryReader : public Reader {
-public:
- COFFImportLibraryReader(PECOFFLinkingContext &ctx) : _ctx(ctx) {}
-
- bool canParse(file_magic magic, StringRef,
- const MemoryBuffer &mb) const override {
- if (mb.getBufferSize() < sizeof(COFF::ImportHeader))
- return false;
- return (magic == llvm::sys::fs::file_magic::coff_import_library);
- }
-
- std::error_code
- loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
- std::vector<std::unique_ptr<File> > &result) const override {
- auto *file = new FileImportLibrary(std::move(mb), _ctx.getMachineType());
- result.push_back(std::unique_ptr<File>(file));
- return std::error_code();
- }
-
-private:
- PECOFFLinkingContext &_ctx;
-};
-
-} // end anonymous namespace
-
-void Registry::addSupportCOFFImportLibraries(PECOFFLinkingContext &ctx) {
- add(llvm::make_unique<COFFImportLibraryReader>(ctx));
-}
-
-} // end namespace lld
diff --git a/lib/ReaderWriter/PECOFF/WriterImportLibrary.cpp b/lib/ReaderWriter/PECOFF/WriterImportLibrary.cpp
deleted file mode 100644
index fd3360f018b6..000000000000
--- a/lib/ReaderWriter/PECOFF/WriterImportLibrary.cpp
+++ /dev/null
@@ -1,118 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/WriterImportLibrary.cpp --------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// This file is responsible for creating the Import Library file.
-///
-//===----------------------------------------------------------------------===//
-
-#include "lld/ReaderWriter/PECOFFLinkingContext.h"
-#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/Path.h"
-#include "llvm/Support/Program.h"
-#include "llvm/Support/raw_ostream.h"
-
-namespace lld {
-namespace pecoff {
-
-/// Creates a .def file containing the list of exported symbols.
-static std::string
-createModuleDefinitionFile(const PECOFFLinkingContext &ctx) {
- std::string ret;
- llvm::raw_string_ostream os(ret);
- os << "LIBRARY \"" << llvm::sys::path::filename(ctx.outputPath()) << "\"\n"
- << "EXPORTS\n";
-
- for (const PECOFFLinkingContext::ExportDesc &desc : ctx.getDllExports()) {
- // Symbol names in a module-definition file will be mangled by lib.exe,
- // so we need to demangle them before writing to a .def file.
- os << " ";
- if (!desc.externalName.empty()) {
- os << desc.externalName;
- } else if (!desc.mangledName.empty()) {
- os << ctx.undecorateSymbol(desc.mangledName);
- } else {
- os << ctx.undecorateSymbol(desc.name);
- }
-
- if (!desc.isPrivate)
- os << " @" << desc.ordinal;
- if (desc.noname)
- os << " NONAME";
- if (desc.isData)
- os << " DATA";
- if (desc.isPrivate)
- os << " PRIVATE";
- os << "\n";
- }
- os.flush();
- return 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 temporary file\n";
- return "";
- }
- llvm::raw_fd_ostream os(fd, /*shouldClose*/ true);
- os << contents;
- return path.str();
-}
-
-static void writeTo(StringRef path, StringRef contents) {
- int fd;
- if (llvm::sys::fs::openFileForWrite(path, fd, llvm::sys::fs::F_Text)) {
- llvm::errs() << "Failed to open " << path << "\n";
- return;
- }
- llvm::raw_fd_ostream os(fd, /*shouldClose*/ true);
- os << contents;
-}
-
-/// Creates a .def file and runs lib.exe on it to create an import library.
-void writeImportLibrary(const PECOFFLinkingContext &ctx) {
- std::string fileContents = createModuleDefinitionFile(ctx);
-
- std::string program = "lib.exe";
- ErrorOr<std::string> programPathOrErr = llvm::sys::findProgramByName(program);
- if (!programPathOrErr) {
- llvm::errs() << "Unable to find " << program << " in PATH\n";
- } else {
- const std::string &programPath = *programPathOrErr;
-
- std::string defPath = writeToTempFile(fileContents);
- llvm::FileRemover tmpFile(defPath);
-
- std::string defArg = "/def:";
- defArg.append(defPath);
- std::string outputArg = "/out:";
- outputArg.append(ctx.getOutputImportLibraryPath());
-
- std::vector<const char *> args;
- args.push_back(programPath.c_str());
- args.push_back("/nologo");
- args.push_back(ctx.is64Bit() ? "/machine:x64" : "/machine:x86");
- args.push_back(defArg.c_str());
- args.push_back(outputArg.c_str());
- args.push_back(nullptr);
-
- if (llvm::sys::ExecuteAndWait(programPath.c_str(), &args[0]) != 0)
- llvm::errs() << program << " failed\n";
- }
-
- // If /lldmoduledeffile:<filename> is given, make a copy of the
- // temporary module definition file. This feature is for unit tests.
- if (!ctx.getModuleDefinitionFile().empty())
- writeTo(ctx.getModuleDefinitionFile(), fileContents);
-}
-
-} // end namespace pecoff
-} // end namespace lld
diff --git a/lib/ReaderWriter/PECOFF/WriterImportLibrary.h b/lib/ReaderWriter/PECOFF/WriterImportLibrary.h
deleted file mode 100644
index a51b9a3648c5..000000000000
--- a/lib/ReaderWriter/PECOFF/WriterImportLibrary.h
+++ /dev/null
@@ -1,23 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/WriterImportLibrary.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_PE_COFF_WRITER_IMPORT_LIBRARY_H
-#define LLD_READER_WRITER_PE_COFF_WRITER_IMPORT_LIBRARY_H
-
-namespace lld {
-class PECOFFLinkingContext;
-
-namespace pecoff {
-
-void writeImportLibrary(const PECOFFLinkingContext &ctx);
-
-} // end namespace pecoff
-} // end namespace lld
-
-#endif
diff --git a/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp b/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
deleted file mode 100644
index d34e2d3d63fd..000000000000
--- a/lib/ReaderWriter/PECOFF/WriterPECOFF.cpp
+++ /dev/null
@@ -1,1417 +0,0 @@
-//===- lib/ReaderWriter/PECOFF/WriterPECOFF.cpp ---------------------------===//
-//
-// The LLVM Linker
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-///
-/// PE/COFF file consists of DOS Header, PE Header, COFF Header and Section
-/// Tables followed by raw section data.
-///
-/// This writer is responsible for writing Core Linker results to an Windows
-/// executable file.
-///
-/// This writer currently supports 32 bit PE/COFF for x86 processor only.
-///
-//===----------------------------------------------------------------------===//
-
-#include "Atoms.h"
-#include "WriterImportLibrary.h"
-#include "lld/Core/DefinedAtom.h"
-#include "lld/Core/File.h"
-#include "lld/Core/Writer.h"
-#include "lld/ReaderWriter/AtomLayout.h"
-#include "lld/ReaderWriter/PECOFFLinkingContext.h"
-#include "llvm/ADT/ArrayRef.h"
-#include "llvm/Object/COFF.h"
-#include "llvm/Support/COFF.h"
-#include "llvm/Support/Debug.h"
-#include "llvm/Support/Endian.h"
-#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/ErrorOr.h"
-#include "llvm/Support/FileOutputBuffer.h"
-#include "llvm/Support/Format.h"
-#include <algorithm>
-#include <cstdlib>
-#include <map>
-#include <time.h>
-#include <vector>
-
-#define DEBUG_TYPE "WriterPECOFF"
-
-using namespace llvm::support::endian;
-
-using llvm::COFF::DataDirectoryIndex;
-using llvm::object::coff_runtime_function_x64;
-using llvm::support::ulittle16_t;
-using llvm::support::ulittle32_t;
-using llvm::support::ulittle64_t;
-
-namespace lld {
-namespace pecoff {
-
-// Disk sector size. Some data needs to be aligned at disk sector boundary in
-// file.
-static const int SECTOR_SIZE = 512;
-
-namespace {
-class SectionChunk;
-
-/// A Chunk is an abstract contiguous range in an output file.
-class Chunk {
-public:
- enum Kind {
- kindHeader,
- kindSection,
- kindStringTable,
- kindAtomChunk
- };
-
- explicit Chunk(Kind kind) : _kind(kind), _size(0) {}
- virtual ~Chunk() {}
- virtual void write(uint8_t *buffer) = 0;
- virtual uint64_t size() const { return _size; }
- virtual uint64_t onDiskSize() const { return size(); }
- virtual uint64_t align() const { return 1; }
-
- uint64_t fileOffset() const { return _fileOffset; }
- void setFileOffset(uint64_t fileOffset) { _fileOffset = fileOffset; }
- Kind getKind() const { return _kind; }
-
-protected:
- Kind _kind;
- uint64_t _size;
- uint64_t _fileOffset;
-};
-
-/// A HeaderChunk is an abstract class to represent a file header for
-/// PE/COFF. The data in the header chunk is metadata about program and will
-/// be consumed by the windows loader. HeaderChunks are not mapped to memory
-/// when executed.
-class HeaderChunk : public Chunk {
-public:
- HeaderChunk() : Chunk(kindHeader) {}
-
- static bool classof(const Chunk *c) { return c->getKind() == kindHeader; }
-};
-
-/// A DOSStubChunk represents the DOS compatible header at the beginning
-/// of PE/COFF files.
-class DOSStubChunk : public HeaderChunk {
-public:
- explicit DOSStubChunk(const PECOFFLinkingContext &ctx)
- : HeaderChunk(), _context(ctx) {
- // Minimum size of DOS stub is 64 bytes. The next block (PE header) needs to
- // be aligned on 8 byte boundary.
- size_t size = std::max(_context.getDosStub().size(), (size_t)64);
- _size = llvm::RoundUpToAlignment(size, 8);
- }
-
- void write(uint8_t *buffer) override {
- ArrayRef<uint8_t> array = _context.getDosStub();
- std::memcpy(buffer, array.data(), array.size());
- auto *header = reinterpret_cast<llvm::object::dos_header *>(buffer);
- header->AddressOfRelocationTable = sizeof(llvm::object::dos_header);
- header->AddressOfNewExeHeader = _size;
- }
-
-private:
- const PECOFFLinkingContext &_context;
-};
-
-/// A PEHeaderChunk represents PE header including COFF header.
-template <class PEHeader>
-class PEHeaderChunk : public HeaderChunk {
-public:
- explicit PEHeaderChunk(const PECOFFLinkingContext &ctx);
-
- void write(uint8_t *buffer) override;
-
- void setSizeOfHeaders(uint64_t size) {
- // Must be multiple of FileAlignment.
- _peHeader.SizeOfHeaders = llvm::RoundUpToAlignment(size, SECTOR_SIZE);
- }
-
- void setSizeOfCode(uint64_t size) { _peHeader.SizeOfCode = size; }
- void setBaseOfCode(uint32_t rva) { _peHeader.BaseOfCode = rva; }
- void setBaseOfData(uint32_t rva);
- void setSizeOfImage(uint32_t size) { _peHeader.SizeOfImage = size; }
-
- void setSizeOfInitializedData(uint64_t size) {
- _peHeader.SizeOfInitializedData = size;
- }
-
- void setSizeOfUninitializedData(uint64_t size) {
- _peHeader.SizeOfUninitializedData = size;
- }
-
- void setNumberOfSections(uint32_t num) { _coffHeader.NumberOfSections = num; }
- void setNumberOfSymbols(uint32_t num) { _coffHeader.NumberOfSymbols = num; }
-
- void setAddressOfEntryPoint(uint32_t address) {
- _peHeader.AddressOfEntryPoint = address;
- }
-
- void setPointerToSymbolTable(uint32_t rva) {
- _coffHeader.PointerToSymbolTable = rva;
- }
-
-private:
- llvm::object::coff_file_header _coffHeader;
- PEHeader _peHeader;
-};
-
-/// A SectionHeaderTableChunk represents Section Table Header of PE/COFF
-/// format, which is a list of section headers.
-class SectionHeaderTableChunk : public HeaderChunk {
-public:
- SectionHeaderTableChunk() : HeaderChunk() {}
- void addSection(SectionChunk *chunk);
- uint64_t size() const override;
- void write(uint8_t *buffer) override;
-
-private:
- static llvm::object::coff_section createSectionHeader(SectionChunk *chunk);
-
- std::vector<SectionChunk *> _sections;
-};
-
-class StringTableChunk : public Chunk {
-public:
- StringTableChunk() : Chunk(kindStringTable) {}
-
- static bool classof(const Chunk *c) {
- return c->getKind() == kindStringTable;
- }
-
- uint32_t addSectionName(StringRef sectionName) {
- if (_stringTable.empty()) {
- // The string table immediately follows the symbol table.
- // We don't really need a symbol table, but some tools (e.g. dumpbin)
- // don't like zero-length symbol table.
- // Make room for the empty symbol slot, which occupies 18 byte.
- // We also need to reserve 4 bytes for the string table header.
- int size = sizeof(llvm::object::coff_symbol16) + 4;
- _stringTable.insert(_stringTable.begin(), size, 0);
- // Set the name of the dummy symbol to the first string table entry.
- // It's better than letting dumpbin print out a garabage as a symbol name.
- char *off = _stringTable.data() + 4;
- write32le(off, 4);
- }
- uint32_t offset = _stringTable.size();
- _stringTable.insert(_stringTable.end(), sectionName.begin(),
- sectionName.end());
- _stringTable.push_back('\0');
- return offset - sizeof(llvm::object::coff_symbol16);
- }
-
- uint64_t size() const override { return _stringTable.size(); }
-
- void write(uint8_t *buffer) override {
- if (_stringTable.empty())
- return;
- char *off = _stringTable.data() + sizeof(llvm::object::coff_symbol16);
- write32le(off, _stringTable.size());
- std::memcpy(buffer, _stringTable.data(), _stringTable.size());
- }
-
-private:
- std::vector<char> _stringTable;
-};
-
-class SectionChunk : public Chunk {
-public:
- uint64_t onDiskSize() const override {
- if (_characteristics & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
- return 0;
- return llvm::RoundUpToAlignment(size(), SECTOR_SIZE);
- }
-
- uint64_t align() const override { return SECTOR_SIZE; }
- uint32_t getCharacteristics() const { return _characteristics; }
- StringRef getSectionName() const { return _sectionName; }
- virtual uint64_t memAlign() const { return _memAlign; }
-
- static bool classof(const Chunk *c) {
- Kind kind = c->getKind();
- return kind == kindSection || kind == kindAtomChunk;
- }
-
- uint64_t getVirtualAddress() { return _virtualAddress; }
- virtual void setVirtualAddress(uint32_t rva) { _virtualAddress = rva; }
-
- uint32_t getStringTableOffset() const { return _stringTableOffset; }
- void setStringTableOffset(uint32_t offset) { _stringTableOffset = offset; }
-
-protected:
- SectionChunk(Kind kind, StringRef sectionName, uint32_t characteristics,
- const PECOFFLinkingContext &ctx)
- : Chunk(kind), _sectionName(sectionName),
- _characteristics(characteristics), _virtualAddress(0),
- _stringTableOffset(0), _memAlign(ctx.getPageSize()) {}
-
-private:
- StringRef _sectionName;
- const uint32_t _characteristics;
- uint64_t _virtualAddress;
- uint32_t _stringTableOffset;
- uint64_t _memAlign;
-};
-
-struct BaseReloc {
- BaseReloc(uint64_t a, llvm::COFF::BaseRelocationType t) : addr(a), type(t) {}
- uint64_t addr;
- llvm::COFF::BaseRelocationType type;
-};
-
-/// An AtomChunk represents a section containing atoms.
-class AtomChunk : public SectionChunk {
-public:
- AtomChunk(const PECOFFLinkingContext &ctx, StringRef name,
- const std::vector<const DefinedAtom *> &atoms);
-
- void write(uint8_t *buffer) override;
-
- uint64_t memAlign() const override;
- void appendAtom(const DefinedAtom *atom);
- void buildAtomRvaMap(std::map<const Atom *, uint64_t> &atomRva) const;
-
- void applyRelocationsARM(uint8_t *buffer,
- std::map<const Atom *, uint64_t> &atomRva,
- std::vector<uint64_t> &sectionRva,
- uint64_t imageBaseAddress);
- void applyRelocationsX86(uint8_t *buffer,
- std::map<const Atom *, uint64_t> &atomRva,
- std::vector<uint64_t> &sectionRva,
- uint64_t imageBaseAddress);
- void applyRelocationsX64(uint8_t *buffer,
- std::map<const Atom *, uint64_t> &atomRva,
- std::vector<uint64_t> &sectionRva,
- uint64_t imageBaseAddress);
-
- void printAtomAddresses(uint64_t baseAddr) const;
- void addBaseRelocations(std::vector<BaseReloc> &relocSites) const;
-
- void setVirtualAddress(uint32_t rva) override;
- uint64_t getAtomVirtualAddress(StringRef name) const;
-
- static bool classof(const Chunk *c) { return c->getKind() == kindAtomChunk; }
-
-protected:
- std::vector<AtomLayout *> _atomLayouts;
- uint64_t _virtualAddress;
-
-private:
- uint32_t
- computeCharacteristics(const PECOFFLinkingContext &ctx, StringRef name,
- const std::vector<const DefinedAtom *> &atoms) const {
- return ctx.getSectionAttributes(name,
- getDefaultCharacteristics(name, atoms));
- }
-
- uint32_t getDefaultCharacteristics(
- StringRef name, const std::vector<const DefinedAtom *> &atoms) const;
-
- mutable llvm::BumpPtrAllocator _alloc;
- llvm::COFF::MachineTypes _machineType;
- const PECOFFLinkingContext &_ctx;
-};
-
-/// A DataDirectoryChunk represents data directory entries that follows the PE
-/// header in the output file. An entry consists of an 8 byte field that
-/// indicates a relative virtual address (the starting address of the entry data
-/// in memory) and 8 byte entry data size.
-class DataDirectoryChunk : public HeaderChunk {
-public:
- DataDirectoryChunk()
- : HeaderChunk(), _data(std::vector<llvm::object::data_directory>(16)) {}
-
- uint64_t size() const override {
- return sizeof(llvm::object::data_directory) * _data.size();
- }
-
- void setField(DataDirectoryIndex index, uint32_t addr, uint32_t size);
- void write(uint8_t *buffer) override;
-
-private:
- std::vector<llvm::object::data_directory> _data;
-};
-
-/// A BaseRelocChunk represents ".reloc" section.
-///
-/// .reloc section contains a list of addresses. If the PE/COFF loader decides
-/// to load the binary at a memory address different from its preferred base
-/// address, which is specified by ImageBase field in the COFF header, the
-/// loader needs to relocate the binary, so that all the addresses in the binary
-/// point to new locations. The loader will do that by fixing up the addresses
-/// specified by .reloc section.
-///
-/// The executable is almost always loaded at the preferred base address because
-/// it's loaded into an empty address space. The DLL is however an subject of
-/// load-time relocation because it may conflict with other DLLs or the
-/// executable.
-class BaseRelocChunk : public SectionChunk {
- typedef std::vector<std::unique_ptr<Chunk> > ChunkVectorT;
-
-public:
- BaseRelocChunk(ChunkVectorT &chunks, const PECOFFLinkingContext &ctx)
- : SectionChunk(kindSection, ".reloc", characteristics, ctx),
- _ctx(ctx), _contents(createContents(chunks)) {}
-
- void write(uint8_t *buffer) override {
- std::memcpy(buffer, &_contents[0], _contents.size());
- }
-
- uint64_t size() const override { return _contents.size(); }
-
-private:
- // When loaded into memory, reloc section should be readable and writable.
- static const uint32_t characteristics =
- llvm::COFF::IMAGE_SCN_MEM_READ |
- llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
- llvm::COFF::IMAGE_SCN_MEM_DISCARDABLE;
-
- std::vector<uint8_t> createContents(ChunkVectorT &chunks) const;
-
- // Returns a list of RVAs that needs to be relocated if the binary is loaded
- // at an address different from its preferred one.
- std::vector<BaseReloc> listRelocSites(ChunkVectorT &chunks) const;
-
- // Create the content of a relocation block.
- std::vector<uint8_t>
- createBaseRelocBlock(uint64_t pageAddr, const BaseReloc *begin,
- const BaseReloc *end) const;
-
- const PECOFFLinkingContext &_ctx;
- std::vector<uint8_t> _contents;
-};
-
-template <class PEHeader>
-PEHeaderChunk<PEHeader>::PEHeaderChunk(const PECOFFLinkingContext &ctx)
- : HeaderChunk() {
- // Set the size of the chunk and initialize the header with null bytes.
- _size = sizeof(llvm::COFF::PEMagic) + sizeof(_coffHeader) + sizeof(_peHeader);
- std::memset(&_coffHeader, 0, sizeof(_coffHeader));
- std::memset(&_peHeader, 0, sizeof(_peHeader));
-
- _coffHeader.Machine = ctx.getMachineType();
- _coffHeader.TimeDateStamp = time(nullptr);
-
- // Attributes of the executable.
- uint16_t characteristics = llvm::COFF::IMAGE_FILE_EXECUTABLE_IMAGE;
- if (!ctx.is64Bit())
- characteristics |= llvm::COFF::IMAGE_FILE_32BIT_MACHINE;
- if (ctx.isDll())
- characteristics |= llvm::COFF::IMAGE_FILE_DLL;
- if (ctx.getLargeAddressAware() || ctx.is64Bit())
- characteristics |= llvm::COFF::IMAGE_FILE_LARGE_ADDRESS_AWARE;
- if (ctx.getSwapRunFromCD())
- characteristics |= llvm::COFF::IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP;
- if (ctx.getSwapRunFromNet())
- characteristics |= llvm::COFF::IMAGE_FILE_NET_RUN_FROM_SWAP;
- if (!ctx.getBaseRelocationEnabled())
- characteristics |= llvm::COFF::IMAGE_FILE_RELOCS_STRIPPED;
-
- _coffHeader.Characteristics = characteristics;
-
- _peHeader.Magic = ctx.is64Bit() ? llvm::COFF::PE32Header::PE32_PLUS
- : llvm::COFF::PE32Header::PE32;
-
- // The address of the executable when loaded into memory. The default for
- // DLLs is 0x10000000. The default for executables is 0x400000.
- _peHeader.ImageBase = ctx.getBaseAddress();
-
- // Sections should be page-aligned when loaded into memory, which is 4KB on
- // x86.
- _peHeader.SectionAlignment = ctx.getSectionDefaultAlignment();
-
- // Sections in an executable file on disk should be sector-aligned (512 byte).
- _peHeader.FileAlignment = SECTOR_SIZE;
-
- // The version number of the resultant executable/DLL. The number is purely
- // informative, and neither the linker nor the loader won't use it. User can
- // set the value using /version command line option. Default is 0.0.
- PECOFFLinkingContext::Version imageVersion = ctx.getImageVersion();
- _peHeader.MajorImageVersion = imageVersion.majorVersion;
- _peHeader.MinorImageVersion = imageVersion.minorVersion;
-
- // The required Windows version number. This is the internal version and
- // shouldn't be confused with product name. Windows 7 is version 6.1 and
- // Windows 8 is 6.2, for example.
- PECOFFLinkingContext::Version minOSVersion = ctx.getMinOSVersion();
- _peHeader.MajorOperatingSystemVersion = minOSVersion.majorVersion;
- _peHeader.MinorOperatingSystemVersion = minOSVersion.minorVersion;
- _peHeader.MajorSubsystemVersion = minOSVersion.majorVersion;
- _peHeader.MinorSubsystemVersion = minOSVersion.minorVersion;
-
- _peHeader.Subsystem = ctx.getSubsystem();
-
- // Despite its name, DLL characteristics field has meaning both for
- // executables and DLLs. We are not very sure if the following bits must
- // be set, but regular binaries seem to have these bits, so we follow
- // them.
- uint16_t dllCharacteristics = 0;
- if (ctx.noSEH())
- dllCharacteristics |= llvm::COFF::IMAGE_DLL_CHARACTERISTICS_NO_SEH;
- if (ctx.isTerminalServerAware())
- dllCharacteristics |=
- llvm::COFF::IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE;
- if (ctx.isNxCompat())
- dllCharacteristics |= llvm::COFF::IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
- if (ctx.getDynamicBaseEnabled())
- dllCharacteristics |= llvm::COFF::IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE;
- if (!ctx.getAllowBind())
- dllCharacteristics |= llvm::COFF::IMAGE_DLL_CHARACTERISTICS_NO_BIND;
- if (!ctx.getAllowIsolation())
- dllCharacteristics |= llvm::COFF::IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION;
- if (ctx.getHighEntropyVA() && ctx.is64Bit())
- dllCharacteristics |= llvm::COFF::IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA;
- _peHeader.DLLCharacteristics = dllCharacteristics;
-
- _peHeader.SizeOfStackReserve = ctx.getStackReserve();
- _peHeader.SizeOfStackCommit = ctx.getStackCommit();
- _peHeader.SizeOfHeapReserve = ctx.getHeapReserve();
- _peHeader.SizeOfHeapCommit = ctx.getHeapCommit();
-
- // The number of data directory entries. We always have 16 entries.
- _peHeader.NumberOfRvaAndSize = 16;
-
- // The size of PE header including optional data directory.
- _coffHeader.SizeOfOptionalHeader = sizeof(PEHeader) +
- _peHeader.NumberOfRvaAndSize * sizeof(llvm::object::data_directory);
-}
-
-template <>
-void PEHeaderChunk<llvm::object::pe32_header>::setBaseOfData(uint32_t rva) {
- _peHeader.BaseOfData = rva;
-}
-
-template <>
-void PEHeaderChunk<llvm::object::pe32plus_header>::setBaseOfData(uint32_t rva) {
- // BaseOfData field does not exist in PE32+ header.
-}
-
-template <class PEHeader>
-void PEHeaderChunk<PEHeader>::write(uint8_t *buffer) {
- std::memcpy(buffer, llvm::COFF::PEMagic, sizeof(llvm::COFF::PEMagic));
- buffer += sizeof(llvm::COFF::PEMagic);
- std::memcpy(buffer, &_coffHeader, sizeof(_coffHeader));
- buffer += sizeof(_coffHeader);
- std::memcpy(buffer, &_peHeader, sizeof(_peHeader));
-}
-
-AtomChunk::AtomChunk(const PECOFFLinkingContext &ctx, StringRef sectionName,
- const std::vector<const DefinedAtom *> &atoms)
- : SectionChunk(kindAtomChunk, sectionName,
- computeCharacteristics(ctx, sectionName, atoms), ctx),
- _virtualAddress(0), _machineType(ctx.getMachineType()), _ctx(ctx) {
- for (auto *a : atoms)
- appendAtom(a);
-}
-
-void AtomChunk::write(uint8_t *buffer) {
- if (_atomLayouts.empty())
- return;
- if (getCharacteristics() & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
- return;
- if (getCharacteristics() & llvm::COFF::IMAGE_SCN_CNT_CODE) {
- // Fill the section with INT 3 (0xCC) rather than NUL, so that the
- // disassembler will not interpret a garbage between atoms as the beginning
- // of multi-byte machine code. This does not change the behavior of
- // resulting binary but help debugging.
- uint8_t *start = buffer + _atomLayouts.front()->_fileOffset;
- uint8_t *end = buffer + _atomLayouts.back()->_fileOffset;
- memset(start, 0xCC, end - start);
- }
-
- for (const auto *layout : _atomLayouts) {
- const DefinedAtom *atom = cast<DefinedAtom>(layout->_atom);
- ArrayRef<uint8_t> rawContent = atom->rawContent();
- std::memcpy(buffer + layout->_fileOffset, rawContent.data(),
- rawContent.size());
- }
-}
-
-// Add all atoms to the given map. This data will be used to do relocation.
-void
-AtomChunk::buildAtomRvaMap(std::map<const Atom *, uint64_t> &atomRva) const {
- for (const auto *layout : _atomLayouts)
- atomRva[layout->_atom] = layout->_virtualAddr;
-}
-
-static int getSectionIndex(uint64_t targetAddr,
- const std::vector<uint64_t> &sectionRva) {
- int i = 1;
- for (uint64_t rva : sectionRva) {
- if (targetAddr < rva)
- return i;
- ++i;
- }
- return i;
-}
-
-static uint32_t getSectionStartAddr(uint64_t targetAddr,
- const std::vector<uint64_t> &sectionRva) {
- // Scan the list of section start addresses to find the section start address
- // for the given RVA.
- for (int i = 0, e = sectionRva.size(); i < e; ++i)
- if (i == e - 1 || (sectionRva[i] <= targetAddr && targetAddr < sectionRva[i + 1]))
- return sectionRva[i];
- llvm_unreachable("Section missing");
-}
-
-static void applyThumbMoveImmediate(ulittle16_t *mov, uint16_t imm) {
- // MOVW(T3): |11110|i|10|0|1|0|0|imm4|0|imm3|Rd|imm8|
- // imm32 = zext imm4:i:imm3:imm8
- // MOVT(T1): |11110|i|10|1|1|0|0|imm4|0|imm3|Rd|imm8|
- // imm16 = imm4:i:imm3:imm8
- mov[0] =
- mov[0] | (((imm & 0x0800) >> 11) << 10) | (((imm & 0xf000) >> 12) << 0);
- mov[1] =
- mov[1] | (((imm & 0x0700) >> 8) << 12) | (((imm & 0x00ff) >> 0) << 0);
-}
-
-static void applyThumbBranchImmediate(ulittle16_t *bl, int32_t imm) {
- // BL(T1): |11110|S|imm10|11|J1|1|J2|imm11|
- // imm32 = sext S:I1:I2:imm10:imm11:'0'
- // B.W(T4): |11110|S|imm10|10|J1|1|J2|imm11|
- // imm32 = sext S:I1:I2:imm10:imm11:'0'
- //
- // I1 = ~(J1 ^ S), I2 = ~(J2 ^ S)
-
- assert((~abs(imm) & (-1 << 24)) && "bl/b.w out of range");
-
- uint32_t S = (imm < 0 ? 1 : 0);
- uint32_t J1 = ((~imm & 0x00800000) >> 23) ^ S;
- uint32_t J2 = ((~imm & 0x00400000) >> 22) ^ S;
-
- bl[0] = bl[0] | (((imm & 0x003ff000) >> 12) << 0) | (S << 10);
- bl[1] = bl[1] | (((imm & 0x00000ffe) >> 1) << 0) | (J2 << 11) | (J1 << 13);
-}
-
-void AtomChunk::applyRelocationsARM(uint8_t *Buffer,
- std::map<const Atom *, uint64_t> &AtomRVA,
- std::vector<uint64_t> &SectionRVA,
- uint64_t ImageBase) {
- Buffer = Buffer + _fileOffset;
- parallel_for_each(_atomLayouts.begin(), _atomLayouts.end(),
- [&](const AtomLayout *layout) {
- const DefinedAtom *Atom = cast<DefinedAtom>(layout->_atom);
- for (const Reference *R : *Atom) {
- if (R->kindNamespace() != Reference::KindNamespace::COFF)
- continue;
-
- bool AssumeTHUMBCode = false;
- if (auto Target = dyn_cast<DefinedAtom>(R->target()))
- AssumeTHUMBCode = Target->permissions() == DefinedAtom::permR_X ||
- Target->permissions() == DefinedAtom::permRWX;
-
- const auto AtomOffset = R->offsetInAtom();
- const auto FileOffset = layout->_fileOffset;
- const auto TargetAddr = AtomRVA[R->target()] | (AssumeTHUMBCode ? 1 : 0);
- auto RelocSite16 =
- reinterpret_cast<ulittle16_t *>(Buffer + FileOffset + AtomOffset);
- auto RelocSite32 =
- reinterpret_cast<ulittle32_t *>(Buffer + FileOffset + AtomOffset);
-
- switch (R->kindValue()) {
- default: llvm_unreachable("unsupported relocation type");
- case llvm::COFF::IMAGE_REL_ARM_ADDR32:
- *RelocSite32 = *RelocSite32 + TargetAddr + ImageBase;
- break;
- case llvm::COFF::IMAGE_REL_ARM_ADDR32NB:
- *RelocSite32 = *RelocSite32 + TargetAddr;
- break;
- case llvm::COFF::IMAGE_REL_ARM_MOV32T:
- applyThumbMoveImmediate(&RelocSite16[0], (TargetAddr + ImageBase) >> 0);
- applyThumbMoveImmediate(&RelocSite16[2], (TargetAddr + ImageBase) >> 16);
- break;
- case llvm::COFF::IMAGE_REL_ARM_BRANCH24T:
- // NOTE: the thumb bit will implicitly be truncated properly
- applyThumbBranchImmediate(RelocSite16,
- TargetAddr - AtomRVA[Atom] - AtomOffset - 4);
- break;
- case llvm::COFF::IMAGE_REL_ARM_BLX23T:
- // NOTE: the thumb bit will implicitly be truncated properly
- applyThumbBranchImmediate(RelocSite16,
- TargetAddr - AtomRVA[Atom] - AtomOffset - 4);
- break;
- }
- }
- });
-}
-
-void AtomChunk::applyRelocationsX86(uint8_t *buffer,
- std::map<const Atom *, uint64_t> &atomRva,
- std::vector<uint64_t> &sectionRva,
- uint64_t imageBaseAddress) {
- buffer += _fileOffset;
- parallel_for_each(_atomLayouts.begin(), _atomLayouts.end(),
- [&](const AtomLayout *layout) {
- const DefinedAtom *atom = cast<DefinedAtom>(layout->_atom);
- for (const Reference *ref : *atom) {
- // Skip if this reference is not for COFF relocation.
- if (ref->kindNamespace() != Reference::KindNamespace::COFF)
- continue;
- auto relocSite32 = reinterpret_cast<ulittle32_t *>(
- buffer + layout->_fileOffset + ref->offsetInAtom());
- auto relocSite16 = reinterpret_cast<ulittle16_t *>(relocSite32);
- const Atom *target = ref->target();
- uint64_t targetAddr = atomRva[target];
- // Also account for whatever offset is already stored at the relocation
- // site.
- switch (ref->kindValue()) {
- case llvm::COFF::IMAGE_REL_I386_ABSOLUTE:
- // This relocation is no-op.
- break;
- case llvm::COFF::IMAGE_REL_I386_DIR32:
- // Set target's 32-bit VA.
- if (auto *abs = dyn_cast<AbsoluteAtom>(target))
- *relocSite32 += abs->value();
- else
- *relocSite32 += targetAddr + imageBaseAddress;
- break;
- case llvm::COFF::IMAGE_REL_I386_DIR32NB:
- // Set target's 32-bit RVA.
- *relocSite32 += targetAddr;
- break;
- case llvm::COFF::IMAGE_REL_I386_REL32: {
- // Set 32-bit relative address of the target. This relocation is
- // usually used for relative branch or call instruction.
- uint32_t disp = atomRva[atom] + ref->offsetInAtom() + 4;
- *relocSite32 += targetAddr - disp;
- break;
- }
- case llvm::COFF::IMAGE_REL_I386_SECTION:
- // The 16-bit section index that contains the target symbol.
- *relocSite16 += getSectionIndex(targetAddr, sectionRva);
- break;
- case llvm::COFF::IMAGE_REL_I386_SECREL:
- // The 32-bit relative address from the beginning of the section that
- // contains the target symbol.
- *relocSite32 +=
- targetAddr - getSectionStartAddr(targetAddr, sectionRva);
- break;
- default:
- llvm::report_fatal_error("Unsupported relocation kind");
- }
- }
- });
-}
-
-void AtomChunk::applyRelocationsX64(uint8_t *buffer,
- std::map<const Atom *, uint64_t> &atomRva,
- std::vector<uint64_t> &sectionRva,
- uint64_t imageBase) {
- buffer += _fileOffset;
- parallel_for_each(_atomLayouts.begin(), _atomLayouts.end(),
- [&](const AtomLayout *layout) {
- const DefinedAtom *atom = cast<DefinedAtom>(layout->_atom);
- for (const Reference *ref : *atom) {
- if (ref->kindNamespace() != Reference::KindNamespace::COFF)
- continue;
-
- uint8_t *loc = buffer + layout->_fileOffset + ref->offsetInAtom();
- auto relocSite16 = reinterpret_cast<ulittle16_t *>(loc);
- auto relocSite32 = reinterpret_cast<ulittle32_t *>(loc);
- auto relocSite64 = reinterpret_cast<ulittle64_t *>(loc);
- uint64_t targetAddr = atomRva[ref->target()];
-
- switch (ref->kindValue()) {
- case llvm::COFF::IMAGE_REL_AMD64_ADDR64:
- *relocSite64 += targetAddr + imageBase;
- break;
- case llvm::COFF::IMAGE_REL_AMD64_ADDR32:
- *relocSite32 += targetAddr + imageBase;
- break;
- case llvm::COFF::IMAGE_REL_AMD64_ADDR32NB:
- *relocSite32 += targetAddr;
- break;
- case llvm::COFF::IMAGE_REL_AMD64_REL32:
- *relocSite32 += targetAddr - atomRva[atom] - ref->offsetInAtom() - 4;
- break;
- case llvm::COFF::IMAGE_REL_AMD64_REL32_1:
- *relocSite32 += targetAddr - atomRva[atom] - ref->offsetInAtom() - 5;
- break;
- case llvm::COFF::IMAGE_REL_AMD64_REL32_2:
- *relocSite32 += targetAddr - atomRva[atom] - ref->offsetInAtom() - 6;
- break;
- case llvm::COFF::IMAGE_REL_AMD64_REL32_3:
- *relocSite32 += targetAddr - atomRva[atom] - ref->offsetInAtom() - 7;
- break;
- case llvm::COFF::IMAGE_REL_AMD64_REL32_4:
- *relocSite32 += targetAddr - atomRva[atom] - ref->offsetInAtom() - 8;
- break;
- case llvm::COFF::IMAGE_REL_AMD64_REL32_5:
- *relocSite32 += targetAddr - atomRva[atom] - ref->offsetInAtom() - 9;
- break;
- case llvm::COFF::IMAGE_REL_AMD64_SECTION:
- *relocSite16 += getSectionIndex(targetAddr, sectionRva) - 1;
- break;
- case llvm::COFF::IMAGE_REL_AMD64_SECREL:
- *relocSite32 +=
- targetAddr - getSectionStartAddr(targetAddr, sectionRva);
- break;
- default:
- llvm::errs() << "Kind: " << (int)ref->kindValue() << "\n";
- llvm::report_fatal_error("Unsupported relocation kind");
- }
- }
- });
-}
-
-/// Print atom VAs. Used only for debugging.
-void AtomChunk::printAtomAddresses(uint64_t baseAddr) const {
- for (const auto *layout : _atomLayouts) {
- const DefinedAtom *atom = cast<DefinedAtom>(layout->_atom);
- uint64_t addr = layout->_virtualAddr;
- llvm::dbgs() << llvm::format("0x%08llx: ", addr + baseAddr)
- << (atom->name().empty() ? "(anonymous)" : atom->name())
- << "\n";
- }
-}
-
-/// List all virtual addresses (and not relative virtual addresses) that need
-/// to be fixed up if image base is relocated. The only relocation type that
-/// needs to be fixed is DIR32 on i386. REL32 is not (and should not be)
-/// fixed up because it's PC-relative.
-void AtomChunk::addBaseRelocations(std::vector<BaseReloc> &relocSites) const {
- for (const auto *layout : _atomLayouts) {
- const DefinedAtom *atom = cast<DefinedAtom>(layout->_atom);
- for (const Reference *ref : *atom) {
- if (ref->kindNamespace() != Reference::KindNamespace::COFF)
- continue;
-
- // An absolute symbol points to a fixed location in memory. Their
- // address should not be fixed at load time. One exception is ImageBase
- // because that's relative to run-time image base address.
- if (auto *abs = dyn_cast<AbsoluteAtom>(ref->target()))
- if (!abs->name().equals("__ImageBase") &&
- !abs->name().equals("___ImageBase"))
- continue;
-
- uint64_t address = layout->_virtualAddr + ref->offsetInAtom();
- switch (_machineType) {
- default: llvm_unreachable("unsupported machine type");
- case llvm::COFF::IMAGE_FILE_MACHINE_I386:
- if (ref->kindValue() == llvm::COFF::IMAGE_REL_I386_DIR32)
- relocSites.push_back(
- BaseReloc(address, llvm::COFF::IMAGE_REL_BASED_HIGHLOW));
- break;
- case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
- if (ref->kindValue() == llvm::COFF::IMAGE_REL_AMD64_ADDR64)
- relocSites.push_back(
- BaseReloc(address, llvm::COFF::IMAGE_REL_BASED_DIR64));
- break;
- case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
- if (ref->kindValue() == llvm::COFF::IMAGE_REL_ARM_ADDR32)
- relocSites.push_back(
- BaseReloc(address, llvm::COFF::IMAGE_REL_BASED_HIGHLOW));
- else if (ref->kindValue() == llvm::COFF::IMAGE_REL_ARM_MOV32T)
- relocSites.push_back(
- BaseReloc(address, llvm::COFF::IMAGE_REL_BASED_ARM_MOV32T));
- break;
- }
- }
- }
-}
-
-void AtomChunk::setVirtualAddress(uint32_t rva) {
- SectionChunk::setVirtualAddress(rva);
- for (AtomLayout *layout : _atomLayouts)
- layout->_virtualAddr += rva;
-}
-
-uint64_t AtomChunk::getAtomVirtualAddress(StringRef name) const {
- for (auto atomLayout : _atomLayouts)
- if (atomLayout->_atom->name() == name)
- return atomLayout->_virtualAddr;
- return 0;
-}
-
-void DataDirectoryChunk::setField(DataDirectoryIndex index, uint32_t addr,
- uint32_t size) {
- llvm::object::data_directory &dir = _data[index];
- dir.RelativeVirtualAddress = addr;
- dir.Size = size;
-}
-
-void DataDirectoryChunk::write(uint8_t *buffer) {
- std::memcpy(buffer, &_data[0], size());
-}
-
-uint64_t AtomChunk::memAlign() const {
- // ReaderCOFF propagated the section alignment to the first atom in
- // the section. We restore that here.
- if (_atomLayouts.empty())
- return _ctx.getPageSize();
- int align = _ctx.getPageSize();
- for (auto atomLayout : _atomLayouts) {
- auto *atom = cast<const DefinedAtom>(atomLayout->_atom);
- align = std::max(align, 1 << atom->alignment().powerOf2);
- }
- return align;
-}
-
-void AtomChunk::appendAtom(const DefinedAtom *atom) {
- // Atom may have to be at a proper alignment boundary. If so, move the
- // pointer to make a room after the last atom before adding new one.
- _size = llvm::RoundUpToAlignment(_size, 1 << atom->alignment().powerOf2);
-
- // Create an AtomLayout and move the current pointer.
- auto *layout = new (_alloc) AtomLayout(atom, _size, _size);
- _atomLayouts.push_back(layout);
- _size += atom->size();
-}
-
-uint32_t AtomChunk::getDefaultCharacteristics(
- StringRef name, const std::vector<const DefinedAtom *> &atoms) const {
- const uint32_t code = llvm::COFF::IMAGE_SCN_CNT_CODE;
- const uint32_t execute = llvm::COFF::IMAGE_SCN_MEM_EXECUTE;
- const uint32_t read = llvm::COFF::IMAGE_SCN_MEM_READ;
- const uint32_t write = llvm::COFF::IMAGE_SCN_MEM_WRITE;
- const uint32_t data = llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA;
- const uint32_t bss = llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA;
- if (name == ".text")
- return code | execute | read;
- if (name == ".data")
- return data | read | write;
- if (name == ".rdata")
- return data | read;
- if (name == ".bss")
- return bss | read | write;
- assert(atoms.size() > 0);
- switch (atoms[0]->permissions()) {
- case DefinedAtom::permR__:
- return data | read;
- case DefinedAtom::permRW_:
- return data | read | write;
- case DefinedAtom::permR_X:
- return code | execute | read;
- case DefinedAtom::permRWX:
- return code | execute | read | write;
- default:
- llvm_unreachable("Unsupported permission");
- }
-}
-
-void SectionHeaderTableChunk::addSection(SectionChunk *chunk) {
- _sections.push_back(chunk);
-}
-
-uint64_t SectionHeaderTableChunk::size() const {
- return _sections.size() * sizeof(llvm::object::coff_section);
-}
-
-void SectionHeaderTableChunk::write(uint8_t *buffer) {
- uint64_t offset = 0;
- for (SectionChunk *chunk : _sections) {
- llvm::object::coff_section header = createSectionHeader(chunk);
- std::memcpy(buffer + offset, &header, sizeof(header));
- offset += sizeof(header);
- }
-}
-
-llvm::object::coff_section
-SectionHeaderTableChunk::createSectionHeader(SectionChunk *chunk) {
- llvm::object::coff_section header;
-
- // We have extended the COFF specification by allowing section names to be
- // greater than eight characters. We achieve this by adding the section names
- // to the string table. Binutils' linker, ld, performs the same trick.
- StringRef sectionName = chunk->getSectionName();
- std::memset(header.Name, 0, llvm::COFF::NameSize);
- if (uint32_t stringTableOffset = chunk->getStringTableOffset())
- sprintf(header.Name, "/%u", stringTableOffset);
- else
- std::strncpy(header.Name, sectionName.data(), sectionName.size());
-
- uint32_t characteristics = chunk->getCharacteristics();
- header.VirtualSize = chunk->size();
- header.VirtualAddress = chunk->getVirtualAddress();
- header.SizeOfRawData = chunk->onDiskSize();
- header.PointerToRelocations = 0;
- header.PointerToLinenumbers = 0;
- header.NumberOfRelocations = 0;
- header.NumberOfLinenumbers = 0;
- header.Characteristics = characteristics;
-
- if (characteristics & llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) {
- header.PointerToRawData = 0;
- } else {
- header.PointerToRawData = chunk->fileOffset();
- }
- return header;
-}
-
-/// Creates .reloc section content from the other sections. The content of
-/// .reloc is basically a list of relocation sites. The relocation sites are
-/// divided into blocks. Each block represents the base relocation for a 4K
-/// page.
-///
-/// By dividing 32 bit RVAs into blocks, COFF saves disk and memory space for
-/// the base relocation. A block consists of a 32 bit page RVA and 16 bit
-/// relocation entries which represent offsets in the page. That is a more
-/// compact representation than a simple vector of 32 bit RVAs.
-std::vector<uint8_t>
-BaseRelocChunk::createContents(ChunkVectorT &chunks) const {
- std::vector<uint8_t> contents;
- std::vector<BaseReloc> relocSites = listRelocSites(chunks);
-
- uint64_t mask = _ctx.getPageSize() - 1;
- parallel_sort(relocSites.begin(), relocSites.end(),
- [=](const BaseReloc &a, const BaseReloc &b) {
- return (a.addr & ~mask) < (b.addr & ~mask);
- });
-
- // Base relocations for the same memory page are grouped together
- // and passed to createBaseRelocBlock.
- for (auto it = relocSites.begin(), e = relocSites.end(); it != e;) {
- auto beginIt = it;
- uint64_t pageAddr = (beginIt->addr & ~mask);
- for (++it; it != e; ++it)
- if ((it->addr & ~mask) != pageAddr)
- break;
- const BaseReloc *begin = &*beginIt;
- const BaseReloc *end = begin + (it - beginIt);
- std::vector<uint8_t> block = createBaseRelocBlock(pageAddr, begin, end);
- contents.insert(contents.end(), block.begin(), block.end());
- }
- return contents;
-}
-
-// Returns a list of RVAs that needs to be relocated if the binary is loaded
-// at an address different from its preferred one.
-std::vector<BaseReloc>
-BaseRelocChunk::listRelocSites(ChunkVectorT &chunks) const {
- std::vector<BaseReloc> ret;
- for (auto &cp : chunks)
- if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp))
- chunk->addBaseRelocations(ret);
- return ret;
-}
-
-// Create the content of a relocation block.
-std::vector<uint8_t>
-BaseRelocChunk::createBaseRelocBlock(uint64_t pageAddr,
- const BaseReloc *begin,
- const BaseReloc *end) const {
- // Relocation blocks should be padded with IMAGE_REL_I386_ABSOLUTE to be
- // aligned to a DWORD size boundary.
- uint32_t size = llvm::RoundUpToAlignment(
- sizeof(ulittle32_t) * 2 + sizeof(ulittle16_t) * (end - begin),
- sizeof(ulittle32_t));
- std::vector<uint8_t> contents(size);
- uint8_t *ptr = &contents[0];
-
- // The first four bytes is the page RVA.
- write32le(ptr, pageAddr);
- ptr += sizeof(ulittle32_t);
-
- // The second four bytes is the size of the block, including the the page
- // RVA and this size field.
- write32le(ptr, size);
- ptr += sizeof(ulittle32_t);
-
- uint64_t mask = _ctx.getPageSize() - 1;
- for (const BaseReloc *i = begin; i < end; ++i) {
- write16le(ptr, (i->type << 12) | (i->addr & mask));
- ptr += sizeof(ulittle16_t);
- }
- return contents;
-}
-
-} // end anonymous namespace
-
-class PECOFFWriter : public Writer {
-public:
- explicit PECOFFWriter(const PECOFFLinkingContext &context)
- : _ctx(context), _numSections(0), _imageSizeInMemory(_ctx.getPageSize()),
- _imageSizeOnDisk(0) {}
-
- template <class PEHeader> void build(const File &linkedFile);
- std::error_code writeFile(const File &linkedFile, StringRef path) override;
-
-private:
- void applyAllRelocations(uint8_t *bufferStart);
- void printAllAtomAddresses() const;
- void reorderSEHTableEntries(uint8_t *bufferStart);
- void reorderSEHTableEntriesX86(uint8_t *bufferStart);
- void reorderSEHTableEntriesX64(uint8_t *bufferStart);
-
- void addChunk(Chunk *chunk);
- void addSectionChunk(std::unique_ptr<SectionChunk> chunk,
- SectionHeaderTableChunk *table,
- StringTableChunk *stringTable);
- void setImageSizeOnDisk();
- uint64_t
- calcSectionSize(llvm::COFF::SectionCharacteristics sectionType) const;
-
- uint64_t calcSizeOfInitializedData() const {
- return calcSectionSize(llvm::COFF::IMAGE_SCN_CNT_INITIALIZED_DATA);
- }
-
- uint64_t calcSizeOfUninitializedData() const {
- return calcSectionSize(llvm::COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA);
- }
-
- uint64_t calcSizeOfCode() const {
- return calcSectionSize(llvm::COFF::IMAGE_SCN_CNT_CODE);
- }
-
- std::vector<std::unique_ptr<Chunk> > _chunks;
- const PECOFFLinkingContext &_ctx;
- uint32_t _numSections;
-
- // The size of the image in memory. This is initialized with
- // _ctx.getPageSize(), as the first page starting at ImageBase is usually left
- // unmapped. IIUC there's no technical reason to do so, but we'll follow that
- // convention so that we don't produce odd-looking binary.
- uint32_t _imageSizeInMemory;
-
- // The size of the image on disk. This is basically the sum of all chunks in
- // the output file with paddings between them.
- uint32_t _imageSizeOnDisk;
-
- // The map from atom to its relative virtual address.
- std::map<const Atom *, uint64_t> _atomRva;
-};
-
-StringRef customSectionName(const DefinedAtom *atom) {
- assert(atom->sectionChoice() == DefinedAtom::sectionCustomRequired);
- StringRef s = atom->customSectionName();
- size_t pos = s.find('$');
- return (pos == StringRef::npos) ? s : s.substr(0, pos);
-}
-
-StringRef chooseSectionByContent(const DefinedAtom *atom) {
- switch (atom->contentType()) {
- case DefinedAtom::typeCode:
- return ".text";
- case DefinedAtom::typeZeroFill:
- return ".bss";
- case DefinedAtom::typeData:
- if (atom->permissions() == DefinedAtom::permR__)
- return ".rdata";
- if (atom->permissions() == DefinedAtom::permRW_)
- return ".data";
- break;
- default:
- break;
- }
- llvm::errs() << "Atom: contentType=" << atom->contentType()
- << " permission=" << atom->permissions() << "\n";
- llvm::report_fatal_error("Failed to choose section based on content");
-}
-
-typedef std::map<StringRef, std::vector<const DefinedAtom *> > AtomVectorMap;
-
-void groupAtoms(const PECOFFLinkingContext &ctx, const File &file,
- AtomVectorMap &result) {
- for (const DefinedAtom *atom : file.defined()) {
- if (atom->sectionChoice() == DefinedAtom::sectionCustomRequired) {
- StringRef section = customSectionName(atom);
- result[ctx.getOutputSectionName(section)].push_back(atom);
- continue;
- }
- if (atom->sectionChoice() == DefinedAtom::sectionBasedOnContent) {
- StringRef section = chooseSectionByContent(atom);
- result[ctx.getOutputSectionName(section)].push_back(atom);
- continue;
- }
- llvm_unreachable("Unknown section choice");
- }
-}
-
-static const DefinedAtom *findTLSUsedSymbol(const PECOFFLinkingContext &ctx,
- const File &file) {
- StringRef sym = ctx.decorateSymbol("_tls_used");
- for (const DefinedAtom *atom : file.defined())
- if (atom->name() == sym)
- return atom;
- return nullptr;
-}
-
-// Create all chunks that consist of the output file.
-template <class PEHeader>
-void PECOFFWriter::build(const File &linkedFile) {
- AtomVectorMap atoms;
- groupAtoms(_ctx, linkedFile, atoms);
-
- // Create file chunks and add them to the list.
- auto *dosStub = new DOSStubChunk(_ctx);
- auto *peHeader = new PEHeaderChunk<PEHeader>(_ctx);
- auto *dataDirectory = new DataDirectoryChunk();
- auto *sectionTable = new SectionHeaderTableChunk();
- auto *stringTable = new StringTableChunk();
- addChunk(dosStub);
- addChunk(peHeader);
- addChunk(dataDirectory);
- addChunk(sectionTable);
- addChunk(stringTable);
-
- // Create sections and add the atoms to them.
- for (auto i : atoms) {
- StringRef sectionName = i.first;
- std::vector<const DefinedAtom *> &contents = i.second;
- std::unique_ptr<SectionChunk> section(
- new AtomChunk(_ctx, sectionName, contents));
- if (section->size() > 0)
- addSectionChunk(std::move(section), sectionTable, stringTable);
- }
-
- // Build atom to its RVA map.
- for (std::unique_ptr<Chunk> &cp : _chunks)
- if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp))
- chunk->buildAtomRvaMap(_atomRva);
-
- // We know the addresses of all defined atoms that needs to be
- // relocated. So we can create the ".reloc" section which contains
- // all the relocation sites.
- if (_ctx.getBaseRelocationEnabled()) {
- std::unique_ptr<SectionChunk> baseReloc(new BaseRelocChunk(_chunks, _ctx));
- if (baseReloc->size()) {
- SectionChunk &ref = *baseReloc;
- addSectionChunk(std::move(baseReloc), sectionTable, stringTable);
- dataDirectory->setField(DataDirectoryIndex::BASE_RELOCATION_TABLE,
- ref.getVirtualAddress(), ref.size());
- }
- }
-
- setImageSizeOnDisk();
-
- if (stringTable->size()) {
- peHeader->setPointerToSymbolTable(stringTable->fileOffset());
- peHeader->setNumberOfSymbols(1);
- }
-
- for (std::unique_ptr<Chunk> &chunk : _chunks) {
- SectionChunk *section = dyn_cast<SectionChunk>(chunk.get());
- if (!section)
- continue;
- if (section->getSectionName() == ".text") {
- peHeader->setBaseOfCode(section->getVirtualAddress());
-
- // Find the virtual address of the entry point symbol if any. PECOFF spec
- // says that entry point for dll images is optional, in which case it must
- // be set to 0.
- if (_ctx.hasEntry()) {
- AtomChunk *atom = cast<AtomChunk>(section);
- uint64_t entryPointAddress =
- atom->getAtomVirtualAddress(_ctx.getEntrySymbolName());
-
- if (entryPointAddress) {
- // NOTE: ARM NT assumes a pure THUMB execution, so adjust the entry
- // point accordingly
- if (_ctx.getMachineType() == llvm::COFF::IMAGE_FILE_MACHINE_ARMNT)
- entryPointAddress |= 1;
- peHeader->setAddressOfEntryPoint(entryPointAddress);
- }
- } else {
- peHeader->setAddressOfEntryPoint(0);
- }
- }
- StringRef name = section->getSectionName();
- if (name == ".data") {
- peHeader->setBaseOfData(section->getVirtualAddress());
- continue;
- }
- DataDirectoryIndex ignore = DataDirectoryIndex(-1);
- DataDirectoryIndex idx = llvm::StringSwitch<DataDirectoryIndex>(name)
- .Case(".pdata", DataDirectoryIndex::EXCEPTION_TABLE)
- .Case(".rsrc", DataDirectoryIndex::RESOURCE_TABLE)
- .Case(".idata.a", DataDirectoryIndex::IAT)
- .Case(".idata.d", DataDirectoryIndex::IMPORT_TABLE)
- .Case(".edata", DataDirectoryIndex::EXPORT_TABLE)
- .Case(".loadcfg", DataDirectoryIndex::LOAD_CONFIG_TABLE)
- .Case(".didat.d", DataDirectoryIndex::DELAY_IMPORT_DESCRIPTOR)
- .Default(ignore);
- if (idx == ignore)
- continue;
- dataDirectory->setField(idx, section->getVirtualAddress(), section->size());
- }
-
- if (const DefinedAtom *atom = findTLSUsedSymbol(_ctx, linkedFile)) {
- dataDirectory->setField(DataDirectoryIndex::TLS_TABLE, _atomRva[atom],
- 0x18);
- }
-
- // Now that we know the size and file offset of sections. Set the file
- // header accordingly.
- peHeader->setSizeOfCode(calcSizeOfCode());
- peHeader->setSizeOfInitializedData(calcSizeOfInitializedData());
- peHeader->setSizeOfUninitializedData(calcSizeOfUninitializedData());
- peHeader->setNumberOfSections(_numSections);
- peHeader->setSizeOfImage(_imageSizeInMemory);
- peHeader->setSizeOfHeaders(sectionTable->fileOffset() + sectionTable->size());
-}
-
-std::error_code PECOFFWriter::writeFile(const File &linkedFile,
- StringRef path) {
- if (_ctx.is64Bit()) {
- this->build<llvm::object::pe32plus_header>(linkedFile);
- } else {
- this->build<llvm::object::pe32_header>(linkedFile);
- }
-
- uint64_t totalSize =
- _chunks.back()->fileOffset() + _chunks.back()->onDiskSize();
- std::unique_ptr<llvm::FileOutputBuffer> buffer;
- std::error_code ec = llvm::FileOutputBuffer::create(
- path, totalSize, buffer, llvm::FileOutputBuffer::F_executable);
- if (ec)
- return ec;
-
- for (std::unique_ptr<Chunk> &chunk : _chunks)
- chunk->write(buffer->getBufferStart() + chunk->fileOffset());
- applyAllRelocations(buffer->getBufferStart());
- reorderSEHTableEntries(buffer->getBufferStart());
- DEBUG(printAllAtomAddresses());
-
- if (_ctx.isDll())
- writeImportLibrary(_ctx);
-
- return buffer->commit();
-}
-
-/// Apply relocations to the output file buffer. This two pass. In the first
-/// pass, we visit all atoms to create a map from atom to its virtual
-/// address. In the second pass, we visit all relocation references to fix
-/// up addresses in the buffer.
-void PECOFFWriter::applyAllRelocations(uint8_t *bufferStart) {
- // Create the list of section start addresses. It's needed for
- // relocations of SECREL type.
- std::vector<uint64_t> sectionRva;
- for (auto &cp : _chunks)
- if (SectionChunk *section = dyn_cast<SectionChunk>(&*cp))
- sectionRva.push_back(section->getVirtualAddress());
-
- uint64_t base = _ctx.getBaseAddress();
- for (auto &cp : _chunks) {
- if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp)) {
- switch (_ctx.getMachineType()) {
- default: llvm_unreachable("unsupported machine type");
- case llvm::COFF::IMAGE_FILE_MACHINE_ARMNT:
- chunk->applyRelocationsARM(bufferStart, _atomRva, sectionRva, base);
- break;
- case llvm::COFF::IMAGE_FILE_MACHINE_I386:
- chunk->applyRelocationsX86(bufferStart, _atomRva, sectionRva, base);
- break;
- case llvm::COFF::IMAGE_FILE_MACHINE_AMD64:
- chunk->applyRelocationsX64(bufferStart, _atomRva, sectionRva, base);
- break;
- }
- }
- }
-}
-
-/// Print atom VAs. Used only for debugging.
-void PECOFFWriter::printAllAtomAddresses() const {
- for (auto &cp : _chunks)
- if (AtomChunk *chunk = dyn_cast<AtomChunk>(&*cp))
- chunk->printAtomAddresses(_ctx.getBaseAddress());
-}
-
-void PECOFFWriter::reorderSEHTableEntries(uint8_t *bufferStart) {
- auto machineType = _ctx.getMachineType();
- if (machineType == llvm::COFF::IMAGE_FILE_MACHINE_I386)
- reorderSEHTableEntriesX86(bufferStart);
- if (machineType == llvm::COFF::IMAGE_FILE_MACHINE_AMD64)
- reorderSEHTableEntriesX64(bufferStart);
-}
-
-/// It seems that the entries in .sxdata must be sorted. This function is called
-/// after a COFF file image is created in memory and before it is written to
-/// disk. It is safe to reorder entries at this stage because the contents of
-/// the entries are RVAs and there's no reference to a .sxdata entry other than
-/// to the beginning of the section.
-void PECOFFWriter::reorderSEHTableEntriesX86(uint8_t *bufferStart) {
- for (std::unique_ptr<Chunk> &chunk : _chunks) {
- if (SectionChunk *section = dyn_cast<SectionChunk>(chunk.get())) {
- if (section->getSectionName() == ".sxdata") {
- int numEntries = section->size() / sizeof(ulittle32_t);
- ulittle32_t *begin = reinterpret_cast<ulittle32_t *>(bufferStart + section->fileOffset());
- ulittle32_t *end = begin + numEntries;
- std::sort(begin, end);
- }
- }
- }
-}
-
-/// The entries in .pdata must be sorted according to its BeginAddress field
-/// value. It's safe to do it because of the same reason as .sxdata.
-void PECOFFWriter::reorderSEHTableEntriesX64(uint8_t *bufferStart) {
- for (std::unique_ptr<Chunk> &chunk : _chunks) {
- if (SectionChunk *section = dyn_cast<SectionChunk>(chunk.get())) {
- if (section->getSectionName() != ".pdata")
- continue;
- int numEntries = section->size() / sizeof(coff_runtime_function_x64);
- coff_runtime_function_x64 *begin =
- (coff_runtime_function_x64 *)(bufferStart + section->fileOffset());
- coff_runtime_function_x64 *end = begin + numEntries;
- std::sort(begin, end, [](const coff_runtime_function_x64 &lhs,
- const coff_runtime_function_x64 &rhs) {
- return lhs.BeginAddress < rhs.BeginAddress;
- });
- }
- }
-}
-
-void PECOFFWriter::addChunk(Chunk *chunk) {
- _chunks.push_back(std::unique_ptr<Chunk>(chunk));
-}
-
-void PECOFFWriter::addSectionChunk(std::unique_ptr<SectionChunk> chunk,
- SectionHeaderTableChunk *table,
- StringTableChunk *stringTable) {
- table->addSection(chunk.get());
- _numSections++;
-
- StringRef sectionName = chunk->getSectionName();
- if (sectionName.size() > llvm::COFF::NameSize) {
- uint32_t stringTableOffset = stringTable->addSectionName(sectionName);
- chunk->setStringTableOffset(stringTableOffset);
- }
-
- // Compute and set the starting address of sections when loaded in
- // memory. They are different from positions on disk because sections need
- // to be sector-aligned on disk but page-aligned in memory.
- _imageSizeInMemory = llvm::RoundUpToAlignment(
- _imageSizeInMemory, chunk->memAlign());
- chunk->setVirtualAddress(_imageSizeInMemory);
- _imageSizeInMemory = llvm::RoundUpToAlignment(
- _imageSizeInMemory + chunk->size(), _ctx.getPageSize());
- _chunks.push_back(std::move(chunk));
-}
-
-void PECOFFWriter::setImageSizeOnDisk() {
- for (auto &chunk : _chunks) {
- // Compute and set the offset of the chunk in the output file.
- _imageSizeOnDisk =
- llvm::RoundUpToAlignment(_imageSizeOnDisk, chunk->align());
- chunk->setFileOffset(_imageSizeOnDisk);
- _imageSizeOnDisk += chunk->onDiskSize();
- }
-}
-
-uint64_t PECOFFWriter::calcSectionSize(
- llvm::COFF::SectionCharacteristics sectionType) const {
- uint64_t ret = 0;
- for (auto &cp : _chunks)
- if (SectionChunk *chunk = dyn_cast<SectionChunk>(&*cp))
- if (chunk->getCharacteristics() & sectionType)
- ret += chunk->onDiskSize();
- return ret;
-}
-
-} // end namespace pecoff
-
-std::unique_ptr<Writer> createWriterPECOFF(const PECOFFLinkingContext &info) {
- return std::unique_ptr<Writer>(new pecoff::PECOFFWriter(info));
-}
-
-} // end namespace lld
diff --git a/lib/ReaderWriter/YAML/Makefile b/lib/ReaderWriter/YAML/Makefile
deleted file mode 100644
index 739b6eae747a..000000000000
--- a/lib/ReaderWriter/YAML/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-##===- lld/lib/ReaderWriter/YAML/Makefile --------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL := ../../..
-LIBRARYNAME := lldYAML
-USEDLIBS = lldCore.a
-
-include $(LLD_LEVEL)/Makefile
diff --git a/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp b/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
index 868b9497c4cc..78c6797b713f 100644
--- a/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
+++ b/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp
@@ -25,6 +25,7 @@
#include "llvm/Support/ErrorHandling.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 <memory>
@@ -214,30 +215,14 @@ private:
NameToAtom _groupMap;
};
-// Used in NormalizedFile to hold the atoms lists.
-template <typename T> class AtomList : public lld::File::atom_collection<T> {
+/// Mapping of Atoms.
+template <typename T> class AtomList {
+ typedef lld::File::AtomVector<T> Ty;
+
public:
- virtual lld::File::atom_iterator<T> begin() const {
- return lld::File::atom_iterator<T>(
- *this,
- _atoms.empty() ? 0 : reinterpret_cast<const void *>(_atoms.data()));
- }
- virtual lld::File::atom_iterator<T> end() const {
- return lld::File::atom_iterator<T>(
- *this, _atoms.empty() ? 0 : reinterpret_cast<const void *>(
- _atoms.data() + _atoms.size()));
- }
- virtual const T *deref(const void *it) const {
- return *reinterpret_cast<const T *const *>(it);
- }
- virtual void next(const void *&it) const {
- const T *const *p = reinterpret_cast<const T *const *>(it);
- ++p;
- it = reinterpret_cast<const void *>(p);
- }
- virtual void push_back(const T *element) { _atoms.push_back(element); }
- virtual uint64_t size() const { return _atoms.size(); }
- std::vector<const T *> _atoms;
+ typename Ty::iterator begin() { return _atoms.begin(); }
+ typename Ty::iterator end() { return _atoms.end(); }
+ Ty _atoms;
};
/// Mapping of kind: field in yaml files.
@@ -270,7 +255,7 @@ struct RefKind {
Reference::KindValue value;
};
-} // namespace anon
+} // anonymous namespace
LLVM_YAML_IS_SEQUENCE_VECTOR(ArchMember)
LLVM_YAML_IS_SEQUENCE_VECTOR(const lld::Reference *)
@@ -377,6 +362,9 @@ template <> struct ScalarEnumerationTraits<lld::DefinedAtom::CodeModel> {
io.enumCase(value, "mips-micro-pic", lld::DefinedAtom::codeMipsMicroPIC);
io.enumCase(value, "mips-16", lld::DefinedAtom::codeMips16);
io.enumCase(value, "arm-thumb", lld::DefinedAtom::codeARMThumb);
+ io.enumCase(value, "arm-a", lld::DefinedAtom::codeARM_a);
+ io.enumCase(value, "arm-d", lld::DefinedAtom::codeARM_d);
+ io.enumCase(value, "arm-t", lld::DefinedAtom::codeARM_t);
}
};
@@ -449,6 +437,7 @@ template <> struct ScalarEnumerationTraits<lld::DefinedAtom::ContentType> {
io.enumCase(value, "no-alloc", DefinedAtom::typeNoAlloc);
io.enumCase(value, "group-comdat", DefinedAtom::typeGroupComdat);
io.enumCase(value, "gnu-linkonce", DefinedAtom::typeGnuLinkOnce);
+ io.enumCase(value, "sectcreate", DefinedAtom::typeSectCreate);
}
};
@@ -478,15 +467,15 @@ struct ScalarEnumerationTraits<lld::SharedLibraryAtom::Type> {
/// This is a custom formatter for lld::DefinedAtom::Alignment. Values look
/// like:
-/// 2^3 # 8-byte aligned
-/// 7 mod 2^4 # 16-byte aligned plus 7 bytes
+/// 8 # 8-byte aligned
+/// 7 mod 16 # 16-byte aligned plus 7 bytes
template <> struct ScalarTraits<lld::DefinedAtom::Alignment> {
static void output(const lld::DefinedAtom::Alignment &value, void *ctxt,
raw_ostream &out) {
if (value.modulus == 0) {
- out << llvm::format("2^%d", value.powerOf2);
+ out << llvm::format("%d", value.value);
} else {
- out << llvm::format("%d mod 2^%d", value.modulus, value.powerOf2);
+ out << llvm::format("%d mod %d", value.modulus, value.value);
}
}
@@ -505,16 +494,12 @@ template <> struct ScalarTraits<lld::DefinedAtom::Alignment> {
scalar = scalar.drop_front(modStart + 3);
scalar = scalar.ltrim();
}
- if (!scalar.startswith("2^")) {
- return "malformed alignment";
- }
- StringRef powerStr = scalar.drop_front(2);
unsigned int power;
- if (powerStr.getAsInteger(0, power)) {
+ if (scalar.getAsInteger(0, power)) {
return "malformed alignment power";
}
- value.powerOf2 = power;
- if (value.modulus > (1 << value.powerOf2)) {
+ value.value = power;
+ if (value.modulus >= power) {
return "malformed alignment, modulus too large for power";
}
return StringRef(); // returning empty string means success
@@ -598,19 +583,23 @@ template <> struct MappingTraits<const lld::File *> {
const lld::File *denormalize(IO &io) { return this; }
- const atom_collection<lld::DefinedAtom> &defined() const override {
+ const AtomVector<lld::DefinedAtom> &defined() const override {
return _noDefinedAtoms;
}
- const atom_collection<lld::UndefinedAtom> &undefined() const override {
+
+ const AtomVector<lld::UndefinedAtom> &undefined() const override {
return _noUndefinedAtoms;
}
- virtual const atom_collection<lld::SharedLibraryAtom> &
+
+ const AtomVector<lld::SharedLibraryAtom> &
sharedLibrary() const override {
return _noSharedLibraryAtoms;
}
- const atom_collection<lld::AbsoluteAtom> &absolute() const override {
+
+ const AtomVector<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()) {
@@ -630,7 +619,7 @@ template <> struct MappingTraits<const lld::File *> {
return nullptr;
}
- virtual std::error_code
+ std::error_code
parseAllMembers(std::vector<std::unique_ptr<File>> &result) override {
return std::error_code();
}
@@ -646,28 +635,31 @@ template <> struct MappingTraits<const lld::File *> {
: File(file->path(), kindObject), _io(io),
_rnb(new RefNameBuilder(*file)), _path(file->path()) {
for (const lld::DefinedAtom *a : file->defined())
- _definedAtoms.push_back(a);
+ _definedAtoms._atoms.push_back(a);
for (const lld::UndefinedAtom *a : file->undefined())
- _undefinedAtoms.push_back(a);
+ _undefinedAtoms._atoms.push_back(a);
for (const lld::SharedLibraryAtom *a : file->sharedLibrary())
- _sharedLibraryAtoms.push_back(a);
+ _sharedLibraryAtoms._atoms.push_back(a);
for (const lld::AbsoluteAtom *a : file->absolute())
- _absoluteAtoms.push_back(a);
+ _absoluteAtoms._atoms.push_back(a);
}
const lld::File *denormalize(IO &io);
- const atom_collection<lld::DefinedAtom> &defined() const override {
- return _definedAtoms;
+ const AtomVector<lld::DefinedAtom> &defined() const override {
+ return _definedAtoms._atoms;
}
- const atom_collection<lld::UndefinedAtom> &undefined() const override {
- return _undefinedAtoms;
+
+ const AtomVector<lld::UndefinedAtom> &undefined() const override {
+ return _undefinedAtoms._atoms;
}
- virtual const atom_collection<lld::SharedLibraryAtom> &
+
+ const AtomVector<lld::SharedLibraryAtom> &
sharedLibrary() const override {
- return _sharedLibraryAtoms;
+ return _sharedLibraryAtoms._atoms;
}
- const atom_collection<lld::AbsoluteAtom> &absolute() const override {
- return _absoluteAtoms;
+
+ const AtomVector<lld::AbsoluteAtom> &absolute() const override {
+ return _absoluteAtoms._atoms;
}
// Allocate a new copy of this string in _storage, so the strings
@@ -795,7 +787,7 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
public:
NormalizedAtom(IO &io)
: _file(fileFromContext(io)), _name(), _refName(), _contentType(),
- _alignment(0), _content(), _references(), _isGroupChild(false) {
+ _alignment(1), _content(), _references(), _isGroupChild(false) {
static uint32_t ordinalCounter = 1;
_ordinal = ordinalCounter++;
}
@@ -941,7 +933,7 @@ template <> struct MappingTraits<const lld::DefinedAtom *> {
DefinedAtom::interposeNo);
io.mapOptional("merge", keys->_merge, DefinedAtom::mergeNo);
io.mapOptional("alignment", keys->_alignment,
- DefinedAtom::Alignment(0));
+ DefinedAtom::Alignment(1));
io.mapOptional("section-choice", keys->_sectionChoice,
DefinedAtom::sectionBasedOnContent);
io.mapOptional("section-name", keys->_sectionName, StringRef());
@@ -1246,7 +1238,7 @@ namespace yaml {
class Writer : public lld::Writer {
public:
- Writer(const LinkingContext &context) : _context(context) {}
+ Writer(const LinkingContext &context) : _ctx(context) {}
std::error_code writeFile(const lld::File &file, StringRef outPath) override {
// Create stream to path.
@@ -1257,8 +1249,8 @@ public:
// Create yaml Output writer, using yaml options for context.
YamlContext yamlContext;
- yamlContext._linkingContext = &_context;
- yamlContext._registry = &_context.registry();
+ yamlContext._ctx = &_ctx;
+ yamlContext._registry = &_ctx.registry();
llvm::yaml::Output yout(out, &yamlContext);
// Write yaml output.
@@ -1269,7 +1261,7 @@ public:
}
private:
- const LinkingContext &_context;
+ const LinkingContext &_ctx;
};
} // end namespace yaml
@@ -1287,7 +1279,6 @@ class NativeYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
}
};
-
/// Handles !archive tagged yaml documents.
class ArchiveYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
bool handledDocTag(llvm::yaml::IO &io, const lld::File *&file) const override {
@@ -1299,19 +1290,18 @@ class ArchiveYamlIOTaggedDocumentHandler : public YamlIOTaggedDocumentHandler {
}
};
-
-
class YAMLReader : public Reader {
public:
YAMLReader(const Registry &registry) : _registry(registry) {}
- bool canParse(file_magic, StringRef ext, const MemoryBuffer &) const override {
- return (ext.equals(".objtxt") || ext.equals(".yaml"));
+ bool canParse(file_magic magic, MemoryBufferRef mb) const override {
+ StringRef name = mb.getBufferIdentifier();
+ return name.endswith(".objtxt") || name.endswith(".yaml");
}
- std::error_code
- loadFile(std::unique_ptr<MemoryBuffer> mb, const class Registry &,
- std::vector<std::unique_ptr<File>> &result) const override {
+ ErrorOr<std::unique_ptr<File>>
+ loadFile(std::unique_ptr<MemoryBuffer> mb,
+ const class Registry &) const override {
// Create YAML Input Reader.
YamlContext yamlContext;
yamlContext._registry = &_registry;
@@ -1321,20 +1311,19 @@ public:
// Fill vector with File objects created by parsing yaml.
std::vector<const lld::File *> createdFiles;
yin >> createdFiles;
+ assert(createdFiles.size() == 1);
// Error out now if there were parsing errors.
if (yin.error())
return make_error_code(lld::YamlReaderError::illegal_value);
std::shared_ptr<MemoryBuffer> smb(mb.release());
- for (const File *file : createdFiles) {
- // Note: loadFile() should return vector of *const* File
- File *f = const_cast<File *>(file);
- f->setLastError(std::error_code());
- f->setSharedMemoryBuffer(smb);
- result.emplace_back(f);
- }
- return make_error_code(lld::YamlReaderError::success);
+ const File *file = createdFiles[0];
+ // Note: loadFile() should return vector of *const* File
+ File *f = const_cast<File *>(file);
+ f->setLastError(std::error_code());
+ f->setSharedMemoryBuffer(smb);
+ return std::unique_ptr<File>(f);
}
private:
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index e29f5f4c5a90..b92489e2cc8d 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -20,9 +20,9 @@ configure_lit_site_cfg(
)
set(LLD_TEST_DEPS
- FileCheck not llvm-nm
+ FileCheck not llvm-ar llvm-as llvm-nm llc
lld llvm-config llvm-objdump llvm-readobj yaml2obj obj2yaml
- linker-script-test macho-dump llvm-mc llvm-nm
+ linker-script-test 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
new file mode 100644
index 000000000000..33b2c886b860
--- /dev/null
+++ b/test/COFF/Inputs/armnt-executable.obj.yaml
@@ -0,0 +1,29 @@
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_ARMNT
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: '7047'
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 2
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 1
+ - Name: mainCRTStartup
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/Inputs/armnt-executable.s b/test/COFF/Inputs/armnt-executable.s
new file mode 100644
index 000000000000..7e1a8ce82120
--- /dev/null
+++ b/test/COFF/Inputs/armnt-executable.s
@@ -0,0 +1,13 @@
+# void mainCRTStartup() {}
+ .syntax unified
+ .thumb
+ .text
+ .def mainCRTStartup
+ .scl 2
+ .type 32
+ .endef
+ .global mainCRTStartup
+ .align 2
+ .thumb_func
+mainCRTStartup:
+ bx lr
diff --git a/test/COFF/Inputs/conflict.ll b/test/COFF/Inputs/conflict.ll
new file mode 100644
index 000000000000..8cd7d706e5fb
--- /dev/null
+++ b/test/COFF/Inputs/conflict.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+define void @foo() {
+ ret void
+}
diff --git a/test/COFF/Inputs/entry-mangled.ll b/test/COFF/Inputs/entry-mangled.ll
new file mode 100644
index 000000000000..b6fac214dfc1
--- /dev/null
+++ b/test/COFF/Inputs/entry-mangled.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc18.0.0"
+
+define void @"\01?main@@YAHXZ"() {
+ ret void
+}
diff --git a/test/COFF/Inputs/export.ll b/test/COFF/Inputs/export.ll
new file mode 100644
index 000000000000..d254683cdd6f
--- /dev/null
+++ b/test/COFF/Inputs/export.ll
@@ -0,0 +1,18 @@
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+define void @_DllMainCRTStartup() {
+ ret void
+}
+
+define void @exportfn1() {
+ ret void
+}
+
+define void @exportfn2() {
+ ret void
+}
+
+define dllexport void @exportfn3() {
+ ret void
+}
diff --git a/test/COFF/Inputs/export.yaml b/test/COFF/Inputs/export.yaml
new file mode 100644
index 000000000000..25b57288a1bf
--- /dev/null
+++ b/test/COFF/Inputs/export.yaml
@@ -0,0 +1,57 @@
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B800000000506800000000680000000050E80000000050E800000000
+ - Name: .drectve
+ Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 2147483648
+ SectionData: 2f6578706f72743a6578706f7274666e3300 # /export:exportfn3
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 28
+ NumberOfRelocations: 4
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: _DllMainCRTStartup
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: exportfn1
+ Value: 8
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: exportfn2
+ Value: 16
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: exportfn3
+ Value: 16
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '?mangled@@YAHXZ'
+ Value: 16
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/Inputs/export2.yaml b/test/COFF/Inputs/export2.yaml
new file mode 100644
index 000000000000..592b76526ffa
--- /dev/null
+++ b/test/COFF/Inputs/export2.yaml
@@ -0,0 +1,29 @@
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B800000000506800000000680000000050E80000000050E800000000
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 28
+ NumberOfRelocations: 4
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: '?mangled2@@YAHXZ'
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/Inputs/hello32.yaml b/test/COFF/Inputs/hello32.yaml
new file mode 100644
index 000000000000..ea5a5c84c4f1
--- /dev/null
+++ b/test/COFF/Inputs/hello32.yaml
@@ -0,0 +1,82 @@
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_I386
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 33DB538D0500000000508D05000000005053E80000000050E800000000
+ Relocations:
+ - VirtualAddress: 5
+ SymbolName: caption
+ Type: IMAGE_REL_I386_DIR32
+ - VirtualAddress: 12
+ SymbolName: message
+ Type: IMAGE_REL_I386_DIR32
+ - VirtualAddress: 19
+ SymbolName: '_MessageBoxA@16'
+ Type: IMAGE_REL_I386_REL32
+ - VirtualAddress: 25
+ SymbolName: '_ExitProcess@4'
+ Type: IMAGE_REL_I386_REL32
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 16
+ SectionData: 48656C6C6F0048656C6C6F20576F726C642100
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 29
+ NumberOfRelocations: 4
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: .data
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 19
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: '_ExitProcess@4'
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '_MessageBoxA@16'
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: message
+ Value: 6
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: caption
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: '_main@0'
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/Inputs/hello64.asm b/test/COFF/Inputs/hello64.asm
new file mode 100644
index 000000000000..6605213224bc
--- /dev/null
+++ b/test/COFF/Inputs/hello64.asm
@@ -0,0 +1,24 @@
+;; ml64 hello64.asm /link /subsystem:windows /defaultlib:kernel32 \
+;; /defaultlib:user32 /out:hello64.exe /entry:main
+
+extern ExitProcess : PROC
+extern MessageBoxA : PROC
+extern ImportByOrdinal: PROC
+
+.data
+ caption db 'Hello', 0
+ message db 'Hello World!', 0
+
+.code
+main PROC
+ sub rsp,28h
+ mov rcx, 0
+ lea rdx, message
+ lea r8, caption
+ mov r9d, 0
+ call MessageBoxA
+ mov ecx, 0
+ call ExitProcess
+ call ImportByOrdinal
+main ENDP
+END
diff --git a/test/COFF/Inputs/hello64.obj b/test/COFF/Inputs/hello64.obj
new file mode 100644
index 000000000000..90c1ce4aa4cf
--- /dev/null
+++ b/test/COFF/Inputs/hello64.obj
Binary files differ
diff --git a/test/COFF/Inputs/import.yaml b/test/COFF/Inputs/import.yaml
new file mode 100644
index 000000000000..2c5fdc545b48
--- /dev/null
+++ b/test/COFF/Inputs/import.yaml
@@ -0,0 +1,41 @@
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ 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_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: exportfn1
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: exportfn2
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/Inputs/imports-mangle.lib b/test/COFF/Inputs/imports-mangle.lib
new file mode 100644
index 000000000000..f3c722ad0746
--- /dev/null
+++ b/test/COFF/Inputs/imports-mangle.lib
Binary files differ
diff --git a/test/COFF/Inputs/include1a.yaml b/test/COFF/Inputs/include1a.yaml
new file mode 100644
index 000000000000..7fca9833cb7b
--- /dev/null
+++ b/test/COFF/Inputs/include1a.yaml
@@ -0,0 +1,33 @@
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B800000000506800000000680000000050E80000000050E800000000
+ - Name: .drectve
+ Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 2147483648
+ SectionData: 2f696e636c7564653a666f6f00 # /include:foo
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 28
+ NumberOfRelocations: 4
+ 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
+...
diff --git a/test/COFF/Inputs/include1b.yaml b/test/COFF/Inputs/include1b.yaml
new file mode 100644
index 000000000000..e4151be27cc3
--- /dev/null
+++ b/test/COFF/Inputs/include1b.yaml
@@ -0,0 +1,33 @@
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B800000000506800000000680000000050E80000000050E800000000
+ - Name: .drectve
+ Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 2147483648
+ SectionData: 2f696e636c7564653a62617200 # /include:bar
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 28
+ NumberOfRelocations: 4
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: foo
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/Inputs/include1c.yaml b/test/COFF/Inputs/include1c.yaml
new file mode 100644
index 000000000000..78dd29659e22
--- /dev/null
+++ b/test/COFF/Inputs/include1c.yaml
@@ -0,0 +1,29 @@
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B800000000506800000000680000000050E80000000050E800000000
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 28
+ NumberOfRelocations: 4
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: bar
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/pecoff/Inputs/library.lib b/test/COFF/Inputs/library.lib
index 2f4207d7983d..2f4207d7983d 100755
--- a/test/pecoff/Inputs/library.lib
+++ b/test/COFF/Inputs/library.lib
Binary files differ
diff --git a/test/COFF/Inputs/lto-chkstk-chkstk.s b/test/COFF/Inputs/lto-chkstk-chkstk.s
new file mode 100644
index 000000000000..292b30d5ffab
--- /dev/null
+++ b/test/COFF/Inputs/lto-chkstk-chkstk.s
@@ -0,0 +1,3 @@
+.globl __chkstk
+__chkstk:
+ret
diff --git a/test/COFF/Inputs/lto-chkstk-foo.s b/test/COFF/Inputs/lto-chkstk-foo.s
new file mode 100644
index 000000000000..a69f870a1b60
--- /dev/null
+++ b/test/COFF/Inputs/lto-chkstk-foo.s
@@ -0,0 +1,3 @@
+.globl foo
+foo:
+ret
diff --git a/test/COFF/Inputs/lto-comdat1.ll b/test/COFF/Inputs/lto-comdat1.ll
new file mode 100644
index 000000000000..7a9f50c0f9db
--- /dev/null
+++ b/test/COFF/Inputs/lto-comdat1.ll
@@ -0,0 +1,13 @@
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+$comdat = comdat any
+
+define void @f1() {
+ call void @comdat()
+ ret void
+}
+
+define linkonce_odr void @comdat() comdat {
+ ret void
+}
diff --git a/test/COFF/Inputs/lto-comdat2.ll b/test/COFF/Inputs/lto-comdat2.ll
new file mode 100644
index 000000000000..c2af2a4de597
--- /dev/null
+++ b/test/COFF/Inputs/lto-comdat2.ll
@@ -0,0 +1,13 @@
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+$comdat = comdat any
+
+define void @f2() {
+ call void @comdat()
+ ret void
+}
+
+define linkonce_odr void @comdat() comdat {
+ ret void
+}
diff --git a/test/COFF/Inputs/lto-dep.ll b/test/COFF/Inputs/lto-dep.ll
new file mode 100644
index 000000000000..d6d47f234917
--- /dev/null
+++ b/test/COFF/Inputs/lto-dep.ll
@@ -0,0 +1,10 @@
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+define void @foo() {
+ ret void
+}
+
+define internal void @internal() {
+ ret void
+}
diff --git a/test/COFF/Inputs/machine-x64.yaml b/test/COFF/Inputs/machine-x64.yaml
new file mode 100644
index 000000000000..d70e0808a2e1
--- /dev/null
+++ b/test/COFF/Inputs/machine-x64.yaml
@@ -0,0 +1,29 @@
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 000000000000
+symbols:
+ - Name: .text
+ 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_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/Inputs/machine-x86.yaml b/test/COFF/Inputs/machine-x86.yaml
new file mode 100644
index 000000000000..6b6cfae09c57
--- /dev/null
+++ b/test/COFF/Inputs/machine-x86.yaml
@@ -0,0 +1,29 @@
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_I386
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 000000000000
+symbols:
+ - Name: .text
+ 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_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/pecoff/Inputs/resource.res b/test/COFF/Inputs/resource.res
index f1c799fbbb08..f1c799fbbb08 100755..100644
--- a/test/pecoff/Inputs/resource.res
+++ b/test/COFF/Inputs/resource.res
Binary files differ
diff --git a/test/COFF/Inputs/ret42.lib b/test/COFF/Inputs/ret42.lib
new file mode 100644
index 000000000000..f60a9cdf6f90
--- /dev/null
+++ b/test/COFF/Inputs/ret42.lib
Binary files differ
diff --git a/test/COFF/Inputs/ret42.obj b/test/COFF/Inputs/ret42.obj
new file mode 100644
index 000000000000..1765f0e7c36e
--- /dev/null
+++ b/test/COFF/Inputs/ret42.obj
Binary files differ
diff --git a/test/COFF/Inputs/ret42.yaml b/test/COFF/Inputs/ret42.yaml
new file mode 100644
index 000000000000..2b38cc7f0d6b
--- /dev/null
+++ b/test/COFF/Inputs/ret42.yaml
@@ -0,0 +1,45 @@
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: '.text$mn'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: B82A000000C3
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 16
+ SectionData: ''
+symbols:
+ - Name: '.text$mn'
+ 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: .data
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 0
+ 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/Inputs/std32.lib b/test/COFF/Inputs/std32.lib
new file mode 100644
index 000000000000..7401ff3faf9e
--- /dev/null
+++ b/test/COFF/Inputs/std32.lib
Binary files differ
diff --git a/test/COFF/Inputs/std64.lib b/test/COFF/Inputs/std64.lib
new file mode 100644
index 000000000000..bbd223c59f40
--- /dev/null
+++ b/test/COFF/Inputs/std64.lib
Binary files differ
diff --git a/test/COFF/Inputs/weak-external.ll b/test/COFF/Inputs/weak-external.ll
new file mode 100644
index 000000000000..4775d50456c9
--- /dev/null
+++ b/test/COFF/Inputs/weak-external.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+define void @g() {
+ ret void
+}
diff --git a/test/COFF/Inputs/weak-external2.ll b/test/COFF/Inputs/weak-external2.ll
new file mode 100644
index 000000000000..2102c3b6a526
--- /dev/null
+++ b/test/COFF/Inputs/weak-external2.ll
@@ -0,0 +1,6 @@
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+define void @f() {
+ ret void
+}
diff --git a/test/COFF/Inputs/weak-external3.ll b/test/COFF/Inputs/weak-external3.ll
new file mode 100644
index 000000000000..f9a51360a89d
--- /dev/null
+++ b/test/COFF/Inputs/weak-external3.ll
@@ -0,0 +1,8 @@
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+@f = weak alias void(), void()* @g
+
+define void @g() {
+ ret void
+}
diff --git a/test/COFF/alternatename.test b/test/COFF/alternatename.test
new file mode 100644
index 000000000000..5b9dc470af16
--- /dev/null
+++ b/test/COFF/alternatename.test
@@ -0,0 +1,61 @@
+# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
+# RUN: lld-link /entry:foo /subsystem:console \
+# RUN: /alternatename:foo=main /out:%t.exe %t.obj
+# RUN: lld-link /entry:foo /subsystem:console \
+# RUN: /alternatename:foo=main \
+# RUN: /alternatename:foo=main \
+# RUN: /alternatename:nosuchsym1=nosuchsym2 \
+# RUN: /out:%t.exe %t.obj
+
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /entry:foo /subsystem:console /out:%t.exe %t.obj
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: '.text$mn'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: B82A000000C3
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 16
+ SectionData: ''
+ - Name: .drectve
+ Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 2147483648
+ SectionData: 2f616c7465726e6174656e616d653a666f6f3d6d61696e00 # /alternatename:foo=main
+symbols:
+ - Name: '.text$mn'
+ 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: .data
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 0
+ 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/ar-comdat.test b/test/COFF/ar-comdat.test
new file mode 100644
index 000000000000..af7d732ea3c0
--- /dev/null
+++ b/test/COFF/ar-comdat.test
@@ -0,0 +1,38 @@
+# RUN: yaml2obj %s > %t1.obj
+# RUN: yaml2obj %s > %t2.obj
+# RUN: llvm-lib /out:%t.lib %t1.obj %t2.obj
+# RUN: lld-link /out:%t.exe /lldmap:%t.map /entry:main /subsystem:console %p/Inputs/ret42.obj %t.lib
+# RUN: FileCheck %s < %t.map
+
+# CHECK-NOT: .lib
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: .bss
+ Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: ''
+symbols:
+ - Name: .bss
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 4
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 1
+ Selection: IMAGE_COMDAT_SELECT_ANY
+ - Name: x
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/armnt-blx23t.test b/test/COFF/armnt-blx23t.test
new file mode 100644
index 000000000000..fdc2bf51afb3
--- /dev/null
+++ b/test/COFF/armnt-blx23t.test
@@ -0,0 +1,66 @@
+# REQUIRES: arm
+
+# RUN: yaml2obj < %s > %t.obj
+# RUN: llvm-objdump -d %t.obj | FileCheck %s -check-prefix BEFORE
+# RUN: lld-link /entry:function /subsystem:console /out:%t.exe %t.obj
+# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER
+
+# BEFORE: Disassembly of section .text:
+# BEFORE: 0: 70 47 bx lr
+# BEFORE: 2: 00 bf nop
+# BEFORE: 4: 2d e9 00 48 push.w {r11, lr}
+# BEFORE: 8: eb 46 mov r11, sp
+# BEFORE: a: 20 20 movs r0, #32
+# BEFORE: c: 00 f0 00 f8 bl #0
+# BEFORE: 10: 01 30 adds r0, #1
+# BEFORE: 12: bd e8 00 88 pop.w {r11, pc}
+
+# AFTER: Disassembly of section .text:
+# AFTER: 1000: 70 47 bx lr
+# AFTER: 1002: 00 bf nop
+# AFTER: 1004: 2d e9 00 48 push.w {r11, lr}
+# AFTER: 1008: eb 46 mov r11, sp
+# AFTER: 100a: 20 20 movs r0, #32
+# AFTER: 100c: ff f7 f8 ff bl #-16
+# AFTER: 1010: 01 30 adds r0, #1
+# AFTER: 1012: bd e8 00 88 pop.w {r11, pc}
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_ARMNT
+ Characteristics: [ ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 704700BF2DE90048EB46202000F000F80130BDE80088
+ Relocations:
+ - VirtualAddress: 12
+ SymbolName: identity
+ Type: 21
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 22
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 1
+ - Name: identity
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: function
+ Value: 4
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/armnt-branch24t.test b/test/COFF/armnt-branch24t.test
new file mode 100644
index 000000000000..358b603303b3
--- /dev/null
+++ b/test/COFF/armnt-branch24t.test
@@ -0,0 +1,59 @@
+# REQUIRES: arm
+
+# RUN: yaml2obj < %s > %t.obj
+# RUN: llvm-objdump -d %t.obj | FileCheck %s -check-prefix BEFORE
+# RUN: lld-link /entry:function /subsystem:console /out:%t.exe %t.obj
+# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER
+
+# BEFORE: Disassembly of section .text:
+# BEFORE: 0: 70 47 bx lr
+# BEFORE: 2: 00 bf nop
+# BEFORE: 4: 20 20 movs r0, #32
+# BEFORE: 6: 00 f0 00 b8 b.w #0
+
+# AFTER: Disassembly of section .text:
+# AFTER: .text:
+# AFTER: 1000: 70 47 bx lr
+# AFTER: 1002: 00 bf nop
+# AFTER: 1004: 20 20 movs r0, #32
+# AFTER: 1006: ff f7 fb bf b.w #-10
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_ARMNT
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 704700BF202000F000B8
+ Relocations:
+ - VirtualAddress: 6
+ SymbolName: identity
+ Type: 20
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 10
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 1
+ - Name: identity
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: function
+ Value: 4
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/armnt-entry-point.test b/test/COFF/armnt-entry-point.test
new file mode 100644
index 000000000000..7b1bd100e083
--- /dev/null
+++ b/test/COFF/armnt-entry-point.test
@@ -0,0 +1,5 @@
+# RUN: yaml2obj < %p/Inputs/armnt-executable.obj.yaml > %t.obj
+# RUN: lld-link /out:%t.exe /entry:mainCRTStartup /subsystem:console %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
+
+CHECK: AddressOfEntryPoint: 0x1001
diff --git a/test/COFF/armnt-imports.test b/test/COFF/armnt-imports.test
new file mode 100644
index 000000000000..3842259a7a72
--- /dev/null
+++ b/test/COFF/armnt-imports.test
@@ -0,0 +1,51 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /out:%t.exe /subsystem:console %t.obj \
+# RUN: /entry:mainCRTStartup %p/Inputs/library.lib
+# RUN: llvm-readobj -coff-imports %t.exe | FileCheck %s
+
+# CHECK: Import {
+# CHECK: Name: library.dll
+# CHECK: ImportLookupTableRVA: 0x2028
+# CHECK: ImportAddressTableRVA: 0x2030
+# CHECK: Symbol: function (0)
+# CHECK: }
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_ARMNT
+ Characteristics: [ ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 40F20000C0F2000000680047
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: __imp_function
+ Type: 17
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 12
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 1
+ - Name: mainCRTStartup
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __imp_function
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/armnt-mov32t-exec.test b/test/COFF/armnt-mov32t-exec.test
new file mode 100644
index 000000000000..7fa9952e9547
--- /dev/null
+++ b/test/COFF/armnt-mov32t-exec.test
@@ -0,0 +1,60 @@
+# REQUIRES: arm
+
+# RUN: yaml2obj < %s > %t.obj
+# RUN: llvm-objdump -d %t.obj | FileCheck %s -check-prefix BEFORE
+# RUN: lld-link /out:%t.exe /subsystem:console /entry:get_function %t.obj
+# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER
+
+# BEFORE: Disassembly of section .text:
+# BEFORE: 0: 70 47 bx lr
+# BEFORE: 2: 00 bf nop
+# BEFORE: 4: 40 f2 00 00 movw r0, #0
+# BEFORE: 8: c0 f2 00 00 movt r0, #0
+# BEFORE: c: 70 47 bx lr
+
+# AFTER: Disassembly of section .text:
+# AFTER: 1000: 70 47 bx lr
+# AFTER: 1002: 00 bf nop
+# AFTER: 1004: 41 f2 01 00 movw r0, #4097
+# AFTER: 1008: c0 f2 40 00 movt r0, #64
+# AFTER: 100c: 70 47 bx lr
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_ARMNT
+ Characteristics: [ ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 704700BF40F20000C0F200007047
+ Relocations:
+ - VirtualAddress: 4
+ SymbolName: function
+ Type: 17
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 14
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 1
+ - Name: function
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: get_function
+ Value: 4
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/armnt-movt32t.test b/test/COFF/armnt-movt32t.test
new file mode 100644
index 000000000000..be292cb39300
--- /dev/null
+++ b/test/COFF/armnt-movt32t.test
@@ -0,0 +1,72 @@
+# REQUIRES: arm
+
+# RUN: yaml2obj < %s > %t.obj
+# RUN: llvm-objdump -d %t.obj | FileCheck %s -check-prefix BEFORE
+# RUN: lld-link /entry:get_buffer /subsystem:console /out:%t.exe %t.obj
+# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER
+
+# BEFORE: Disassembly of section .text:
+# BEFORE: 0: 40 f2 00 00 movw r0, #0
+# BEFORE: 4: c0 f2 00 00 movt r0, #0
+# BEFORE: 8: 70 47 bx lr
+
+# AFTER: Disassembly of section .text:
+# AFTER: 0: 41 f2 00 00 movw r0, #4096
+# AFTER: 4: c0 f2 40 00 movt r0, #64
+# AFTER: 8: 70 47 bx lr
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_ARMNT
+ Characteristics: [ ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 40F20000C0F200007047
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: buffer
+ Type: 17
+ - Name: .rdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 1
+ SectionData: '62756666657200'
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 10
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 1
+ - Name: .rdata
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 7
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 2
+ - Name: get_buffer
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: buffer
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+...
diff --git a/test/COFF/base.test b/test/COFF/base.test
new file mode 100644
index 000000000000..f03e321fc23a
--- /dev/null
+++ b/test/COFF/base.test
@@ -0,0 +1,57 @@
+# RUN: yaml2obj < %s > %t.obj
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=DEFAULT-HEADER %s
+# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=DEFAULT-TEXT %s
+
+# DEFAULT-HEADER: ImageBase: 0x140000000
+# DEFAULT-TEXT: Contents of section .text:
+# DEFAULT-TEXT-NEXT: 1000 00000040 01000000
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj /base:0x280000000
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=BASE-HEADER %s
+# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=BASE-TEXT %s
+
+# BASE-HEADER: ImageBase: 0x280000000
+# BASE-TEXT: Contents of section .text:
+# BASE-TEXT-NEXT: 1000 00000080 02000000
+
+---
+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
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: __ImageBase
+ Type: IMAGE_REL_AMD64_ADDR64
+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: 1
+ 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: __ImageBase
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/baserel.test b/test/COFF/baserel.test
new file mode 100644
index 000000000000..bac9c22cbc3d
--- /dev/null
+++ b/test/COFF/baserel.test
@@ -0,0 +1,215 @@
+# RUN: yaml2obj < %s > %t.obj
+#
+# RUN: lld-link /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib
+# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck %s -check-prefix=BASEREL
+#
+# RUN: lld-link /out:%t.exe /entry:main /fixed %t.obj %p/Inputs/std64.lib
+# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck %s -check-prefix=NOBASEREL
+#
+# BASEREL: BaseReloc [
+# BASEREL-NEXT: Entry {
+# BASEREL-NEXT: Type: DIR64
+# BASEREL-NEXT: Address: 0x2007
+# BASEREL-NEXT: }
+# BASEREL-NEXT: Entry {
+# BASEREL-NEXT: Type: DIR64
+# BASEREL-NEXT: Address: 0x200C
+# BASEREL-NEXT: }
+# BASEREL-NEXT: Entry {
+# BASEREL-NEXT: Type: DIR64
+# BASEREL-NEXT: Address: 0x201E
+# BASEREL-NEXT: }
+# BASEREL-NEXT: Entry {
+# BASEREL-NEXT: Type: ABSOLUTE
+# BASEREL-NEXT: Address: 0x2000
+# BASEREL-NEXT: }
+# BASEREL-NEXT: Entry {
+# BASEREL-NEXT: Type: DIR64
+# BASEREL-NEXT: Address: 0x3007
+# BASEREL-NEXT: }
+# BASEREL-NEXT: Entry {
+# BASEREL-NEXT: Type: DIR64
+# BASEREL-NEXT: Address: 0x300C
+# BASEREL-NEXT: }
+# BASEREL-NEXT: Entry {
+# BASEREL-NEXT: Type: DIR64
+# BASEREL-NEXT: Address: 0x301E
+# BASEREL-NEXT: }
+# BASEREL-NEXT: Entry {
+# BASEREL-NEXT: Type: ABSOLUTE
+# BASEREL-NEXT: Address: 0x3000
+# BASEREL-NEXT: }
+#
+# NOBASEREL: BaseReloc [
+# NOBASEREL-NEXT: ]
+#
+# RUN: lld-link /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib
+# RUN: llvm-readobj -file-headers -sections %t.exe | FileCheck %s \
+# RUN: --check-prefix=BASEREL-HEADER
+#
+# RN: lld-link /out:%t.exe /entry:main /fixed %t.obj %p/Inputs/std64.lib
+# RN: llvm-readobj -file-headers %t.exe | FileCheck %s \
+# RN: --check-prefix=NOBASEREL-HEADER
+#
+# BASEREL-HEADER-NOT: IMAGE_FILE_RELOCS_STRIPPED
+#
+# NOBASEREL-HEADER: IMAGE_FILE_RELOCS_STRIPPED
+#
+# BASEREL-HEADER: BaseRelocationTableRVA: 0x5000
+# BASEREL-HEADER: BaseRelocationTableSize: 0x20
+# BASEREL-HEADER: Name: .reloc (2E 72 65 6C 6F 63 00 00)
+# BASEREL-HEADER-NEXT: VirtualSize: 0x20
+# BASEREL-HEADER-NEXT: VirtualAddress: 0x5000
+# BASEREL-HEADER-NEXT: RawDataSize: 512
+# BASEREL-HEADER-NEXT: PointerToRawData: 0xC00
+# BASEREL-HEADER-NEXT: PointerToRelocations: 0x0
+# BASEREL-HEADER-NEXT: PointerToLineNumbers: 0x0
+# BASEREL-HEADER-NEXT: RelocationCount: 0
+# BASEREL-HEADER-NEXT: LineNumberCount: 0
+# BASEREL-HEADER-NEXT: Characteristics [ (0x42000040)
+# BASEREL-HEADER-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
+# BASEREL-HEADER-NEXT: IMAGE_SCN_MEM_DISCARDABLE (0x2000000)
+# BASEREL-HEADER-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
+# BASEREL-HEADER-NEXT: ]
+
+---
+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: B800000000000000005068000000000000000068000000000000000050E8000000000000000050E8000000000000000050E80000000000000000
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: abs_symbol
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 7
+ SymbolName: caption
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 12
+ SymbolName: message
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 18
+ SymbolName: MessageBoxA
+ Type: IMAGE_REL_AMD64_REL32
+ - VirtualAddress: 24
+ SymbolName: ExitProcess
+ Type: IMAGE_REL_AMD64_REL32
+ - VirtualAddress: 30
+ SymbolName: __ImageBase
+ Type: IMAGE_REL_AMD64_ADDR64
+ - Name: .text2
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4096
+ SectionData: B800000000000000005068000000000000000068000000000000000050E8000000000000000050E8000000000000000050E80000000000000000
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: abs_symbol
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 7
+ SymbolName: caption
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 12
+ SymbolName: message
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 18
+ SymbolName: MessageBoxA
+ Type: IMAGE_REL_AMD64_REL32
+ - VirtualAddress: 24
+ SymbolName: ExitProcess
+ Type: IMAGE_REL_AMD64_REL32
+ - VirtualAddress: 30
+ SymbolName: __ImageBase
+ Type: IMAGE_REL_AMD64_ADDR64
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: 48656C6C6F0048656C6C6F20576F726C6400
+symbols:
+ - Name: "@comp.id"
+ Value: 10394907
+ SectionNumber: 65535
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 28
+ NumberOfRelocations: 6
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: .text2
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 28
+ NumberOfRelocations: 6
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: .data
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 18
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: MessageBoxA
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: ExitProcess
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: message
+ Value: 6
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: main
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: caption
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: abs_symbol
+ Value: 0xDEADBEEF
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __ImageBase
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/common.test b/test/COFF/common.test
new file mode 100644
index 000000000000..de25848674ed
--- /dev/null
+++ b/test/COFF/common.test
@@ -0,0 +1,102 @@
+# RUN: yaml2obj %s > %t.obj
+# RUN: lld-link /out:%t.exe /entry:main %t.obj %t.obj
+# RUN: llvm-objdump -d %t.exe | FileCheck %s
+
+# Operands of B8 (MOV EAX) are common symbols
+# CHECK: 3000: b8 00 10 00 40
+# CHECK: 3005: b8 04 10 00 40
+# CHECK: 300a: b8 20 10 00 40
+# CHECK: 300f: b8 60 10 00 40
+# CHECK: 3014: b8 80 10 00 40
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: b800000000b800000000b800000000b800000000b800000000
+ Relocations:
+ - VirtualAddress: 1
+ SymbolName: bssdata4
+ Type: IMAGE_REL_AMD64_ADDR32
+ - VirtualAddress: 6
+ SymbolName: bsspad1
+ Type: IMAGE_REL_AMD64_ADDR32
+ - VirtualAddress: 11
+ SymbolName: bssdata64
+ Type: IMAGE_REL_AMD64_ADDR32
+ - VirtualAddress: 16
+ SymbolName: bsspad2
+ Type: IMAGE_REL_AMD64_ADDR32
+ - VirtualAddress: 21
+ SymbolName: bssdata16
+ Type: IMAGE_REL_AMD64_ADDR32
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: 03000000
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 0
+ NumberOfRelocations: 5
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: .data
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 4
+ 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
+ - Name: bssdata4
+ Value: 4
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: bsspad1
+ Value: 1
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: bssdata64
+ Value: 64
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: bsspad2
+ Value: 1
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: bssdata16
+ Value: 16
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/conflict.test b/test/COFF/conflict.test
new file mode 100644
index 000000000000..3d5725ab79ee
--- /dev/null
+++ b/test/COFF/conflict.test
@@ -0,0 +1,41 @@
+# RUN: yaml2obj < %s > %t1.obj
+# RUN: yaml2obj < %s > %t2.obj
+# RUN: not lld-link /out:%t.exe %t1.obj %t2.obj >& %t.log
+# RUN: FileCheck %s < %t.log
+
+# RUN: llvm-as -o %t.lto1.obj %S/Inputs/conflict.ll
+# RUN: llvm-as -o %t.lto2.obj %S/Inputs/conflict.ll
+# RUN: not lld-link /out:%t.exe %t.lto1.obj %t.lto2.obj >& %t.log
+# RUN: FileCheck %s < %t.log
+
+# CHECK: duplicate symbol: foo {{.+}}1.obj and foo {{.+}}2.obj
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 000000000000
+symbols:
+ - Name: .text
+ 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: foo
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/debug.test b/test/COFF/debug.test
new file mode 100644
index 000000000000..52e0f60fe3f5
--- /dev/null
+++ b/test/COFF/debug.test
@@ -0,0 +1,38 @@
+# RUN: yaml2obj %s > %t.obj
+# RUN: lld-link /out:%t.exe /entry:main /subsystem:console %t.obj
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B82A000000C3
+symbols:
+ - Name: .text
+ 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_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: debug
+ Value: 0
+ SectionNumber: -2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/defparser.test b/test/COFF/defparser.test
new file mode 100644
index 000000000000..2e5223a699df
--- /dev/null
+++ b/test/COFF/defparser.test
@@ -0,0 +1,13 @@
+# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
+
+# RUN: echo -e "LIBRARY foo\nEXPORTS ? @" > %t.def
+# RUN: not lld-link /def:%t.def %t.obj
+
+# RUN: echo -e "LIBRARY foo\nHEAP abc" > %t.def
+# RUN: not lld-link /def:%t.def %t.obj
+
+# RUN: echo -e "LIBRARY foo\nSTACK abc" > %t.def
+# RUN: not lld-link /def:%t.def %t.obj
+
+# RUN: echo -e "foo" > %t.def
+# RUN: not lld-link /def:%t.def %t.obj
diff --git a/test/COFF/delayimports.test b/test/COFF/delayimports.test
new file mode 100644
index 000000000000..2c27d58dc793
--- /dev/null
+++ b/test/COFF/delayimports.test
@@ -0,0 +1,41 @@
+# RUN: lld-link /out:%t.exe /entry:main /subsystem:console \
+# RUN: %p/Inputs/hello64.obj %p/Inputs/std64.lib /delayload:STD64.DLL \
+# RUN: /alternatename:__delayLoadHelper2=main
+# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s
+# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s
+
+IMPORT: DelayImport {
+IMPORT-NEXT: Name: std64.dll
+IMPORT-NEXT: Attributes: 0x1
+IMPORT-NEXT: ModuleHandle: 0x1018
+IMPORT-NEXT: ImportAddressTable: 0x1020
+IMPORT-NEXT: ImportNameTable: 0x3040
+IMPORT-NEXT: BoundDelayImportTable: 0x0
+IMPORT-NEXT: UnloadDelayImportTable: 0x0
+IMPORT-NEXT: Import {
+IMPORT-NEXT: Symbol: ExitProcess (0)
+IMPORT-NEXT: Address: 0x140002066
+IMPORT-NEXT: }
+IMPORT-NEXT: Import {
+IMPORT-NEXT: Symbol: (50)
+IMPORT-NEXT: Address: 0x1400020BD
+IMPORT-NEXT: }
+IMPORT-NEXT: Import {
+IMPORT-NEXT: Symbol: MessageBoxA (0)
+IMPORT-NEXT: Address: 0x140002114
+IMPORT-NEXT: }
+IMPORT-NEXT: }
+
+BASEREL: BaseReloc [
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: DIR64
+BASEREL-NEXT: Address: 0x1020
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: DIR64
+BASEREL-NEXT: Address: 0x1028
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: DIR64
+BASEREL-NEXT: Address: 0x1030
+BASEREL-NEXT: }
diff --git a/test/COFF/delayimports32.test b/test/COFF/delayimports32.test
new file mode 100644
index 000000000000..328b34504ac5
--- /dev/null
+++ b/test/COFF/delayimports32.test
@@ -0,0 +1,86 @@
+# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj
+# RUN: lld-link %t.obj %p/Inputs/std32.lib /subsystem:console \
+# RUN: /entry:main@0 /alternatename:___delayLoadHelper2@8=_main@0 \
+# RUN: /debug /delayload:std32.dll /out:%t.exe
+# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s
+# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s
+# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DISASM %s
+
+IMPORT: Format: COFF-i386
+IMPORT-NEXT: Arch: i386
+IMPORT-NEXT: AddressSize: 32bit
+IMPORT-NEXT: DelayImport {
+IMPORT-NEXT: Name: std32.dll
+IMPORT-NEXT: Attributes: 0x1
+IMPORT-NEXT: ModuleHandle: 0x1018
+IMPORT-NEXT: ImportAddressTable: 0x1020
+IMPORT-NEXT: ImportNameTable: 0x3040
+IMPORT-NEXT: BoundDelayImportTable: 0x0
+IMPORT-NEXT: UnloadDelayImportTable: 0x0
+IMPORT-NEXT: Import {
+IMPORT-NEXT: Symbol: ExitProcess (0)
+IMPORT-NEXT: Address: 0x402029
+IMPORT-NEXT: }
+IMPORT-NEXT: Import {
+IMPORT-NEXT: Symbol: MessageBoxA (0)
+IMPORT-NEXT: Address: 0x40203E
+IMPORT-NEXT: }
+IMPORT-NEXT: }
+
+BASEREL: BaseReloc [
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: HIGHLOW
+BASEREL-NEXT: Address: 0x1020
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: HIGHLOW
+BASEREL-NEXT: Address: 0x1024
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: HIGHLOW
+BASEREL-NEXT: Address: 0x2005
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: HIGHLOW
+BASEREL-NEXT: Address: 0x200C
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: HIGHLOW
+BASEREL-NEXT: Address: 0x201F
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: HIGHLOW
+BASEREL-NEXT: Address: 0x2025
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: HIGHLOW
+BASEREL-NEXT: Address: 0x202C
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: HIGHLOW
+BASEREL-NEXT: Address: 0x2031
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: HIGHLOW
+BASEREL-NEXT: Address: 0x2041
+BASEREL-NEXT: }
+BASEREL-NEXT: Entry {
+BASEREL-NEXT: Type: HIGHLOW
+BASEREL-NEXT: Address: 0x2046
+BASEREL-NEXT: }
+BASEREL-NEXT: ]
+
+DISASM: 202b: 68 20 10 40 00 pushl $4198432
+DISASM-NEXT: 2030: 68 00 30 40 00 pushl $4206592
+DISASM-NEXT: 2035: e8 c6 ff ff ff calll -58 <_main@0>
+DISASM-NEXT: 203a: 5a popl %edx
+DISASM-NEXT: 203b: 59 popl %ecx
+DISASM-NEXT: 203c: ff e0 jmpl *%eax
+DISASM-NEXT: 203e: 51 pushl %ecx
+DISASM-NEXT: 203f: 52 pushl %edx
+DISASM-NEXT: 2040: 68 24 10 40 00 pushl $4198436
+DISASM-NEXT: 2045: 68 00 30 40 00 pushl $4206592
+DISASM-NEXT: 204a: e8 b1 ff ff ff calll -79 <_main@0>
+DISASM-NEXT: 204f: 5a popl %edx
+DISASM-NEXT: 2050: 59 popl %ecx
+DISASM-NEXT: 2051: ff e0 jmpl *%eax
diff --git a/test/COFF/dll.test b/test/COFF/dll.test
new file mode 100644
index 000000000000..bafd3c233c87
--- /dev/null
+++ b/test/COFF/dll.test
@@ -0,0 +1,53 @@
+# REQUIRES: winres
+# REQUIRES: winlib
+
+# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj
+# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2 \
+# RUN: /export:mangled
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=EXPORT %s
+
+EXPORT: Export Table:
+EXPORT: DLL name: dll.test.tmp.dll
+EXPORT: Ordinal RVA Name
+EXPORT-NEXT: 0 0
+EXPORT-NEXT: 1 0x1008 exportfn1
+EXPORT-NEXT: 2 0x1010 exportfn2
+EXPORT-NEXT: 3 0x1010 exportfn3
+EXPORT-NEXT: 4 0x1010 mangled
+
+# RUN: yaml2obj < %p/Inputs/export2.yaml > %t5.obj
+# RUN: rm -f %t5.lib
+# RUN: llvm-ar cru %t5.lib %t5.obj
+# RUN: lld-link /out:%t5.dll /dll %t.obj %t5.lib /export:mangled2
+# RUN: llvm-objdump -p %t5.dll | FileCheck -check-prefix=EXPORT2 %s
+
+EXPORT2: Export Table:
+EXPORT2: DLL name: dll.test.tmp5.dll
+EXPORT2: Ordinal RVA Name
+EXPORT2-NEXT: 0 0
+EXPORT2-NEXT: 1 0x1010 exportfn3
+EXPORT2-NEXT: 2 0x101c mangled2
+
+# RUN: llvm-as -o %t.lto.obj %p/Inputs/export.ll
+# RUN: lld-link /out:%t.lto.dll /dll %t.lto.obj /export:exportfn1 /export:exportfn2
+# RUN: llvm-objdump -p %t.lto.dll | FileCheck -check-prefix=EXPORT-LTO %s
+
+EXPORT-LTO: Export Table:
+EXPORT-LTO: DLL name: dll.test.tmp.lto.dll
+EXPORT-LTO: Ordinal RVA Name
+EXPORT-LTO-NEXT: 0 0
+EXPORT-LTO-NEXT: 1 0x1010 exportfn1
+EXPORT-LTO-NEXT: 2 0x1020 exportfn2
+EXPORT-LTO-NEXT: 3 0x1030 exportfn3
+
+# RUN: lld-link /out:%t.dll /dll %t.obj /implib:%t2.lib \
+# RUN: /export:exportfn1 /export:exportfn2
+# RUN: yaml2obj < %p/Inputs/import.yaml > %t2.obj
+# RUN: lld-link /out:%t2.exe /entry:main %t2.obj %t2.lib
+# RUN: llvm-readobj -coff-imports %t2.exe | FileCheck -check-prefix=IMPORT %s
+
+# RUN: lld-link /out:%t2.lto.exe /entry:main %t2.obj %t.lto.lib
+# RUN: llvm-readobj -coff-imports %t2.lto.exe | FileCheck -check-prefix=IMPORT %s
+
+IMPORT: Symbol: exportfn1
+IMPORT: Symbol: exportfn2
diff --git a/test/COFF/dllorder.test b/test/COFF/dllorder.test
new file mode 100644
index 000000000000..417483d33086
--- /dev/null
+++ b/test/COFF/dllorder.test
@@ -0,0 +1,65 @@
+# 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/driver.test b/test/COFF/driver.test
new file mode 100644
index 000000000000..0832350a4f30
--- /dev/null
+++ b/test/COFF/driver.test
@@ -0,0 +1,3 @@
+# RUN: not lld-link nosuchfile.obj >& %t.log
+# RUN: FileCheck -check-prefix=MISSING %s < %t.log
+MISSING: nosuchfile.obj: {{[Nn]}}o such file or directory
diff --git a/test/COFF/entry-inference.test b/test/COFF/entry-inference.test
new file mode 100644
index 000000000000..2063f28edc77
--- /dev/null
+++ b/test/COFF/entry-inference.test
@@ -0,0 +1,50 @@
+# RUN: sed -e s/ENTRYNAME/main/ %s | yaml2obj > %t.obj
+# RUN: not lld-link /out:%t.exe %t.obj > %t.log 2>&1
+# RUN: FileCheck -check-prefix=MAIN %s < %t.log
+
+# RUN: sed s/ENTRYNAME/wmain/ %s | yaml2obj > %t.obj
+# RUN: not lld-link /out:%t.exe %t.obj > %t.log 2>&1
+# RUN: FileCheck -check-prefix=WMAIN %s < %t.log
+
+# RUN: sed s/ENTRYNAME/WinMain/ %s | yaml2obj > %t.obj
+# RUN: not lld-link /out:%t.exe %t.obj > %t.log 2>&1
+# RUN: FileCheck -check-prefix=WINMAIN %s < %t.log
+
+# RUN: sed s/ENTRYNAME/wWinMain/ %s | yaml2obj > %t.obj
+# RUN: not lld-link /out:%t.exe %t.obj > %t.log 2>&1
+# RUN: FileCheck -check-prefix=WWINMAIN %s < %t.log
+
+# MAIN: <root>: undefined symbol: mainCRTStartup
+# WMAIN: <root>: undefined symbol: wmainCRTStartup
+# WINMAIN: <root>: undefined symbol: WinMainCRTStartup
+# WWINMAIN: <root>: undefined symbol: wWinMainCRTStartup
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B82A000000C3
+symbols:
+ - Name: .text
+ 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: ENTRYNAME
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/entry-inference2.test b/test/COFF/entry-inference2.test
new file mode 100644
index 000000000000..afac80859d10
--- /dev/null
+++ b/test/COFF/entry-inference2.test
@@ -0,0 +1,39 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: not lld-link /out:%t.exe %t.obj /verbose > %t.log 2>&1
+# RUN: FileCheck %s < %t.log
+
+# CHECK: Entry name inferred: WinMainCRTStartup
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B82A000000C3
+ - Name: .drectve
+ Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 2147483648
+ SectionData: 2f616c7465726e6174656e616d653a6d61696e3d57696e4d61696e00 # /alternatename:main=WinMain
+symbols:
+ - Name: .text
+ 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: WinMain
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/entry-inference32.test b/test/COFF/entry-inference32.test
new file mode 100644
index 000000000000..6e1a5f925180
--- /dev/null
+++ b/test/COFF/entry-inference32.test
@@ -0,0 +1,35 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: not lld-link /out:%t.exe %t.obj /verbose > %t.log 2>&1
+# RUN: FileCheck %s < %t.log
+
+# CHECK: Entry name inferred: _WinMainCRTStartup
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_I386
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B82A000000C3
+symbols:
+ - Name: .text
+ 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: _WinMain@16
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/entry-mangled.test b/test/COFF/entry-mangled.test
new file mode 100644
index 000000000000..41620336513e
--- /dev/null
+++ b/test/COFF/entry-mangled.test
@@ -0,0 +1,35 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: llvm-as -o %t.lto.obj %S/Inputs/entry-mangled.ll
+# RUN: lld-link /out:%t.exe /entry:main %t.lto.obj
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 000000000000
+symbols:
+ - Name: .text
+ 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
+ Selection: IMAGE_COMDAT_SELECT_ANY
+ - Name: '?main@@YAHXZ'
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/entrylib.ll b/test/COFF/entrylib.ll
new file mode 100644
index 000000000000..4ffa42c44a3e
--- /dev/null
+++ b/test/COFF/entrylib.ll
@@ -0,0 +1,11 @@
+; RUN: llvm-as -o %t.obj %s
+; RUN: rm -f %t.lib
+; RUN: llvm-ar cru %t.lib %t.obj
+; RUN: lld-link /out:%t.exe /entry:main %t.lib
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+define i32 @main() {
+ ret i32 0
+}
diff --git a/test/COFF/export-exe.test b/test/COFF/export-exe.test
new file mode 100644
index 000000000000..7a345160faa9
--- /dev/null
+++ b/test/COFF/export-exe.test
@@ -0,0 +1,11 @@
+# REQUIRES: winlib
+# RUN: lld-link /entry:main /out:%t.exe /subsystem:windows \
+# RUN: %p/Inputs/ret42.obj /export:main
+# RUN: llvm-objdump -p %t.exe | FileCheck %s
+
+CHECK: Export Table:
+CHECK-NEXT: DLL name: export-exe.test.tmp.exe
+CHECK-NEXT: Ordinal base: 0
+CHECK-NEXT: Ordinal RVA Name
+CHECK-NEXT: 0 0
+CHECK-NEXT: 1 0x1000 main
diff --git a/test/COFF/export.test b/test/COFF/export.test
new file mode 100644
index 000000000000..a3ea0ab9bca2
--- /dev/null
+++ b/test/COFF/export.test
@@ -0,0 +1,82 @@
+# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj
+#
+# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK1 %s
+# REQUIRES: winlib
+
+CHECK1: Export Table:
+CHECK1: DLL name: export.test.tmp.dll
+CHECK1: Ordinal RVA Name
+CHECK1-NEXT: 0 0
+CHECK1-NEXT: 1 0x1008 exportfn1
+CHECK1-NEXT: 2 0x1010 exportfn2
+
+# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1,@5 /export:exportfn2
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK2 %s
+
+CHECK2: Export Table:
+CHECK2: DLL name: export.test.tmp.dll
+CHECK2: Ordinal RVA Name
+CHECK2-NEXT: 0 0
+CHECK2-NEXT: 1 0
+CHECK2-NEXT: 2 0
+CHECK2-NEXT: 3 0
+CHECK2-NEXT: 4 0
+CHECK2-NEXT: 5 0x1008 exportfn1
+CHECK2-NEXT: 6 0x1010 exportfn2
+CHECK2-NEXT: 7 0x1010 exportfn3
+
+# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1,@5,noname /export:exportfn2
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK3 %s
+
+CHECK3: Export Table:
+CHECK3: DLL name: export.test.tmp.dll
+CHECK3: Ordinal RVA Name
+CHECK3-NEXT: 0 0
+CHECK3-NEXT: 1 0
+CHECK3-NEXT: 2 0
+CHECK3-NEXT: 3 0
+CHECK3-NEXT: 4 0
+CHECK3-NEXT: 5 0x1008
+CHECK3-NEXT: 6 0x1010 exportfn2
+
+# RUN: lld-link /out:%t.dll /dll %t.obj /export:f1=exportfn1 /export:f2=exportfn2
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK4 %s
+
+CHECK4: Export Table:
+CHECK4: DLL name: export.test.tmp.dll
+CHECK4: Ordinal RVA Name
+CHECK4-NEXT: 0 0
+CHECK4-NEXT: 1 0x1010 exportfn3
+CHECK4-NEXT: 2 0x1008 f1
+CHECK4-NEXT: 3 0x1010 f2
+
+# RUN: echo "EXPORTS exportfn1 @3" > %t.def
+# RUN: echo "fn2=exportfn2 @2" >> %t.def
+# RUN: lld-link /out:%t.dll /dll %t.obj /def:%t.def
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK5 %s
+
+CHECK5: Export Table:
+CHECK5: DLL name: export.test.tmp.dll
+CHECK5: Ordinal RVA Name
+CHECK5-NEXT: 0 0
+CHECK5-NEXT: 1 0
+CHECK5-NEXT: 2 0x1010 fn2
+CHECK5-NEXT: 3 0x1008 exportfn1
+CHECK5-NEXT: 4 0x1010 exportfn3
+
+# RUN: lld-link /out:%t.DLL /dll %t.obj /export:exportfn1 /export:exportfn2 \
+# RUN: /export:exportfn1 /export:exportfn2,@5 >& %t.log
+# RUN: FileCheck -check-prefix=CHECK6 %s < %t.log
+
+CHECK6: duplicate /export option: exportfn2
+CHECK6-NOT: duplicate /export option: exportfn1
+
+# RUN: llvm-nm -M %t.lib | FileCheck --check-prefix=SYMTAB %s
+
+SYMTAB: __imp_exportfn1 in export.test.tmp.DLL
+SYMTAB: exportfn1 in export.test.tmp.DLL
+SYMTAB: __imp_exportfn2 in export.test.tmp.DLL
+SYMTAB: exportfn2 in export.test.tmp.DLL
+SYMTAB: __imp_exportfn3 in export.test.tmp.DLL
+SYMTAB: exportfn3 in export.test.tmp.DLL
diff --git a/test/COFF/export32.test b/test/COFF/export32.test
new file mode 100644
index 000000000000..5d7b2708dcba
--- /dev/null
+++ b/test/COFF/export32.test
@@ -0,0 +1,133 @@
+# RUN: yaml2obj < %s > %t.obj
+#
+# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK1 %s
+# REQUIRES: winlib
+
+# CHECK1: Export Table:
+# CHECK1: DLL name: export32.test.tmp.dll
+# CHECK1: Ordinal RVA Name
+# CHECK1-NEXT: 0 0
+# CHECK1-NEXT: 1 0x1008 exportfn1
+# CHECK1-NEXT: 2 0x1010 exportfn2
+
+# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1,@5 \
+# RUN: /export:exportfn2 /export:mangled
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK2 %s
+
+# CHECK2: Export Table:
+# CHECK2: DLL name: export32.test.tmp.dll
+# CHECK2: Ordinal RVA Name
+# CHECK2-NEXT: 0 0
+# CHECK2-NEXT: 1 0
+# CHECK2-NEXT: 2 0
+# CHECK2-NEXT: 3 0
+# CHECK2-NEXT: 4 0
+# CHECK2-NEXT: 5 0x1008 exportfn1
+# CHECK2-NEXT: 6 0x1010 exportfn2
+# CHECK2-NEXT: 7 0x1010 exportfn3
+# CHECK2-NEXT: 8 0x1010 mangled
+
+# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1,@5,noname /export:exportfn2
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK3 %s
+
+# CHECK3: Export Table:
+# CHECK3: DLL name: export32.test.tmp.dll
+# CHECK3: Ordinal RVA Name
+# CHECK3-NEXT: 0 0
+# CHECK3-NEXT: 1 0
+# CHECK3-NEXT: 2 0
+# CHECK3-NEXT: 3 0
+# CHECK3-NEXT: 4 0
+# CHECK3-NEXT: 5 0x1008
+# CHECK3-NEXT: 6 0x1010 exportfn2
+
+# RUN: lld-link /out:%t.dll /dll %t.obj /export:f1=exportfn1 /export:f2=exportfn2
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK4 %s
+
+# CHECK4: Export Table:
+# CHECK4: DLL name: export32.test.tmp.dll
+# CHECK4: Ordinal RVA Name
+# CHECK4-NEXT: 0 0
+# CHECK4-NEXT: 1 0x1010 exportfn3
+# CHECK4-NEXT: 2 0x1008 f1
+# CHECK4-NEXT: 3 0x1010 f2
+
+# RUN: echo "EXPORTS exportfn1 @3" > %t.def
+# RUN: echo "fn2=exportfn2 @2" >> %t.def
+# RUN: lld-link /out:%t.dll /dll %t.obj /def:%t.def
+# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK5 %s
+
+# CHECK5: Export Table:
+# CHECK5: DLL name: export32.test.tmp.dll
+# CHECK5: Ordinal RVA Name
+# CHECK5-NEXT: 0 0
+# CHECK5-NEXT: 1 0
+# CHECK5-NEXT: 2 0x1010 fn2
+# CHECK5-NEXT: 3 0x1008 exportfn1
+# CHECK5-NEXT: 4 0x1010 exportfn3
+
+# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2 \
+# RUN: /export:exportfn1 /export:exportfn2,@5 >& %t.log
+# RUN: FileCheck -check-prefix=CHECK6 %s < %t.log
+
+# CHECK6: duplicate /export option: _exportfn2
+# CHECK6-NOT: duplicate /export option: _exportfn1
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_I386
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B800000000506800000000680000000050E80000000050E800000000
+ - Name: .drectve
+ Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 2147483648
+ SectionData: 2f6578706f72743a5f6578706f7274666e3300 # /export:_exportfn3
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 28
+ NumberOfRelocations: 4
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: __DllMainCRTStartup@12
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: _exportfn1
+ Value: 8
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: _exportfn2@4
+ Value: 16
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: _exportfn3
+ Value: 16
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '?mangled@@YAHXZ'
+ Value: 16
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/failifmismatch.test b/test/COFF/failifmismatch.test
new file mode 100644
index 000000000000..021d91b644c4
--- /dev/null
+++ b/test/COFF/failifmismatch.test
@@ -0,0 +1,11 @@
+# RUN: lld-link /entry:main /subsystem:console /out:%t.exe \
+# RUN: %p/Inputs/ret42.obj
+
+# RUN: lld-link /entry:main /subsystem:console /out:%t.exe \
+# RUN: %p/Inputs/ret42.obj /failifmismatch:k1=v1 /failifmismatch:k2=v1
+
+# RUN: lld-link /entry:main /subsystem:console /out:%t.exe \
+# RUN: %p/Inputs/ret42.obj /failifmismatch:k1=v1 /failifmismatch:k1=v1
+
+# RUN: not lld-link /entry:main /subsystem:console /out:%t.exe \
+# RUN: %p/Inputs/ret42.obj /failifmismatch:k1=v1 /failifmismatch:k1=v2
diff --git a/test/COFF/filetype.test b/test/COFF/filetype.test
new file mode 100644
index 000000000000..e161910ec2c8
--- /dev/null
+++ b/test/COFF/filetype.test
@@ -0,0 +1,4 @@
+# Make sure input file type is detected by file magic and not by extension.
+
+# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.lib
+# RUN: lld-link /out:%t.exe /entry:main %t.lib
diff --git a/test/COFF/force.test b/test/COFF/force.test
new file mode 100644
index 000000000000..44e5722dab5d
--- /dev/null
+++ b/test/COFF/force.test
@@ -0,0 +1,43 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: not lld-link /out:%t.exe /entry:main %t.obj >& %t.log
+# RUN: FileCheck %s < %t.log
+# RUN: lld-link /out:%t.exe /entry:main %t.obj /force >& %t.log
+# RUN: FileCheck %s < %t.log
+
+# CHECK: .obj: undefined symbol: foo
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 000000000000
+symbols:
+ - Name: .text
+ 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_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: foo
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/heap.test b/test/COFF/heap.test
new file mode 100644
index 000000000000..1eb70a2f1953
--- /dev/null
+++ b/test/COFF/heap.test
@@ -0,0 +1,25 @@
+# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=DEFAULT %s
+
+DEFAULT: SizeOfHeapReserve: 1048576
+DEFAULT: SizeOfHeapCommit: 4096
+
+# RUN: lld-link /out:%t.exe /entry:main /heap:0x3000 %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s
+# RUN: echo "HEAPSIZE 12288" > %t.def
+# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s
+
+CHECK1: SizeOfHeapReserve: 12288
+CHECK1: SizeOfHeapCommit: 4096
+
+# RUN: lld-link /out:%t.exe /entry:main /heap:0x5000,0x3000 %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s
+# RUN: echo "HEAPSIZE 20480,12288" > %t.def
+# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s
+
+CHECK2: SizeOfHeapReserve: 20480
+CHECK2: SizeOfHeapCommit: 12288
diff --git a/test/COFF/hello32.test b/test/COFF/hello32.test
new file mode 100644
index 000000000000..4307d4bf89a9
--- /dev/null
+++ b/test/COFF/hello32.test
@@ -0,0 +1,129 @@
+# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj
+# RUN: lld-link %t.obj %p/Inputs/std32.lib /subsystem:console \
+# RUN: /entry:main@0 /out:%t.exe
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=HEADER %s
+# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s
+# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s
+
+HEADER: Format: COFF-i386
+HEADER-NEXT: Arch: i386
+HEADER-NEXT: AddressSize: 32bit
+HEADER-NEXT: ImageFileHeader {
+HEADER-NEXT: Machine: IMAGE_FILE_MACHINE_I386 (0x14C)
+HEADER-NEXT: SectionCount: 4
+HEADER-NEXT: TimeDateStamp: 1970-01-01 00:00:00 (0x0)
+HEADER-NEXT: PointerToSymbolTable: 0x0
+HEADER-NEXT: SymbolCount: 0
+HEADER-NEXT: OptionalHeaderSize: 224
+HEADER-NEXT: Characteristics [ (0x102)
+HEADER-NEXT: IMAGE_FILE_32BIT_MACHINE (0x100)
+HEADER-NEXT: IMAGE_FILE_EXECUTABLE_IMAGE (0x2)
+HEADER-NEXT: ]
+HEADER-NEXT: }
+HEADER-NEXT: ImageOptionalHeader {
+HEADER-NEXT: MajorLinkerVersion: 0
+HEADER-NEXT: MinorLinkerVersion: 0
+HEADER-NEXT: SizeOfCode: 512
+HEADER-NEXT: SizeOfInitializedData: 1536
+HEADER-NEXT: SizeOfUninitializedData: 0
+HEADER-NEXT: AddressOfEntryPoint: 0x2000
+HEADER-NEXT: BaseOfCode: 0x2000
+HEADER-NEXT: BaseOfData: 0x0
+HEADER-NEXT: ImageBase: 0x400000
+HEADER-NEXT: SectionAlignment: 4096
+HEADER-NEXT: FileAlignment: 512
+HEADER-NEXT: MajorOperatingSystemVersion: 6
+HEADER-NEXT: MinorOperatingSystemVersion: 0
+HEADER-NEXT: MajorImageVersion: 0
+HEADER-NEXT: MinorImageVersion: 0
+HEADER-NEXT: MajorSubsystemVersion: 6
+HEADER-NEXT: MinorSubsystemVersion: 0
+HEADER-NEXT: SizeOfImage: 16896
+HEADER-NEXT: SizeOfHeaders: 512
+HEADER-NEXT: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3)
+HEADER-NEXT: Characteristics [ (0x8140)
+HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE (0x40)
+HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT (0x100)
+HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE (0x8000)
+HEADER-NEXT: ]
+HEADER-NEXT: SizeOfStackReserve: 1048576
+HEADER-NEXT: SizeOfStackCommit: 4096
+HEADER-NEXT: SizeOfHeapReserve: 1048576
+HEADER-NEXT: SizeOfHeapCommit: 4096
+HEADER-NEXT: NumberOfRvaAndSize: 16
+HEADER-NEXT: DataDirectory {
+HEADER-NEXT: ExportTableRVA: 0x0
+HEADER-NEXT: ExportTableSize: 0x0
+HEADER-NEXT: ImportTableRVA: 0x3000
+HEADER-NEXT: ImportTableSize: 0x28
+HEADER-NEXT: ResourceTableRVA: 0x0
+HEADER-NEXT: ResourceTableSize: 0x0
+HEADER-NEXT: ExceptionTableRVA: 0x0
+HEADER-NEXT: ExceptionTableSize: 0x0
+HEADER-NEXT: CertificateTableRVA: 0x0
+HEADER-NEXT: CertificateTableSize: 0x0
+HEADER-NEXT: BaseRelocationTableRVA: 0x4000
+HEADER-NEXT: BaseRelocationTableSize: 0x10
+HEADER-NEXT: DebugRVA: 0x0
+HEADER-NEXT: DebugSize: 0x0
+HEADER-NEXT: ArchitectureRVA: 0x0
+HEADER-NEXT: ArchitectureSize: 0x0
+HEADER-NEXT: GlobalPtrRVA: 0x0
+HEADER-NEXT: GlobalPtrSize: 0x0
+HEADER-NEXT: TLSTableRVA: 0x0
+HEADER-NEXT: TLSTableSize: 0x0
+HEADER-NEXT: LoadConfigTableRVA: 0x0
+HEADER-NEXT: LoadConfigTableSize: 0x0
+HEADER-NEXT: BoundImportRVA: 0x0
+HEADER-NEXT: BoundImportSize: 0x0
+HEADER-NEXT: IATRVA: 0x3034
+HEADER-NEXT: IATSize: 0xC
+HEADER-NEXT: DelayImportDescriptorRVA: 0x0
+HEADER-NEXT: DelayImportDescriptorSize: 0x0
+HEADER-NEXT: CLRRuntimeHeaderRVA: 0x0
+HEADER-NEXT: CLRRuntimeHeaderSize: 0x0
+HEADER-NEXT: ReservedRVA: 0x0
+HEADER-NEXT: ReservedSize: 0x0
+HEADER-NEXT: }
+HEADER-NEXT: }
+HEADER-NEXT: DOSHeader {
+HEADER-NEXT: Magic: MZ
+HEADER-NEXT: UsedBytesInTheLastPage: 0
+HEADER-NEXT: FileSizeInPages: 0
+HEADER-NEXT: NumberOfRelocationItems: 0
+HEADER-NEXT: HeaderSizeInParagraphs: 0
+HEADER-NEXT: MinimumExtraParagraphs: 0
+HEADER-NEXT: MaximumExtraParagraphs: 0
+HEADER-NEXT: InitialRelativeSS: 0
+HEADER-NEXT: InitialSP: 0
+HEADER-NEXT: Checksum: 0
+HEADER-NEXT: InitialIP: 0
+HEADER-NEXT: InitialRelativeCS: 0
+HEADER-NEXT: AddressOfRelocationTable: 64
+HEADER-NEXT: OverlayNumber: 0
+HEADER-NEXT: OEMid: 0
+HEADER-NEXT: OEMinfo: 0
+HEADER-NEXT: AddressOfNewExeHeader: 64
+HEADER-NEXT: }
+
+IMPORTS: Format: COFF-i386
+IMPORTS: Arch: i386
+IMPORTS: AddressSize: 32bit
+IMPORTS: Import {
+IMPORTS: Name: std32.dll
+IMPORTS: ImportLookupTableRVA: 0x3028
+IMPORTS: ImportAddressTableRVA: 0x3034
+IMPORTS: Symbol: ExitProcess (0)
+IMPORTS: Symbol: MessageBoxA (1)
+IMPORTS: }
+
+BASEREL: BaseReloc [
+BASEREL: Entry {
+BASEREL: Type: HIGHLOW
+BASEREL: Address: 0x2005
+BASEREL: }
+BASEREL: Entry {
+BASEREL: Type: HIGHLOW
+BASEREL: Address: 0x200C
+BASEREL: }
+BASEREL: ]
diff --git a/test/COFF/help.test b/test/COFF/help.test
new file mode 100644
index 000000000000..d36fe6d785fa
--- /dev/null
+++ b/test/COFF/help.test
@@ -0,0 +1,3 @@
+# RUN: lld-link /help | FileCheck %s
+
+CHECK: OVERVIEW: LLVM Linker
diff --git a/test/COFF/icf-circular.test b/test/COFF/icf-circular.test
new file mode 100644
index 000000000000..7319e135e2e6
--- /dev/null
+++ b/test/COFF/icf-circular.test
@@ -0,0 +1,81 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /entry:foo /out:%t.exe /subsystem:console /include:bar \
+# RUN: /verbose %t.obj > %t.log 2>&1
+# RUN: FileCheck %s < %t.log
+
+# CHECK: Selected foo
+# CHECK: Removed bar
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: '.text$mn'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 4883EC28E8000000004883C428C3
+ Relocations:
+ - VirtualAddress: 5
+ SymbolName: foo
+ Type: IMAGE_REL_AMD64_REL32
+ - VirtualAddress: 10
+ SymbolName: __ImageBase
+ Type: IMAGE_REL_AMD64_REL32
+ - Name: '.text$mn'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 4883EC28E8000000004883C428C3
+ Relocations:
+ - VirtualAddress: 5
+ SymbolName: bar
+ Type: IMAGE_REL_AMD64_REL32
+ - VirtualAddress: 10
+ SymbolName: __ImageBase
+ Type: IMAGE_REL_AMD64_REL32
+symbols:
+ - Name: '.text$mn'
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 14
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 1682752513
+ Number: 0
+ Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
+ - Name: '.text$mn'
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 14
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 1682752513
+ Number: 0
+ Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
+ - Name: foo
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: bar
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __ImageBase
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/icf-circular2.test b/test/COFF/icf-circular2.test
new file mode 100644
index 000000000000..e7598c124365
--- /dev/null
+++ b/test/COFF/icf-circular2.test
@@ -0,0 +1,69 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /entry:foo /out:%t.exe /subsystem:console /include:bar \
+# RUN: /verbose %t.obj > %t.log 2>&1
+# RUN: FileCheck %s < %t.log
+
+# CHECK: Selected foo
+# CHECK: Removed bar
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: '.text$mn'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 4883EC28E8000000004883C428C3
+ Relocations:
+ - VirtualAddress: 5
+ SymbolName: foo
+ Type: IMAGE_REL_AMD64_REL32
+ - Name: '.text$mn'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 4883EC28E8000000004883C428C3
+ Relocations:
+ - VirtualAddress: 5
+ SymbolName: foo
+ Type: IMAGE_REL_AMD64_REL32
+symbols:
+ - Name: '.text$mn'
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 14
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 1682752513
+ Number: 0
+ Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
+ - Name: '.text$mn'
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 14
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 1682752513
+ Number: 0
+ Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
+ - Name: foo
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: bar
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/icf-different-align.test b/test/COFF/icf-different-align.test
new file mode 100644
index 000000000000..6876048a5d40
--- /dev/null
+++ b/test/COFF/icf-different-align.test
@@ -0,0 +1,61 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /entry:foo /out:%t.exe /subsystem:console /include:bar \
+# RUN: /verbose %t.obj > %t.log 2>&1
+# RUN: FileCheck %s < %t.log
+
+# CHECK-NOT: Selected foo
+# CHECK-NOT: Removed bar
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: '.text$mn'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 8
+ SectionData: 4883EC28E8000000004883C428C3
+ - Name: '.text$mn'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 4883EC28E8000000004883C428C3
+symbols:
+ - Name: '.text$mn'
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 14
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 1682752513
+ Number: 0
+ Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
+ - Name: '.text$mn'
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 14
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 1682752513
+ Number: 0
+ Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
+ - Name: foo
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: bar
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/icf-local.test b/test/COFF/icf-local.test
new file mode 100644
index 000000000000..a0b4c91559a3
--- /dev/null
+++ b/test/COFF/icf-local.test
@@ -0,0 +1,66 @@
+# COMDAT sections with non-external linkage should not be merged by ICF.
+
+# RUN: yaml2obj < %s > %t1.obj
+# RUN: sed s/foo/main/ %s | yaml2obj > %t2.obj
+# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /verbose \
+# RUN: %t1.obj %t2.obj > %t.log 2>&1
+# RUN: FileCheck %s < %t.log
+
+# CHECK-NOT: Removed bar
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 488D0500000000C3
+ Relocations:
+ - VirtualAddress: 3
+ SymbolName: bar
+ Type: IMAGE_REL_AMD64_REL32
+ - Name: .rdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ]
+ Alignment: 8
+ SectionData: 2A000000000000002B00000000000000
+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: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 1092178131
+ Number: 1
+ - Name: .rdata
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 16
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 1200668497
+ Number: 5
+ Selection: IMAGE_COMDAT_SELECT_ANY
+ - Name: foo
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: bar
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+...
diff --git a/test/COFF/icf-simple.test b/test/COFF/icf-simple.test
new file mode 100644
index 000000000000..ae72fd9d9d73
--- /dev/null
+++ b/test/COFF/icf-simple.test
@@ -0,0 +1,71 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /entry:foo /out:%t.exe /subsystem:console /include:bar \
+# RUN: /verbose %t.obj > %t.log 2>&1
+# RUN: FileCheck -check-prefix=ICF %s < %t.log
+
+# ICF: Selected foo
+# ICF: Removed bar
+
+# RUN: lld-link /entry:foo /out:%t.exe /subsystem:console /include:bar \
+# RUN: /verbose /opt:noicf %t.obj > %t.log 2>&1
+# RUN: FileCheck -check-prefix=NOICF %s < %t.log
+# RUN: lld-link /entry:foo /out:%t.exe /subsystem:console /include:bar \
+# RUN: /verbose /opt:noref,noicf %t.obj > %t.log 2>&1
+# RUN: FileCheck -check-prefix=NOICF %s < %t.log
+
+# NOICF-NOT: Removed foo
+# NOICF-NOT: Removed bar
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: '.text$mn'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 4883EC28E8000000004883C428C3
+ - Name: '.text$mn'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 4883EC28E8000000004883C428C3
+symbols:
+ - Name: '.text$mn'
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 14
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 1682752513
+ Number: 0
+ Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
+ - Name: '.text$mn'
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 14
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 1682752513
+ Number: 0
+ Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
+ - Name: foo
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: bar
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/imports-mangle.test b/test/COFF/imports-mangle.test
new file mode 100644
index 000000000000..35b385559005
--- /dev/null
+++ b/test/COFF/imports-mangle.test
@@ -0,0 +1,66 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /out:%t.exe /opt:noref /entry:main \
+# RUN: %t.obj %p/Inputs/imports-mangle.lib
+# RUN: llvm-readobj -coff-imports %t.exe | FileCheck %s
+
+# CHECK: Import {
+# CHECK: Symbol: sym4 (0)
+# CHECK: Symbol: _sym3 (1)
+# CHECK: Symbol: sym1 (2)
+# CHECK: Symbol: (2)
+# CHECK: }
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 000000000000
+symbols:
+ - Name: .text
+ 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
+ Selection: IMAGE_COMDAT_SELECT_ANY
+ - Name: main
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: sym1
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: sym2
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __sym3
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '?sym4@@YAHH@Z'
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/imports.test b/test/COFF/imports.test
new file mode 100644
index 000000000000..584c24eb1b76
--- /dev/null
+++ b/test/COFF/imports.test
@@ -0,0 +1,35 @@
+# Verify that the lld can handle .lib files and emit .idata sections.
+#
+# RUN: lld-link /out:%t.exe /entry:main /subsystem:console \
+# RUN: %p/Inputs/hello64.obj %p/Inputs/std64.lib
+# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=TEXT %s
+# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s
+
+# RUN: lld-link /out:%t.exe /entry:main /subsystem:console \
+# RUN: %p/Inputs/hello64.obj %p/Inputs/std64.lib /include:ExitProcess
+# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=TEXT %s
+# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s
+
+TEXT: Disassembly of section .text:
+TEXT-NEXT: .text:
+TEXT-NEXT: subq $40, %rsp
+TEXT-NEXT: movq $0, %rcx
+TEXT-NEXT: leaq -4108(%rip), %rdx
+TEXT-NEXT: leaq -4121(%rip), %r8
+TEXT-NEXT: movl $0, %r9d
+TEXT-NEXT: callq 60
+TEXT-NEXT: movl $0, %ecx
+TEXT-NEXT: callq 18
+TEXT-NEXT: callq 29
+TEXT: jmpq *4098(%rip)
+TEXT: jmpq *4090(%rip)
+TEXT: jmpq *4082(%rip)
+
+IMPORT: Import {
+IMPORT-NEXT: Name: std64.dll
+IMPORT-NEXT: ImportLookupTableRVA: 0x3028
+IMPORT-NEXT: ImportAddressTableRVA: 0x3048
+IMPORT-NEXT: Symbol: ExitProcess (0)
+IMPORT-NEXT: Symbol: (50)
+IMPORT-NEXT: Symbol: MessageBoxA (1)
+IMPORT-NEXT: }
diff --git a/test/COFF/include.test b/test/COFF/include.test
new file mode 100644
index 000000000000..b9e5f49b4fb6
--- /dev/null
+++ b/test/COFF/include.test
@@ -0,0 +1,83 @@
+# RUN: yaml2obj < %s > %t.obj
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj /verbose >& %t.log
+### FileCheck doesn't like empty input, so write something.
+# RUN: echo dummy >> %t.log
+# RUN: FileCheck -check-prefix=CHECK1 %s < %t.log
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj /verbose /include:unused >& %t.log
+# RUN: echo dummy >> %t.log
+# RUN: FileCheck -check-prefix=CHECK2 %s < %t.log
+
+# CHECK1: Discarded unused
+# CHECK1-NOT: Discarded used
+# CHECK2-NOT: Discarded unused
+# CHECK2-NOT: Discarded used
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: '.text$mn'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B82A000000C3
+ - Name: '.text$mn'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B82A000000C3
+ - Name: '.text$mn'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B82A000000C3
+ - Name: .drectve
+ Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
+ Alignment: 2147483648
+ SectionData: 2f696e636c7564653a7573656400 # /include:used
+symbols:
+ - Name: '.text$mn'
+ 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
+ Selection: IMAGE_COMDAT_SELECT_ANY
+ - Name: '.text$mn'
+ Value: 0
+ SectionNumber: 2
+ 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
+ Selection: IMAGE_COMDAT_SELECT_ANY
+ - Name: main
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: used
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: unused
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/include2.test b/test/COFF/include2.test
new file mode 100644
index 000000000000..f2379eaede40
--- /dev/null
+++ b/test/COFF/include2.test
@@ -0,0 +1,14 @@
+# RUN: yaml2obj < %p/Inputs/include1a.yaml > %t1.obj
+# RUN: yaml2obj < %p/Inputs/include1b.yaml > %t2.obj
+# RUN: yaml2obj < %p/Inputs/include1c.yaml > %t3.obj
+# RUN: rm -f %t2.lib %t3.lib
+# RUN: llvm-ar cru %t2.lib %t2.obj
+# RUN: llvm-ar cru %t3.lib %t3.obj
+# RUN: lld-link /out:%t.exe /entry:main %t1.obj %t2.lib %t3.lib /verbose >& %t.log
+# RUN: FileCheck %s < %t.log
+
+CHECK: include2.test.tmp1.obj
+CHECK: include2.test.tmp2.lib
+CHECK: include2.test.tmp3.lib
+CHECK: include2.test.tmp2.lib(include2.test.tmp2.obj) for foo
+CHECK: include2.test.tmp3.lib(include2.test.tmp3.obj) for bar
diff --git a/test/COFF/internal.test b/test/COFF/internal.test
new file mode 100644
index 000000000000..80a5332847de
--- /dev/null
+++ b/test/COFF/internal.test
@@ -0,0 +1,42 @@
+# Test that non-external symbols don't conflict
+
+# RUN: yaml2obj < %s > %t1.obj
+# RUN: yaml2obj < %s > %t2.obj
+# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t3.obj
+# RUN: lld-link /out:%t.exe /entry:main %t1.obj %t2.obj %t3.obj
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 000000000000
+symbols:
+ - Name: .text
+ 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: defined
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: absolute
+ Value: 0xdeadbeef
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+...
diff --git a/test/COFF/invalid-obj.test b/test/COFF/invalid-obj.test
new file mode 100644
index 000000000000..fd63f7874cc1
--- /dev/null
+++ b/test/COFF/invalid-obj.test
@@ -0,0 +1,14 @@
+# RUN: yaml2obj %s > %t.obj
+# RUN: not lld-link %t.obj 2>&1 | FileCheck %s
+
+# CHECK: getSectionName failed: #1:
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: '/1'
+ Characteristics: []
+ SectionData: 00
+symbols:
diff --git a/test/COFF/largeaddressaware.test b/test/COFF/largeaddressaware.test
new file mode 100644
index 000000000000..d035e7ce9993
--- /dev/null
+++ b/test/COFF/largeaddressaware.test
@@ -0,0 +1,21 @@
+# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj
+# RUN: lld-link %t.obj %p/Inputs/std32.lib /subsystem:console \
+# RUN: /entry:main@0 /out:%t.exe /largeaddressaware
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=HEADER %s
+
+HEADER: Format: COFF-i386
+HEADER-NEXT: Arch: i386
+HEADER-NEXT: AddressSize: 32bit
+HEADER-NEXT: ImageFileHeader {
+HEADER-NEXT: Machine: IMAGE_FILE_MACHINE_I386 (0x14C)
+HEADER-NEXT: SectionCount: 4
+HEADER-NEXT: TimeDateStamp: 1970-01-01 00:00:00 (0x0)
+HEADER-NEXT: PointerToSymbolTable: 0x0
+HEADER-NEXT: SymbolCount: 0
+HEADER-NEXT: OptionalHeaderSize: 224
+HEADER-NEXT: Characteristics [ (0x122)
+HEADER-NEXT: IMAGE_FILE_32BIT_MACHINE (0x100)
+HEADER-NEXT: IMAGE_FILE_EXECUTABLE_IMAGE (0x2)
+HEADER-NEXT: IMAGE_FILE_LARGE_ADDRESS_AWARE (0x20)
+HEADER-NEXT: ]
+HEADER-NEXT: }
diff --git a/test/COFF/libpath.test b/test/COFF/libpath.test
new file mode 100644
index 000000000000..da465bc556bc
--- /dev/null
+++ b/test/COFF/libpath.test
@@ -0,0 +1,18 @@
+# RUN: mkdir -p %t/a %t/b %t/c
+# RUN: cp %p/Inputs/std64.lib %t/a/
+# RUN: cp %p/Inputs/std64.lib %t/b/
+# RUN: cp %p/Inputs/std64.lib %t/c/
+
+# RUN: env LIB=%t/a lld-link /out:%t.exe /entry:main /verbose \
+# RUN: std64.lib /subsystem:console %p/Inputs/hello64.obj \
+# RUN: /libpath:%t/b /libpath:%t/c > %t.log
+# RUN: FileCheck -check-prefix=CHECK1 %s < %t.log
+
+CHECK1: b{{[/\\]}}std64.lib
+
+# RUN: lld-link /out:%t.exe /entry:main /verbose \
+# RUN: std64.lib /subsystem:console %p/Inputs/hello64.obj \
+# RUN: /libpath:%t/a /libpath:%t/b /libpath:%t/c > %t.log
+# RUN: FileCheck -check-prefix=CHECK2 %s < %t.log
+
+CHECK2: a{{[/\\]}}std64.lib
diff --git a/test/COFF/linkenv.test b/test/COFF/linkenv.test
new file mode 100644
index 000000000000..5dfb875a7daf
--- /dev/null
+++ b/test/COFF/linkenv.test
@@ -0,0 +1,4 @@
+# RUN: env LINK=-help lld-link > %t.log
+# RUN: FileCheck %s < %t.log
+
+CHECK: OVERVIEW: LLVM Linker
diff --git a/test/COFF/lldmap.test b/test/COFF/lldmap.test
new file mode 100644
index 000000000000..a4c2da09ca33
--- /dev/null
+++ b/test/COFF/lldmap.test
@@ -0,0 +1,8 @@
+# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
+# RUN: lld-link /out:%t.exe /entry:main /lldmap:%t.map %t.obj
+# RUN: FileCheck %s < %t.map
+
+# CHECK: .obj:
+# CHECK-NEXT: 140001000 .text$mn
+# CHECK-NEXT: 140001000 .data
+# CHECK-NEXT: 140001000 main
diff --git a/test/COFF/loadcfg.ll b/test/COFF/loadcfg.ll
new file mode 100644
index 000000000000..3166881032b4
--- /dev/null
+++ b/test/COFF/loadcfg.ll
@@ -0,0 +1,15 @@
+; RUN: llvm-as -o %t.obj %s
+; RUN: lld-link /out:%t.exe %t.obj /entry:main /subsystem:console
+; RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
+
+; CHECK: LoadConfigTableRVA: 0x1000
+; CHECK: LoadConfigTableSize: 0x70
+
+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
+
+define void @main() {
+ ret void
+}
diff --git a/test/COFF/loadcfg.test b/test/COFF/loadcfg.test
new file mode 100644
index 000000000000..a84f864b4b53
--- /dev/null
+++ b/test/COFF/loadcfg.test
@@ -0,0 +1,59 @@
+# RUN: yaml2obj < %s > %t.obj
+# 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: LoadConfigTableSize: 0x70
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B82A000000C3
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B82A000000C3
+symbols:
+ - Name: .text
+ 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: .text
+ Value: 0
+ SectionNumber: 2
+ 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
+ Selection: IMAGE_COMDAT_SELECT_ANY
+ - Name: main
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: _load_config_used
+ Value: 0
+ SectionNumber: 2
+ 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
new file mode 100644
index 000000000000..f7780e1d0373
--- /dev/null
+++ b/test/COFF/loadcfg32.test
@@ -0,0 +1,42 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /out:%t.exe %t.obj /entry:main /subsystem:console
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
+
+# CHECK: LoadConfigTableRVA: 0x1000
+# CHECK: LoadConfigTableSize: 0x40
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_I386
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B82A000000C3
+symbols:
+ - Name: .text
+ 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_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __load_config_used
+ Value: 0
+ SectionNumber: 1
+ 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
new file mode 100644
index 000000000000..7c43666c8c1e
--- /dev/null
+++ b/test/COFF/locally-imported.test
@@ -0,0 +1,61 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: llvm-objdump -s %t.exe | FileCheck %s
+# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s
+
+# CHECK: Contents of section .text:
+# CHECK-NEXT: 1000 00200000
+# CHECK: Contents of section .rdata:
+# CHECK-NEXT: 2000 04100040 01000000
+
+# BASEREL: BaseReloc [
+# BASEREL-NEXT: Entry {
+# BASEREL-NEXT: Type: DIR64
+# BASEREL-NEXT: Address: 0x2000
+# BASEREL-NEXT: }
+# BASEREL-NEXT: Entry {
+# BASEREL-NEXT: Type: ABSOLUTE
+# BASEREL-NEXT: Address: 0x2000
+# BASEREL-NEXT: }
+# BASEREL-NEXT: ]
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 00000000
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: __imp_main
+ Type: IMAGE_REL_AMD64_ADDR32NB
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 4
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ Selection: IMAGE_COMDAT_SELECT_ANY
+ - Name: main
+ Value: 4
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __imp_main
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/locally-imported32.test b/test/COFF/locally-imported32.test
new file mode 100644
index 000000000000..7f604d2a0495
--- /dev/null
+++ b/test/COFF/locally-imported32.test
@@ -0,0 +1,50 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: llvm-objdump -s %t.exe | FileCheck %s
+
+# CHECK: Contents of section .text:
+# CHECK-NEXT: 1000 00200000
+
+# CHECK: Contents of section .rdata:
+# CHECK-NEXT: 2000 04104000
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_I386
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 00000000
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: __imp__main
+ Type: IMAGE_REL_I386_DIR32NB
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 4
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ Selection: IMAGE_COMDAT_SELECT_ANY
+ - Name: _main
+ Value: 4
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __imp__main
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/long-section-name.test b/test/COFF/long-section-name.test
new file mode 100644
index 000000000000..a3dad33ec2cf
--- /dev/null
+++ b/test/COFF/long-section-name.test
@@ -0,0 +1,58 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /debug /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -sections %t.exe | FileCheck %s
+
+# CHECK: Name: .data_long_section_name
+# CHECK: Name: .text_long_section_name
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: .text_long_section_name
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B82A000000C3
+ - Name: .data_long_section_name
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: "00"
+symbols:
+ - Name: "@comp.id"
+ Value: 10394907
+ SectionNumber: 65535
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: .text_long_section_name
+ 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: .data_long_section_name
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 0
+ 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
+...
diff --git a/test/COFF/lto-chkstk.ll b/test/COFF/lto-chkstk.ll
new file mode 100644
index 000000000000..43b0bff164e3
--- /dev/null
+++ b/test/COFF/lto-chkstk.ll
@@ -0,0 +1,17 @@
+; RUN: llvm-as -o %t.obj %s
+; RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o %T/lto-chkstk-foo.obj %S/Inputs/lto-chkstk-foo.s
+; RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o %T/lto-chkstk-chkstk.obj %S/Inputs/lto-chkstk-chkstk.s
+; RUN: llvm-ar cru %t.lib %T/lto-chkstk-chkstk.obj
+; RUN: lld-link /out:%t.exe /entry:main /subsystem:console %t.obj %T/lto-chkstk-foo.obj %t.lib
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+define void @main() {
+entry:
+ %array4096 = alloca [4096 x i8]
+ call void @foo([4096 x i8]* %array4096)
+ ret void
+}
+
+declare void @foo([4096 x i8]*)
diff --git a/test/COFF/lto-comdat.ll b/test/COFF/lto-comdat.ll
new file mode 100644
index 000000000000..aaa7a16c4afb
--- /dev/null
+++ b/test/COFF/lto-comdat.ll
@@ -0,0 +1,131 @@
+; RUN: llvm-as -o %T/comdat-main.lto.obj %s
+; RUN: llvm-as -o %T/comdat1.lto.obj %S/Inputs/lto-comdat1.ll
+; RUN: llvm-as -o %T/comdat2.lto.obj %S/Inputs/lto-comdat2.ll
+; RUN: rm -f %T/comdat.lto.lib
+; RUN: llvm-ar cru %T/comdat.lto.lib %T/comdat1.lto.obj %T/comdat2.lto.obj
+
+; RUN: llc -filetype=obj -o %T/comdat-main.obj %s
+; RUN: llc -filetype=obj -o %T/comdat1.obj %S/Inputs/lto-comdat1.ll
+; RUN: llc -filetype=obj -o %T/comdat2.obj %S/Inputs/lto-comdat2.ll
+; RUN: rm -f %T/comdat.lib
+; RUN: llvm-ar cru %T/comdat.lib %T/comdat1.obj %T/comdat2.obj
+
+; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.lto.obj %T/comdat1.lto.obj %T/comdat2.lto.obj
+; RUN: llvm-readobj -file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-11 %s
+; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-11 %s
+; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.lto.obj %T/comdat.lto.lib
+; RUN: llvm-readobj -file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-11 %s
+; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-11 %s
+
+; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.obj %T/comdat1.lto.obj %T/comdat2.lto.obj
+; RUN: llvm-readobj -file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-01 %s
+; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-01 %s
+; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.obj %T/comdat.lto.lib
+; RUN: llvm-readobj -file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-01 %s
+; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-01 %s
+
+; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.lto.obj %T/comdat1.obj %T/comdat2.obj
+; RUN: llvm-readobj -file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-10 %s
+; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-10 %s
+; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.lto.obj %T/comdat.lib
+; RUN: llvm-readobj -file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-10 %s
+; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-10 %s
+
+; HEADERS-11: AddressOfEntryPoint: 0x1000
+; TEXT-11: Disassembly of section .text:
+; TEXT-11-NEXT: .text:
+; TEXT-11-NEXT: xorl %eax, %eax
+; TEXT-11-NEXT: retq
+
+; HEADERS-01: AddressOfEntryPoint: 0x2000
+; TEXT-01: Disassembly of section .text:
+; TEXT-01-NEXT: .text:
+; TEXT-01-NEXT: subq $40, %rsp
+; TEXT-01-NEXT: callq 39
+; TEXT-01-NEXT: callq 50
+; TEXT-01-NEXT: callq 13
+; TEXT-01-NEXT: xorl %eax, %eax
+; TEXT-01-NEXT: addq $40, %rsp
+; TEXT-01-NEXT: retq
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: retq
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: retq
+; TEXT-01-NEXT: nopw %cs:(%rax,%rax)
+; TEXT-01-NEXT: retq
+
+; HEADERS-10: AddressOfEntryPoint: 0x2030
+; TEXT-10: Disassembly of section .text:
+; TEXT-10-NEXT: .text:
+; TEXT-10-NEXT: subq $40, %rsp
+; TEXT-10-NEXT: callq 7
+; TEXT-10-NEXT: nop
+; TEXT-10-NEXT: addq $40, %rsp
+; TEXT-10-NEXT: retq
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: retq
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: subq $40, %rsp
+; TEXT-10-NEXT: callq -25
+; TEXT-10-NEXT: nop
+; TEXT-10-NEXT: addq $40, %rsp
+; TEXT-10-NEXT: retq
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: subq $40, %rsp
+; TEXT-10-NEXT: callq -57
+; TEXT-10-NEXT: callq -30
+; TEXT-10-NEXT: xorl %eax, %eax
+; TEXT-10-NEXT: addq $40, %rsp
+; TEXT-10-NEXT: retq
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+$comdat = comdat any
+
+define i32 @main() {
+ call void @f1()
+ call void @f2()
+ call void @comdat()
+ ret i32 0
+}
+
+define linkonce_odr void @comdat() comdat {
+ ret void
+}
+
+declare void @f1()
+declare void @f2()
diff --git a/test/COFF/lto-linker-opts.ll b/test/COFF/lto-linker-opts.ll
new file mode 100644
index 000000000000..0c183701b686
--- /dev/null
+++ b/test/COFF/lto-linker-opts.ll
@@ -0,0 +1,11 @@
+; RUN: llvm-as -o %T/lto-linker-opts.obj %s
+; RUN: env LIB=%S/Inputs lld-link /out:%T/lto-linker-opts.exe /entry:main /subsystem:console %T/lto-linker-opts.obj
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+!llvm.module.flags = !{!0}
+
+!0 = !{i32 6, !"Linker Options", !1}
+!1 = !{!2}
+!2 = !{!"/DEFAULTLIB:ret42.lib"}
diff --git a/test/COFF/lto-new-symbol.ll b/test/COFF/lto-new-symbol.ll
new file mode 100644
index 000000000000..d9e14eb93264
--- /dev/null
+++ b/test/COFF/lto-new-symbol.ll
@@ -0,0 +1,16 @@
+; RUN: llvm-as -o %t.obj %s
+; RUN: lld-link /out:%t.exe /entry:foo /subsystem:console %t.obj
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+define void @foo(<4 x i32>* %p, <4 x float>* %q, i1 %t) nounwind {
+entry:
+ br label %loop
+loop:
+ store <4 x i32><i32 1073741824, i32 1073741824, i32 1073741824, i32 1073741824>, <4 x i32>* %p
+ store <4 x float><float 2.0, float 2.0, float 2.0, float 2.0>, <4 x float>* %q
+ br i1 %t, label %loop, label %ret
+ret:
+ ret void
+}
diff --git a/test/COFF/lto-opt-level.ll b/test/COFF/lto-opt-level.ll
new file mode 100644
index 000000000000..674b6cc0f934
--- /dev/null
+++ b/test/COFF/lto-opt-level.ll
@@ -0,0 +1,21 @@
+; RUN: llvm-as -o %t.obj %s
+; RUN: lld-link /out:%t0.exe /entry:main /subsystem:console /opt:lldlto=0 /debug %t.obj
+; RUN: llvm-nm %t0.exe | FileCheck --check-prefix=CHECK-O0 %s
+; RUN: lld-link /out:%t2.exe /entry:main /subsystem:console /opt:lldlto=2 /debug %t.obj
+; RUN: llvm-nm %t2.exe | FileCheck --check-prefix=CHECK-O2 %s
+; RUN: lld-link /out:%t2a.exe /entry:main /subsystem:console /debug %t.obj
+; RUN: llvm-nm %t2a.exe | FileCheck --check-prefix=CHECK-O2 %s
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+; 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/COFF/lto-parallel.ll b/test/COFF/lto-parallel.ll
new file mode 100644
index 000000000000..2303797019a5
--- /dev/null
+++ b/test/COFF/lto-parallel.ll
@@ -0,0 +1,20 @@
+; RUN: llvm-as -o %t.obj %s
+; RUN: lld-link /out:%t.exe /entry:foo /include:bar /opt:lldltojobs=2 /subsystem:console /lldmap:%t.map %t.obj
+; RUN: FileCheck %s < %t.map
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+; CHECK: <lto object>:
+; CHECK: foo
+define void @foo() {
+ call void @bar()
+ ret void
+}
+
+; CHECK: <lto object>:
+; CHECK: bar
+define void @bar() {
+ call void @foo()
+ ret void
+}
diff --git a/test/COFF/lto.ll b/test/COFF/lto.ll
new file mode 100644
index 000000000000..b8f8d7063343
--- /dev/null
+++ b/test/COFF/lto.ll
@@ -0,0 +1,130 @@
+; RUN: llvm-as -o %T/main.lto.obj %s
+; RUN: llvm-as -o %T/foo.lto.obj %S/Inputs/lto-dep.ll
+; RUN: rm -f %T/foo.lto.lib
+; RUN: llvm-ar cru %T/foo.lto.lib %T/foo.lto.obj
+
+; RUN: llc -filetype=obj -o %T/main.obj %s
+; RUN: llc -filetype=obj -o %T/foo.obj %S/Inputs/lto-dep.ll
+; RUN: rm -f %T/foo.lib
+; RUN: llvm-ar cru %T/foo.lib %T/foo.obj
+
+; RUN: lld-link /out:%T/main.exe /entry:main /include:f2 /subsystem:console %T/main.lto.obj %T/foo.lto.obj
+; RUN: llvm-readobj -file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-11 %s
+; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-11 %s
+; RUN: lld-link /out:%T/main.exe /entry:main /include:f2 /subsystem:console %T/main.lto.obj %T/foo.lto.lib /verbose 2>&1 | FileCheck -check-prefix=VERBOSE %s
+; RUN: llvm-readobj -file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-11 %s
+; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-11 %s
+
+; RUN: lld-link /out:%T/main.exe /entry:main /subsystem:console %T/main.obj %T/foo.lto.obj
+; RUN: llvm-readobj -file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-01 %s
+; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-01 %s
+; RUN: lld-link /out:%T/main.exe /entry:main /subsystem:console %T/main.obj %T/foo.lto.lib
+; RUN: llvm-readobj -file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-01 %s
+; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-01 %s
+
+; RUN: lld-link /out:%T/main.exe /entry:main /subsystem:console %T/main.lto.obj %T/foo.obj
+; RUN: llvm-readobj -file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-10 %s
+; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-10 %s
+; RUN: lld-link /out:%T/main.exe /entry:main /subsystem:console %T/main.lto.obj %T/foo.lib
+; RUN: llvm-readobj -file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-10 %s
+; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-10 %s
+
+; VERBOSE: foo.lto.lib({{.*}}foo.lto.obj)
+
+; HEADERS-11: AddressOfEntryPoint: 0x1000
+; TEXT-11: Disassembly of section .text:
+; TEXT-11-NEXT: .text:
+; TEXT-11-NEXT: xorl %eax, %eax
+; TEXT-11-NEXT: retq
+; TEXT-11-NEXT: int3
+; TEXT-11-NEXT: int3
+; TEXT-11-NEXT: int3
+; TEXT-11-NEXT: int3
+; TEXT-11-NEXT: int3
+; TEXT-11-NEXT: int3
+; TEXT-11-NEXT: int3
+; TEXT-11-NEXT: int3
+; TEXT-11-NEXT: int3
+; TEXT-11-NEXT: int3
+; TEXT-11-NEXT: int3
+; TEXT-11-NEXT: int3
+; TEXT-11-NEXT: int3
+; TEXT-11-NEXT: movl $2, %eax
+; TEXT-11-NEXT: retq
+
+; HEADERS-01: AddressOfEntryPoint: 0x2000
+; TEXT-01: Disassembly of section .text:
+; TEXT-01-NEXT: .text:
+; TEXT-01-NEXT: subq $40, %rsp
+; TEXT-01-NEXT: callq 23
+; TEXT-01-NEXT: xorl %eax, %eax
+; TEXT-01-NEXT: addq $40, %rsp
+; TEXT-01-NEXT: retq
+; TEXT-01-NEXT: retq
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: int3
+; TEXT-01-NEXT: retq
+
+; HEADERS-10: AddressOfEntryPoint: 0x2020
+; TEXT-10: Disassembly of section .text:
+; TEXT-10-NEXT: .text:
+; TEXT-10-NEXT: retq
+; TEXT-10-NEXT: nopw %cs:(%rax,%rax)
+; TEXT-10-NEXT: retq
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: int3
+; TEXT-10-NEXT: subq $40, %rsp
+; TEXT-10-NEXT: callq -41
+; TEXT-10-NEXT: xorl %eax, %eax
+; TEXT-10-NEXT: addq $40, %rsp
+; TEXT-10-NEXT: retq
+
+target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
+target triple = "x86_64-pc-windows-msvc"
+
+define i32 @main() {
+ call void @foo()
+ ret i32 0
+}
+
+declare void @foo()
+
+$f1 = comdat any
+define i32 @f1() comdat($f1) {
+ ret i32 1
+}
+
+$f2 = comdat any
+define i32 @f2() comdat($f2) {
+ ret i32 2
+}
+
+define internal void @internal() {
+ ret void
+}
diff --git a/test/COFF/machine.test b/test/COFF/machine.test
new file mode 100644
index 000000000000..847018f20fbd
--- /dev/null
+++ b/test/COFF/machine.test
@@ -0,0 +1,30 @@
+# RUN: yaml2obj %p/Inputs/machine-x64.yaml > %t.obj
+# RUN: lld-link /entry:main /subsystem:console /out:%t.exe %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=AMD64 %s
+# RUN: lld-link /entry:main /subsystem:console /machine:x64 \
+# RUN: /out:%t.exe %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=AMD64 %s
+
+AMD64: Machine: IMAGE_FILE_MACHINE_AMD64
+
+# RUN: yaml2obj %p/Inputs/machine-x86.yaml > %t.obj
+# RUN: lld-link /entry:main /subsystem:console /out:%t.exe %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=I386 %s
+# RUN: lld-link /entry:main /subsystem:console /machine:x86 \
+# RUN: /out:%t.exe %t.obj /fixed
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=I386 %s
+
+I386: Machine: IMAGE_FILE_MACHINE_I386
+
+# RUN: yaml2obj %p/Inputs/machine-x64.yaml > %t.obj
+# RUN: not lld-link /entry:main /subsystem:console /machine:x86 \
+# RUN: /out:%t.exe %t.obj /fixed >& %t.log
+# RUN: FileCheck -check-prefix=INCOMPAT %s < %t.log
+
+# RUN: yaml2obj %p/Inputs/machine-x86.yaml > %t1.obj
+# RUN: sed -e s/main/foo/ %p/Inputs/machine-x64.yaml | yaml2obj > %t2.obj
+# RUN: not lld-link /entry:main /subsystem:console /out:%t.exe \
+# RUN: %t1.obj %t2.obj >& %t.log
+# RUN: FileCheck -check-prefix=INCOMPAT %s < %t.log
+
+INCOMPAT: .obj: machine type x64 conflicts with x86
diff --git a/test/COFF/manifest.test b/test/COFF/manifest.test
new file mode 100644
index 000000000000..33e80e75a4d5
--- /dev/null
+++ b/test/COFF/manifest.test
@@ -0,0 +1,61 @@
+# RUN: yaml2obj %p/Inputs/ret42.yaml > %t.obj
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: FileCheck -check-prefix=MANIFEST %s < %t.exe.manifest
+
+MANIFEST: <?xml version="1.0" standalone="yes"?>
+MANIFEST: <assembly xmlns="urn:schemas-microsoft-com:asm.v1"
+MANIFEST: manifestVersion="1.0">
+MANIFEST: <trustInfo>
+MANIFEST: <security>
+MANIFEST: <requestedPrivileges>
+MANIFEST: <requestedExecutionLevel level='asInvoker' uiAccess='false'/>
+MANIFEST: </requestedPrivileges>
+MANIFEST: </security>
+MANIFEST: </trustInfo>
+MANIFEST: </assembly>
+
+# RUN: lld-link /out:%t.exe /entry:main \
+# RUN: /manifestuac:"level='requireAdministrator' uiAccess='true'" %t.obj
+# RUN: FileCheck -check-prefix=UAC %s < %t.exe.manifest
+
+UAC: <?xml version="1.0" standalone="yes"?>
+UAC: <assembly xmlns="urn:schemas-microsoft-com:asm.v1"
+UAC: manifestVersion="1.0">
+UAC: <trustInfo>
+UAC: <security>
+UAC: <requestedPrivileges>
+UAC: <requestedExecutionLevel level='requireAdministrator' uiAccess='true'/>
+UAC: </requestedPrivileges>
+UAC: </security>
+UAC: </trustInfo>
+UAC: </assembly>
+
+# RUN: lld-link /out:%t.exe /entry:main \
+# RUN: /manifestdependency:"foo='bar'" %t.obj
+# RUN: FileCheck -check-prefix=DEPENDENCY %s < %t.exe.manifest
+
+DEPENDENCY: <?xml version="1.0" standalone="yes"?>
+DEPENDENCY: <assembly xmlns="urn:schemas-microsoft-com:asm.v1"
+DEPENDENCY: manifestVersion="1.0">
+DEPENDENCY: <trustInfo>
+DEPENDENCY: <security>
+DEPENDENCY: <requestedPrivileges>
+DEPENDENCY: <requestedExecutionLevel level='asInvoker' uiAccess='false'/>
+DEPENDENCY: </requestedPrivileges>
+DEPENDENCY: </security>
+DEPENDENCY: </trustInfo>
+DEPENDENCY: <dependency>
+DEPENDENCY: <dependentAssembly>
+DEPENDENCY: <assemblyIdentity foo='bar' />
+DEPENDENCY: </dependentAssembly>
+DEPENDENCY: </dependency>
+DEPENDENCY: </assembly>
+
+# RUN: lld-link /out:%t.exe /entry:main /manifestuac:no %t.obj
+# RUN: FileCheck -check-prefix=NOUAC %s < %t.exe.manifest
+
+NOUAC: <?xml version="1.0" standalone="yes"?>
+NOUAC: <assembly xmlns="urn:schemas-microsoft-com:asm.v1"
+NOUAC: manifestVersion="1.0">
+NOUAC: </assembly>
diff --git a/test/COFF/merge.test b/test/COFF/merge.test
new file mode 100644
index 000000000000..45ab4efe37a8
--- /dev/null
+++ b/test/COFF/merge.test
@@ -0,0 +1,53 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \
+# RUN: /merge:.foo=.abc /merge:.bar=.def %t.obj /debug
+# RUN: llvm-readobj -sections %t.exe | FileCheck %s
+
+# CHECK: Name: .def
+# CHECK: Name: .abc
+
+---
+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
+ - Name: .bar
+ 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: .bar
+ Value: 0
+ SectionNumber: 2
+ 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/nodefaultlib.test b/test/COFF/nodefaultlib.test
new file mode 100644
index 000000000000..867dc8f18e78
--- /dev/null
+++ b/test/COFF/nodefaultlib.test
@@ -0,0 +1,30 @@
+# RUN: cp %p/Inputs/hello64.obj %T
+# RUN: cp %p/Inputs/std64.lib %T
+
+# RUN: not lld-link /out:%t.exe /entry:main /subsystem:console \
+# RUN: hello64.obj /defaultlib:std64.lib >& %t.log
+# RUN: FileCheck -check-prefix=CHECK1 %s < %t.log
+
+# RUN: not lld-link /out:%t.exe /entry:main /subsystem:console \
+# RUN: hello64 /defaultlib:std64.lib >& %t.log
+# RUN: FileCheck -check-prefix=CHECK2 %s < %t.log
+
+# RUN: lld-link /libpath:%T /out:%t.exe /entry:main \
+# RUN: /subsystem:console hello64.obj /defaultlib:std64.lib \
+# RUN: /nodefaultlib:std64.lib >& %t.log || true
+# RUN: FileCheck -check-prefix=CHECK3 %s < %t.log
+
+# RUN: lld-link /libpath:%T /out:%t.exe /entry:main \
+# RUN: /subsystem:console hello64.obj /defaultlib:std64 \
+# RUN: /nodefaultlib:std64.lib >& %t.log || true
+# RUN: FileCheck -check-prefix=CHECK3 %s < %t.log
+
+CHECK1: hello64.obj: {{[Nn]}}o such file or directory
+CHECK2: hello64: {{[Nn]}}o such file or directory
+CHECK3: hello64.obj: undefined symbol: MessageBoxA
+
+# RUN: lld-link /libpath:%T /out:%t.exe /entry:main \
+# RUN: /subsystem:console hello64.obj /defaultlib:std64.lib
+
+# RUN: env LIB=%T lld-link /out:%t.exe /entry:main \
+# RUN: /subsystem:console hello64.obj /defaultlib:std64.lib
diff --git a/test/COFF/noentry.test b/test/COFF/noentry.test
new file mode 100644
index 000000000000..80f387fe03c8
--- /dev/null
+++ b/test/COFF/noentry.test
@@ -0,0 +1,11 @@
+# REQUIRES: winres
+# REQUIRES: winlib
+
+# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj
+# RUN: lld-link /out:%t.dll /dll %t.obj
+# RUN: llvm-readobj -file-headers %t.dll | FileCheck -check-prefix=ENTRY %s
+# RUN: lld-link /out:%t.dll /dll /noentry %t.obj
+# RUN: llvm-readobj -file-headers %t.dll | FileCheck -check-prefix=NOENTRY %s
+
+ENTRY: AddressOfEntryPoint: 0x1000
+NOENTRY: AddressOfEntryPoint: 0x0
diff --git a/test/COFF/opt.test b/test/COFF/opt.test
new file mode 100644
index 000000000000..652734b2f68a
--- /dev/null
+++ b/test/COFF/opt.test
@@ -0,0 +1,69 @@
+# RUN: yaml2obj < %s > %t.obj
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj \
+# RUN: /verbose >& %t.log
+### FileCheck doesn't like empty input, so write something.
+# RUN: echo dummy >> %t.log
+# RUN: FileCheck -check-prefix=CHECK1 %s < %t.log
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj \
+# RUN: /verbose /opt:noref >& %t.log
+# RUN: echo dummy >> %t.log
+# RUN: FileCheck -check-prefix=CHECK2 %s < %t.log
+
+# CHECK1: Discarded unused
+# CHECK2-NOT: Discarded unused
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: '.text$mn'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B82A000000C3
+ - Name: '.text$mn'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B82A000000C3
+symbols:
+ - Name: '.text$mn'
+ 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
+ Selection: IMAGE_COMDAT_SELECT_ANY
+ - Name: '.text$mn'
+ Value: 0
+ SectionNumber: 2
+ 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
+ Selection: IMAGE_COMDAT_SELECT_ANY
+ - Name: main
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: unused
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/options.test b/test/COFF/options.test
new file mode 100644
index 000000000000..39f944beddbc
--- /dev/null
+++ b/test/COFF/options.test
@@ -0,0 +1,51 @@
+# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=BIND %s
+# RUN: lld-link /allowbind /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=BIND %s
+BIND-NOT: IMAGE_DLL_CHARACTERISTICS_NO_BIND
+
+# RUN: lld-link /allowbind:no /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NOBIND %s
+NOBIND: IMAGE_DLL_CHARACTERISTICS_NO_BIND
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=ISO %s
+# RUN: lld-link /allowisolation /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=ISO %s
+ISO-NOT: IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION
+
+# RUN: lld-link /allowisolation:no /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NOISO %s
+NOISO: IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=ENT %s
+# RUN: lld-link /out:%t.exe /entry:main /highentropyva %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=ENT %s
+ENT: IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA
+
+# RUN: lld-link /out:%t.exe /highentropyva:no /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NOENT %s
+NOENT-NOT: IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NXCOMPAT %s
+# RUN: lld-link /out:%t.exe /entry:main /nxcompat %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NXCOMPAT %s
+NXCOMPAT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT
+
+# RUN: lld-link /out:%t.exe /nxcompat:no /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NONXCOMPAT %s
+NONXCOMPAT-NOT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=TSAWARE %s
+# RUN: lld-link /out:%t.exe /entry:main /tsaware %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=TSAWARE %s
+TSAWARE: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE
+
+# RUN: lld-link /tsaware:no /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NOTSAWARE %s
+NOTSAWARE-NOT: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE
diff --git a/test/COFF/order.test b/test/COFF/order.test
new file mode 100644
index 000000000000..6a0cee8a32ea
--- /dev/null
+++ b/test/COFF/order.test
@@ -0,0 +1,15 @@
+# RUN: yaml2obj < %p/Inputs/include1a.yaml > %t1.obj
+# RUN: yaml2obj < %p/Inputs/include1b.yaml > %t2.obj
+# RUN: yaml2obj < %p/Inputs/include1c.yaml > %t3.obj
+# RUN: rm -f %t2.lib %t3.lib
+# RUN: llvm-ar cru %t2.lib %t2.obj
+# RUN: llvm-ar cru %t3.lib %t3.obj
+# RUN: lld-link /out:%t.exe /entry:main \
+# RUN: %t1.obj %t2.lib %t3.obj %t3.lib /verbose >& %t.log
+# RUN: FileCheck %s < %t.log
+
+CHECK: order.test.tmp1.obj
+CHECK: order.test.tmp3.obj
+CHECK: order.test.tmp2.lib
+CHECK: order.test.tmp3.lib
+CHECK: order.test.tmp2.lib(order.test.tmp2.obj) for foo
diff --git a/test/COFF/out.test b/test/COFF/out.test
new file mode 100644
index 000000000000..a216fc9add8f
--- /dev/null
+++ b/test/COFF/out.test
@@ -0,0 +1,16 @@
+# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
+
+# RUN: mkdir -p %T/out/tmp
+# RUN: cp %t.obj %T/out/out1.obj
+# RUN: cp %t.obj %T/out/tmp/out2
+# RUN: cp %t.obj %T/out/tmp/out3.xyz
+
+# 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: llvm-readobj out1.exe | FileCheck %s
+# RUN: llvm-readobj out2.exe | FileCheck %s
+# RUN: llvm-readobj out3.exe | FileCheck %s
+
+CHECK: File:
diff --git a/test/COFF/reloc-arm.test b/test/COFF/reloc-arm.test
new file mode 100644
index 000000000000..b44c0822bb7f
--- /dev/null
+++ b/test/COFF/reloc-arm.test
@@ -0,0 +1,71 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: llvm-objdump -s %t.exe | FileCheck %s
+
+# CHECK: .text:
+# CHECK: 402000 01104000 00000000 00000000 00000000
+# CHECK: 402010 01100000 00000000 00000000 00000000
+# CHECK: 402020 01000100 00004000 00000000 00000000
+# CHECK: 402030 fe07e62f 00000000 00000000 00000000
+# CHECK: 402040 3e04de2f 00000000 00000000 00000000
+# CHECK: 402050 fe07d62f 00000000 00000000 00000000
+# CHECK: 402060 00000000 00000000 00000000 00000000
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_ARMNT
+ Characteristics: []
+sections:
+ - Name: .aaa
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4096
+ SectionData: 0000000000000000
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4096
+ SectionData: 00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: foo
+ Type: 1 # IMAGE_REL_ARM_ADDR32
+ - VirtualAddress: 16
+ SymbolName: foo
+ Type: 2 # IMAGE_REL_ARM_ADDR32NB
+ - VirtualAddress: 32
+ SymbolName: foo
+ Type: 17 # IMAGE_REL_AMD64_MOV32T
+ - VirtualAddress: 48
+ SymbolName: foo
+ Type: 20 # IMAGE_REL_AMD64_BRANCH24T
+ - VirtualAddress: 64
+ SymbolName: foo
+ Type: 18 # IMAGE_REL_ARM_BRANCH20T
+ - VirtualAddress: 80
+ SymbolName: foo
+ Type: 21 # IMAGE_REL_AMD64_BLX23T
+symbols:
+ - Name: .aaa
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: .text
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: main
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: foo
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/reloc-x64.test b/test/COFF/reloc-x64.test
new file mode 100644
index 000000000000..5513f2eaa647
--- /dev/null
+++ b/test/COFF/reloc-x64.test
@@ -0,0 +1,102 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: llvm-objdump -d %t.exe | FileCheck %s
+
+# CHECK: .text:
+# CHECK: 1000: a1 03 20 00 40 00 00 00 00
+# CHECK: 1009: a1 03 20 00 40 01 00 00 00
+# CHECK: 1012: a1 03 20 00 00 00 00 00 00
+# CHECK: 101b: a1 e3 0f 00 00 00 00 00 00
+# CHECK: 1024: a1 d9 0f 00 00 00 00 00 00
+# CHECK: 102d: a1 cf 0f 00 00 00 00 00 00
+# CHECK: 1036: a1 c5 0f 00 00 00 00 00 00
+# CHECK: 103f: a1 bb 0f 00 00 00 00 00 00
+# CHECK: 1048: a1 b1 0f 00 00 00 00 00 00
+# CHECK: 1051: a1 02 00 00 00 00 00 00 00
+# CHECK: 105a: a1 03 00 00 00 00 00 00 00
+
+---
+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: A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000A10000000000000000
+ Relocations:
+ - VirtualAddress: 1
+ SymbolName: foo
+ Type: IMAGE_REL_AMD64_ADDR32
+ - VirtualAddress: 10
+ SymbolName: foo
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 19
+ SymbolName: foo
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 28
+ SymbolName: foo
+ Type: IMAGE_REL_AMD64_REL32
+ - VirtualAddress: 37
+ SymbolName: foo
+ Type: IMAGE_REL_AMD64_REL32_1
+ - VirtualAddress: 46
+ SymbolName: foo
+ Type: IMAGE_REL_AMD64_REL32_2
+ - VirtualAddress: 55
+ SymbolName: foo
+ Type: IMAGE_REL_AMD64_REL32_3
+ - VirtualAddress: 64
+ SymbolName: foo
+ Type: IMAGE_REL_AMD64_REL32_4
+ - VirtualAddress: 73
+ SymbolName: foo
+ Type: IMAGE_REL_AMD64_REL32_5
+ - VirtualAddress: 82
+ SymbolName: foo
+ Type: IMAGE_REL_AMD64_SECTION
+ - VirtualAddress: 91
+ SymbolName: foo
+ Type: IMAGE_REL_AMD64_SECREL
+ - Name: .zzz
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ 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: 6
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: .zzz
+ Value: 0
+ SectionNumber: 2
+ 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: foo
+ Value: 3
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/reloc-x86.test b/test/COFF/reloc-x86.test
new file mode 100644
index 000000000000..d189ca02f015
--- /dev/null
+++ b/test/COFF/reloc-x86.test
@@ -0,0 +1,82 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /out:%t.exe /entry:main /base:0x400000 %t.obj
+# RUN: llvm-objdump -d %t.exe | FileCheck %s
+
+# CHECK: .text:
+# CHECK: 1000: a1 00 00 00 00
+# CHECK: 1005: a1 03 20 40 00
+# CHECK: 100a: a1 03 20 00 00
+# CHECK: 100f: a1 ef 0f 00 00
+# CHECK: 1014: a1 00 00 02 00
+# CHECK: 1019: a1 03 00 00 00
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_I386
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4096
+ SectionData: A100000000A100000000A100000000A100000000A100000000A100000000
+ Relocations:
+ - VirtualAddress: 1
+ SymbolName: _foo
+ Type: IMAGE_REL_I386_ABSOLUTE
+ - VirtualAddress: 6
+ SymbolName: _foo
+ Type: IMAGE_REL_I386_DIR32
+ - VirtualAddress: 11
+ SymbolName: _foo
+ Type: IMAGE_REL_I386_DIR32NB
+ - VirtualAddress: 16
+ SymbolName: _foo
+ Type: IMAGE_REL_I386_REL32
+ - VirtualAddress: 23
+ SymbolName: _foo
+ Type: IMAGE_REL_I386_SECTION
+ - VirtualAddress: 26
+ SymbolName: _foo
+ Type: IMAGE_REL_I386_SECREL
+ - Name: .zzz
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ 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: 6
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: .zzz
+ Value: 0
+ SectionNumber: 2
+ 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: _foo
+ Value: 3
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/resource.test b/test/COFF/resource.test
new file mode 100644
index 000000000000..7b6090d89f65
--- /dev/null
+++ b/test/COFF/resource.test
@@ -0,0 +1,14 @@
+# REQUIRES: winres
+
+# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
+# RUN: lld-link /out:%t.exe /entry:main %t.obj %p/Inputs/resource.res
+
+# Check if the binary contains UTF-16LE string "Hello" copied from resource.res.
+# RUN: FileCheck --check-prefix=EXE %s < %t.exe
+
+EXE: {{H.e.l.l.o}}
+
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck --check-prefix=HEADER %s
+
+HEADER: ResourceTableRVA: 0x1000
+HEADER: ResourceTableSize: 0x88
diff --git a/test/COFF/responsefile.test b/test/COFF/responsefile.test
new file mode 100644
index 000000000000..fd4d221c20dc
--- /dev/null
+++ b/test/COFF/responsefile.test
@@ -0,0 +1,7 @@
+# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
+
+# RUN: echo /out:%t.exe /entry:main %t.obj > %t.rsp
+# RUN: lld-link @%t.rsp /heap:0x3000
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
+
+CHECK: SizeOfHeapReserve: 12288
diff --git a/test/COFF/safeseh.test b/test/COFF/safeseh.test
new file mode 100644
index 000000000000..f8308a6131b6
--- /dev/null
+++ b/test/COFF/safeseh.test
@@ -0,0 +1,51 @@
+# RUN: sed s/FEAT_VALUE/1/ %s | yaml2obj > %t.obj
+# RUN: lld-link /out:%t.exe /subsystem:console /entry:main /safeseh %t.obj
+
+# RUN: sed s/FEAT_VALUE/0/ %s | yaml2obj > %t.obj
+# RUN: not lld-link /out:%t.exe /subsystem:console /entry:main \
+# RUN: /safeseh %t.obj >& %t.log
+# RUN: FileCheck %s < %t.log
+
+# CHECK: /safeseh: {{.*}} is not compatible with SEH
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_I386
+ Characteristics: [ ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 1
+ SectionData: 0000000000000000
+symbols:
+ - Name: '@comp.id'
+ Value: 14766605
+ SectionNumber: 65535
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: '@feat.00'
+ Value: FEAT_VALUE
+ SectionNumber: 65535
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - 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_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/seh.test b/test/COFF/seh.test
new file mode 100644
index 000000000000..b3ff66cf09b8
--- /dev/null
+++ b/test/COFF/seh.test
@@ -0,0 +1,70 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /out:%t.exe /subsystem:console /entry:main %t.obj
+# RUN: llvm-objdump -s %t.exe | FileCheck %s
+
+# CHECK: Contents of section .rdata:
+# CHECK: 1000 00200000 02200000
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_I386
+ Characteristics: [ ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 1
+ SectionData: 0000000000000000
+ - Name: .sxdata
+ Characteristics: [ IMAGE_SCN_LNK_INFO ]
+ Alignment: 4
+ SectionData: 0600000007000000
+symbols:
+ - Name: '@comp.id'
+ Value: 14766605
+ SectionNumber: 65535
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: '@feat.00'
+ Value: 2147484049
+ SectionNumber: 65535
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - 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: .sxdata
+ Value: 0
+ SectionNumber: 2
+ 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_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: _foo
+ Value: 2
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/sort-debug.test b/test/COFF/sort-debug.test
new file mode 100644
index 000000000000..c099f2dc19b1
--- /dev/null
+++ b/test/COFF/sort-debug.test
@@ -0,0 +1,296 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /debug /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -sections %t.exe | FileCheck %s
+
+# CHECK: Name: .text
+# CHECK: Name: .debug_abbrev
+# CHECK: Name: .debug_info
+# CHECK: Name: .debug_line
+# CHECK: Name: .debug_pubnames
+# CHECK: Name: .debug_pubtypes
+# CHECK: Name: .reloc
+
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_I386
+ Characteristics: [ ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 508D0500000000C70424000000005AC3
+ Relocations:
+ - VirtualAddress: 3
+ SymbolName: '?x@@3HA'
+ Type: IMAGE_REL_I386_DIR32
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: ''
+ - Name: .bss
+ Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: ''
+ - Name: '.debug$S'
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 1
+ SectionData: 04000000F1000000300000002A00471100000000000000000000000010000000000000000000000000000000000000000000006D61696E0002004F11F200000024000000000000000000010010000000000000000100000018000000000000000100000000000000F4000000080000000100000000000000F30000003C000000005C7573725C6C6F63616C5C676F6F676C655C686F6D655C6D616A6E656D65725C6C6C766D5C7372635C746F6F6C735C6C6C645C3C737464696E3E00
+ Relocations:
+ - VirtualAddress: 44
+ SymbolName: _main
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 48
+ SymbolName: _main
+ Type: IMAGE_REL_I386_SECTION
+ - VirtualAddress: 68
+ SymbolName: _main
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 72
+ SymbolName: _main
+ Type: IMAGE_REL_I386_SECTION
+ - Name: .debug_str
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 1
+ SectionData: ''
+ - Name: .debug_loc
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 1
+ SectionData: ''
+ - Name: .debug_abbrev
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 1
+ SectionData: 011101250E1305030E10171B0E110112060000023400030E49133F193A0B3B0B02186E0E0000032400030E3E0B0B0B0000042E0011011206E77F194018030E3A0B3B0B49133F19000000
+ - Name: .debug_info
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 1
+ SectionData: 54000000040000000000040100000000040037000000000000003F000000000000001000000002720000003B0000000101050300000000780000000374000000050404000000001000000001548000000001013B00000000
+ Relocations:
+ - VirtualAddress: 6
+ SymbolName: .debug_abbrev
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 12
+ SymbolName: .debug_str
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 18
+ SymbolName: .debug_str
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 22
+ SymbolName: .debug_line
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 26
+ SymbolName: .debug_str
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 30
+ SymbolName: .text
+ Type: IMAGE_REL_I386_DIR32
+ - VirtualAddress: 39
+ SymbolName: .debug_str
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 51
+ SymbolName: '?x@@3HA'
+ Type: IMAGE_REL_I386_DIR32
+ - VirtualAddress: 55
+ SymbolName: .debug_str
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 60
+ SymbolName: .debug_str
+ Type: IMAGE_REL_I386_SECREL
+ - VirtualAddress: 67
+ SymbolName: .text
+ Type: IMAGE_REL_I386_DIR32
+ - VirtualAddress: 77
+ SymbolName: .debug_str
+ Type: IMAGE_REL_I386_SECREL
+ - Name: .debug_ranges
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 1
+ SectionData: ''
+ - Name: .debug_pubnames
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 1
+ SectionData: 1D00000002000000000058000000420000006D61696E0026000000780000000000
+ Relocations:
+ - VirtualAddress: 6
+ SymbolName: .debug_info
+ Type: IMAGE_REL_I386_SECREL
+ - Name: .debug_pubtypes
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 1
+ SectionData: 16000000020000000000580000003B000000696E740000000000
+ Relocations:
+ - VirtualAddress: 6
+ SymbolName: .debug_info
+ Type: IMAGE_REL_I386_SECREL
+ - Name: .debug_line
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
+ Alignment: 1
+ SectionData: 3300000002001E0000000101FB0E0D000101010100000001000001003C737464696E3E000000000000050200000000010AD60202000101
+ Relocations:
+ - VirtualAddress: 43
+ SymbolName: .text
+ Type: IMAGE_REL_I386_DIR32
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 16
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 1
+ - Name: .data
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 0
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 2
+ - Name: .bss
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 4
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 3
+ - Name: '.debug$S'
+ Value: 0
+ SectionNumber: 4
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 188
+ NumberOfRelocations: 4
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 4
+ - Name: .debug_str
+ Value: 0
+ SectionNumber: 5
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 133
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 5
+ - Name: .debug_loc
+ Value: 0
+ SectionNumber: 6
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 0
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 6
+ - Name: .debug_abbrev
+ Value: 0
+ SectionNumber: 7
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 74
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 7
+ - Name: .debug_info
+ Value: 0
+ SectionNumber: 8
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 88
+ NumberOfRelocations: 12
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 8
+ - Name: .debug_ranges
+ Value: 0
+ SectionNumber: 9
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 0
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 9
+ - Name: .debug_pubnames
+ Value: 0
+ SectionNumber: 10
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 33
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 10
+ - Name: .debug_pubtypes
+ Value: 0
+ SectionNumber: 11
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 26
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 11
+ - Name: .debug_line
+ Value: 0
+ SectionNumber: 12
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 55
+ NumberOfRelocations: 1
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 12
+ - Name: '@feat.00'
+ Value: 1
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: _main
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: '?x@@3HA'
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/stack.test b/test/COFF/stack.test
new file mode 100644
index 000000000000..df066b16c20d
--- /dev/null
+++ b/test/COFF/stack.test
@@ -0,0 +1,25 @@
+# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=DEFAULT %s
+
+DEFAULT: SizeOfStackReserve: 1048576
+DEFAULT: SizeOfStackCommit: 4096
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj /stack:0x3000
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s
+# RUN: echo "STACKSIZE 12288" > %t.def
+# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s
+
+CHECK1: SizeOfStackReserve: 12288
+CHECK1: SizeOfStackCommit: 4096
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj /stack:0x5000,0x3000
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s
+# RUN: echo "STACKSIZE 20480,12288" > %t.def
+# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s
+
+CHECK2: SizeOfStackReserve: 20480
+CHECK2: SizeOfStackCommit: 12288
diff --git a/test/COFF/subsystem-inference.test b/test/COFF/subsystem-inference.test
new file mode 100644
index 000000000000..da4f573c2e02
--- /dev/null
+++ b/test/COFF/subsystem-inference.test
@@ -0,0 +1,74 @@
+# RUN: sed -e s/ENTRYNAME/main/ %s | yaml2obj > %t.obj
+# RUN: lld-link /out:%t.exe %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=MAIN %s
+
+# RUN: sed s/ENTRYNAME/wmain/ %s | yaml2obj > %t.obj
+# RUN: lld-link /out:%t.exe %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=WMAIN %s
+
+# RUN: sed s/ENTRYNAME/WinMain/ %s | yaml2obj > %t.obj
+# RUN: lld-link /out:%t.exe %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=WINMAIN %s
+
+# RUN: sed s/ENTRYNAME/wWinMain/ %s | yaml2obj > %t.obj
+# RUN: lld-link /out:%t.exe %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=WWINMAIN %s
+
+# MAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
+# WMAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
+# WINMAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI
+# WWINMAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: B82A000000C3
+symbols:
+ - Name: .text
+ 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: ENTRYNAME
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: mainCRTStartup
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: wmainCRTStartup
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: WinMainCRTStartup
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: wWinMainCRTStartup
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/subsystem.test b/test/COFF/subsystem.test
new file mode 100644
index 000000000000..5e72706dd1cb
--- /dev/null
+++ b/test/COFF/subsystem.test
@@ -0,0 +1,19 @@
+# RUN: lld-link /entry:main /out:%t.exe /subsystem:windows \
+# RUN: %p/Inputs/ret42.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s
+
+CHECK1: MajorOperatingSystemVersion: 6
+CHECK1: MinorOperatingSystemVersion: 0
+CHECK1: MajorSubsystemVersion: 6
+CHECK1: MinorSubsystemVersion: 0
+CHECK1: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI
+
+# RUN: lld-link /entry:main /out:%t.exe /subsystem:windows,8.9 \
+# RUN: %p/Inputs/ret42.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s
+
+CHECK2: MajorOperatingSystemVersion: 8
+CHECK2: MinorOperatingSystemVersion: 9
+CHECK2: MajorSubsystemVersion: 8
+CHECK2: MinorSubsystemVersion: 9
+CHECK2: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI
diff --git a/test/COFF/symtab.test b/test/COFF/symtab.test
new file mode 100644
index 000000000000..14ae9a3e816c
--- /dev/null
+++ b/test/COFF/symtab.test
@@ -0,0 +1,254 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /debug /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib
+# RUN: llvm-readobj -symbols %t.exe | FileCheck %s
+# RUN: lld-link /debug /opt:noref /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib
+# RUN: llvm-readobj -symbols %t.exe | FileCheck %s
+
+# RUN: lld-link /debug /nosymtab /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib
+# RUN: llvm-readobj -symbols %t.exe | FileCheck -check-prefix=NO %s
+
+# CHECK: Symbols [
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: .text
+# CHECK-NEXT: Value: 0
+# CHECK-NEXT: Section: .text (2)
+# CHECK-NEXT: BaseType: Null (0x0)
+# CHECK-NEXT: ComplexType: Null (0x0)
+# CHECK-NEXT: StorageClass: Static (0x3)
+# CHECK-NEXT: AuxSymbolCount: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: .text2
+# CHECK-NEXT: Value: 0
+# CHECK-NEXT: Section: .text (2)
+# CHECK-NEXT: BaseType: Null (0x0)
+# CHECK-NEXT: ComplexType: Null (0x0)
+# CHECK-NEXT: StorageClass: Static (0x3)
+# CHECK-NEXT: AuxSymbolCount: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: .data
+# CHECK-NEXT: Value: 0
+# CHECK-NEXT: Section: .data (1)
+# CHECK-NEXT: BaseType: Null (0x0)
+# CHECK-NEXT: ComplexType: Null (0x0)
+# CHECK-NEXT: StorageClass: Static (0x3)
+# CHECK-NEXT: AuxSymbolCount: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: message
+# CHECK-NEXT: Value: 6
+# CHECK-NEXT: Section: .text2 (3)
+# CHECK-NEXT: BaseType: Null (0x0)
+# CHECK-NEXT: ComplexType: Null (0x0)
+# CHECK-NEXT: StorageClass: Static (0x3)
+# CHECK-NEXT: AuxSymbolCount: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: main
+# CHECK-NEXT: Value: 0
+# CHECK-NEXT: Section: .text (2)
+# CHECK-NEXT: BaseType: Null (0x0)
+# CHECK-NEXT: ComplexType: Null (0x0)
+# CHECK-NEXT: StorageClass: External (0x2)
+# CHECK-NEXT: AuxSymbolCount: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: caption
+# CHECK-NEXT: Value: 0
+# CHECK-NEXT: Section: .text2 (3)
+# CHECK-NEXT: BaseType: Null (0x0)
+# CHECK-NEXT: ComplexType: Null (0x0)
+# CHECK-NEXT: StorageClass: Static (0x3)
+# CHECK-NEXT: AuxSymbolCount: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: abs_symbol
+# CHECK-NEXT: Value: 2662186735
+# CHECK-NEXT: Section: IMAGE_SYM_ABSOLUTE (-1)
+# CHECK-NEXT: BaseType: Null (0x0)
+# CHECK-NEXT: ComplexType: Null (0x0)
+# CHECK-NEXT: StorageClass: External (0x2)
+# CHECK-NEXT: AuxSymbolCount: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: __imp_ExitProcess
+# CHECK-NEXT: Value: 64
+# CHECK-NEXT: Section: .idata (4)
+# CHECK-NEXT: BaseType: Null (0x0)
+# CHECK-NEXT: ComplexType: Null (0x0)
+# CHECK-NEXT: StorageClass: External (0x2)
+# CHECK-NEXT: AuxSymbolCount: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: ExitProcess
+# CHECK-NEXT: Value: 64
+# CHECK-NEXT: Section: .text (2)
+# CHECK-NEXT: BaseType: Null (0x0)
+# CHECK-NEXT: ComplexType: Null (0x0)
+# CHECK-NEXT: StorageClass: External (0x2)
+# CHECK-NEXT: AuxSymbolCount: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: __imp_MessageBoxA
+# CHECK-NEXT: Value: 72
+# CHECK-NEXT: Section: .idata (4)
+# CHECK-NEXT: BaseType: Null (0x0)
+# CHECK-NEXT: ComplexType: Null (0x0)
+# CHECK-NEXT: StorageClass: External (0x2)
+# CHECK-NEXT: AuxSymbolCount: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: MessageBoxA
+# CHECK-NEXT: Value: 80
+# CHECK-NEXT: Section: .text (2)
+# CHECK-NEXT: BaseType: Null (0x0)
+# CHECK-NEXT: ComplexType: Null (0x0)
+# CHECK-NEXT: StorageClass: External (0x2)
+# CHECK-NEXT: AuxSymbolCount: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+# NO: Symbols [
+
+---
+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: B800000000000000005068000000000000000068000000000000000050E8000000000000000050E8000000000000000050E80000000000000000
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: abs_symbol
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 7
+ SymbolName: caption
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 12
+ SymbolName: message
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 18
+ SymbolName: MessageBoxA
+ Type: IMAGE_REL_AMD64_REL32
+ - VirtualAddress: 24
+ SymbolName: ExitProcess
+ Type: IMAGE_REL_AMD64_REL32
+ - VirtualAddress: 30
+ SymbolName: __ImageBase
+ Type: IMAGE_REL_AMD64_ADDR64
+ - Name: .text2
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4096
+ SectionData: B800000000000000005068000000000000000068000000000000000050E8000000000000000050E8000000000000000050E80000000000000000
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: abs_symbol
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 7
+ SymbolName: caption
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 12
+ SymbolName: message
+ Type: IMAGE_REL_AMD64_ADDR64
+ - VirtualAddress: 18
+ SymbolName: MessageBoxA
+ Type: IMAGE_REL_AMD64_REL32
+ - VirtualAddress: 24
+ SymbolName: ExitProcess
+ Type: IMAGE_REL_AMD64_REL32
+ - VirtualAddress: 30
+ SymbolName: __ImageBase
+ Type: IMAGE_REL_AMD64_ADDR64
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ Alignment: 4
+ SectionData: 48656C6C6F0048656C6C6F20576F726C6400
+symbols:
+ - Name: "@comp.id"
+ Value: 10394907
+ SectionNumber: 65535
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 28
+ NumberOfRelocations: 6
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: .text2
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 28
+ NumberOfRelocations: 6
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: .data
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 18
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ - Name: MessageBoxA
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: ExitProcess
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: message
+ Value: 6
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: main
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: caption
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ - Name: abs_symbol
+ Value: 0xDEADBEEF
+ SectionNumber: -1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __ImageBase
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/tls.test b/test/COFF/tls.test
new file mode 100644
index 000000000000..395916dfdd67
--- /dev/null
+++ b/test/COFF/tls.test
@@ -0,0 +1,43 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
+
+# CHECK: TLSTableRVA: 0x1000
+# CHECK: TLSTableSize: 0x28
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 00000000
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 4
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ Selection: IMAGE_COMDAT_SELECT_ANY
+ - Name: main
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: _tls_used
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/tls32.test b/test/COFF/tls32.test
new file mode 100644
index 000000000000..4fe020eb9e10
--- /dev/null
+++ b/test/COFF/tls32.test
@@ -0,0 +1,43 @@
+# RUN: yaml2obj < %s > %t.obj
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
+
+# CHECK: TLSTableRVA: 0x1000
+# CHECK: TLSTableSize: 0x28
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_I386
+ Characteristics: []
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 00000000
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 4
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 0
+ Selection: IMAGE_COMDAT_SELECT_ANY
+ - Name: _main
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __tls_used
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/unwind.test b/test/COFF/unwind.test
new file mode 100644
index 000000000000..48e94165b9bd
--- /dev/null
+++ b/test/COFF/unwind.test
@@ -0,0 +1,198 @@
+# RUN: yaml2obj < %s > %t.obj
+#
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=HEADER %s
+# RUN: llvm-objdump -unwind-info %t.exe | FileCheck -check-prefix=UNWIND %s
+#
+# HEADER: ExceptionTableRVA: 0x1000
+#
+# UNWIND: Function Table:
+# UNWIND: Start Address: 0x2000
+# UNWIND: End Address: 0x201b
+# UNWIND: Unwind Info Address: 0x3000
+# UNWIND: Version: 1
+# UNWIND: Flags: 1 UNW_ExceptionHandler
+# UNWIND: Size of prolog: 18
+# UNWIND: Number of Codes: 8
+# UNWIND: Frame register: RBX
+# UNWIND: Frame offset: 0
+# UNWIND: Unwind Codes:
+# UNWIND: 0x12: UOP_SetFPReg
+# UNWIND: 0x0f: UOP_PushNonVol RBX
+# UNWIND: 0x0e: UOP_SaveXMM128 XMM8 [0x0000]
+# UNWIND: 0x09: UOP_SaveNonVol RSI [0x0010]
+# UNWIND: 0x04: UOP_AllocSmall 24
+# UNWIND: 0x00: UOP_PushMachFrame w/o error code
+# UNWIND: Function Table:
+# UNWIND: Start Address: 0x2012
+# UNWIND: End Address: 0x2012
+# UNWIND: Unwind Info Address: 0x301c
+# UNWIND: Version: 1
+# UNWIND: Flags: 4 UNW_ChainInfo
+# UNWIND: Size of prolog: 0
+# UNWIND: Number of Codes: 0
+# UNWIND: No frame pointer used
+# UNWIND: Function Table:
+# UNWIND: Start Address: 0x201b
+# UNWIND: End Address: 0x201c
+# UNWIND: Unwind Info Address: 0x302c
+# UNWIND: Version: 1
+# UNWIND: Flags: 0
+# UNWIND: Size of prolog: 0
+# UNWIND: Number of Codes: 0
+# UNWIND: No frame pointer used
+# UNWIND: Function Table:
+# UNWIND: Start Address: 0x201c
+# UNWIND: End Address: 0x2039
+# UNWIND: Unwind Info Address: 0x3034
+# UNWIND: Version: 1
+# UNWIND: Flags: 0
+# UNWIND: Size of prolog: 14
+# UNWIND: Number of Codes: 6
+# UNWIND: No frame pointer used
+# UNWIND: Unwind Codes:
+# UNWIND: 0x0e: UOP_AllocLarge 8454128
+# UNWIND: 0x07: UOP_AllocLarge 8190
+# UNWIND: 0x00: UOP_PushMachFrame w/o error code
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 4883EC184889742410440F110424534889E3488D235B4883C418C3C34881ECF0FF00004881ECF0FF80004881C4F0FF80004881C4F0FF0000C3
+ - Name: .xdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 0912080312030F300E880000096402000422001A000000000000000021000000000000001B000000000000000100000000000000010E06000E11F0FF80000701FE1F001A
+ Relocations:
+ - VirtualAddress: 20
+ SymbolName: __C_specific_handler
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 32
+ SymbolName: func
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 36
+ SymbolName: func
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 40
+ SymbolName: .xdata
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - Name: .pdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ Alignment: 4
+ SectionData: 000000001B0000000000000012000000120000001C00000000000000010000002C000000000000001D00000034000000
+ Relocations:
+ - VirtualAddress: 0
+ SymbolName: func
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 4
+ SymbolName: func
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 8
+ SymbolName: .xdata
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 12
+ SymbolName: func
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 16
+ SymbolName: func
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 20
+ SymbolName: .xdata
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 24
+ SymbolName: smallFunc
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 28
+ SymbolName: smallFunc
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 32
+ SymbolName: .xdata
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 36
+ SymbolName: allocFunc
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 40
+ SymbolName: allocFunc
+ Type: IMAGE_REL_AMD64_ADDR32NB
+ - VirtualAddress: 44
+ SymbolName: .xdata
+ Type: IMAGE_REL_AMD64_ADDR32NB
+symbols:
+ - Name: .text
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 57
+ NumberOfRelocations: 0
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 1
+ - Name: .xdata
+ Value: 0
+ SectionNumber: 2
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 68
+ NumberOfRelocations: 4
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 2
+ - Name: .pdata
+ Value: 0
+ SectionNumber: 3
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_STATIC
+ SectionDefinition:
+ Length: 48
+ NumberOfRelocations: 12
+ NumberOfLinenumbers: 0
+ CheckSum: 0
+ Number: 3
+ - Name: func
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __C_specific_handler
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: smallFunc
+ Value: 27
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: allocFunc
+ Value: 28
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: main
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: __C_specific_handler
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_NULL
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/version.test b/test/COFF/version.test
new file mode 100644
index 000000000000..69fa93394a0f
--- /dev/null
+++ b/test/COFF/version.test
@@ -0,0 +1,19 @@
+# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=DEFAULT %s
+
+DEFAULT: MajorImageVersion: 0
+DEFAULT: MinorImageVersion: 0
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj /version:11
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s
+
+CHECK1: MajorImageVersion: 11
+CHECK1: MinorImageVersion: 0
+
+# RUN: lld-link /out:%t.exe /entry:main %t.obj /version:11.22
+# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s
+
+CHECK2: MajorImageVersion: 11
+CHECK2: MinorImageVersion: 22
diff --git a/test/COFF/weak-external.test b/test/COFF/weak-external.test
new file mode 100644
index 000000000000..3997170b897a
--- /dev/null
+++ b/test/COFF/weak-external.test
@@ -0,0 +1,36 @@
+# RUN: yaml2obj %s > %t.obj
+# RUN: llvm-as -o %t.lto.obj %S/Inputs/weak-external.ll
+# RUN: lld-link /out:%t1.exe /entry:g /subsystem:console %t.obj
+# RUN: lld-link /out:%t2.exe /entry:g /subsystem:console /lldmap:%t2.map %t.obj %t.lto.obj
+# RUN: FileCheck %s < %t2.map
+
+# CHECK: <lto object>:
+# CHECK-NOT: :
+# CHECK: {{ g$}}
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: '.text'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 00
+symbols:
+ - Name: 'g'
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_WEAK_EXTERNAL
+ WeakExternal:
+ TagIndex: 2
+ Characteristics: IMAGE_WEAK_EXTERN_SEARCH_LIBRARY
+ - Name: 'f'
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/COFF/weak-external2.test b/test/COFF/weak-external2.test
new file mode 100644
index 000000000000..6afaac29219d
--- /dev/null
+++ b/test/COFF/weak-external2.test
@@ -0,0 +1,30 @@
+# RUN: yaml2obj %s > %t.obj
+# 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
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: '.text'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 00
+symbols:
+ - Name: 'f'
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+ - Name: 'g'
+ Value: 0
+ SectionNumber: 0
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_WEAK_EXTERNAL
+ WeakExternal:
+ TagIndex: 0
+ Characteristics: IMAGE_WEAK_EXTERN_SEARCH_LIBRARY
+...
diff --git a/test/COFF/weak-external3.test b/test/COFF/weak-external3.test
new file mode 100644
index 000000000000..9ba32982d505
--- /dev/null
+++ b/test/COFF/weak-external3.test
@@ -0,0 +1,32 @@
+# RUN: yaml2obj %s > %t.obj
+# RUN: llvm-as -o %t.lto.obj %S/Inputs/weak-external3.ll
+# RUN: lld-link /out:%t1.exe /entry:f /subsystem:console /lldmap:%t1.map %t.lto.obj
+# RUN: FileCheck --check-prefix=CHECK1 %s < %t1.map
+# RUN: lld-link /out:%t2.exe /entry:f /subsystem:console /lldmap:%t2.map %t.obj %t.lto.obj
+# RUN: FileCheck --check-prefix=CHECK2 %s < %t2.map
+
+# CHECK1: <lto object>:
+# CHECK1-NOT: :
+# CHECK1: {{ g$}}
+
+# CHECK2: weak-external3{{.*}}:
+# CHECK2-NOT: :
+# CHECK2: {{ f$}}
+
+---
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: '.text'
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ Alignment: 16
+ SectionData: 00
+symbols:
+ - Name: 'f'
+ Value: 0
+ SectionNumber: 1
+ SimpleType: IMAGE_SYM_TYPE_NULL
+ ComplexType: IMAGE_SYM_DTYPE_FUNCTION
+ StorageClass: IMAGE_SYM_CLASS_EXTERNAL
+...
diff --git a/test/Driver/def-lib-search.test b/test/Driver/def-lib-search.test
index 818cbfe6ad61..15d5dbbea9ff 100644
--- a/test/Driver/def-lib-search.test
+++ b/test/Driver/def-lib-search.test
@@ -1,7 +1,7 @@
# Check that search paths explicitly provided by the -L option
-# are used in search before default paths.
+# are used in search before default paths.
-RUN: not lld -flavor gnu -target x86_64 -t -ltest \
+RUN: not lld -flavor old-gnu -target x86_64 -t -ltest \
RUN: --sysroot=%p/Inputs -L%p/Inputs 2> %t
RUN: FileCheck %s < %t
diff --git a/test/Driver/flavor-option.test b/test/Driver/flavor-option.test
index 2ca3b410cbe2..2471bc09519b 100644
--- a/test/Driver/flavor-option.test
+++ b/test/Driver/flavor-option.test
@@ -2,7 +2,7 @@
# 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 gnu | FileCheck %s
+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
index 9d3666f63c36..255b17b1a55e 100644
--- a/test/Driver/lib-search.test
+++ b/test/Driver/lib-search.test
@@ -1,16 +1,16 @@
-RUN: not lld -flavor gnu -t -ltest -L%p/Inputs 2> %t.err
+RUN: not lld -flavor old-gnu -t -ltest -L%p/Inputs 2> %t.err
RUN: FileCheck %s < %t.err
-RUN: not lld -flavor gnu -target x86_64--netbsd -t -ltest \
+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 gnu -target x86_64--netbsd -nostdlib -t -ltest \
+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 gnu -target i386--netbsd -t -ltest \
+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 gnu -target x86_64--netbsd -m elf_i386 -t -ltest \
+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
diff --git a/test/Driver/so-whole-archive.test b/test/Driver/so-whole-archive.test
index 0732c35a7a92..8ab879082bf1 100644
--- a/test/Driver/so-whole-archive.test
+++ b/test/Driver/so-whole-archive.test
@@ -3,8 +3,8 @@
# RUN: yaml2obj -format=elf -docnum=1 %s > %t-so.o
# RUN: yaml2obj -format=elf -docnum=2 %s > %t-exe.o
-# RUN: lld -flavor gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: lld -flavor gnu -target mipsel -o %t.exe %t-exe.o --whole-archive %t.so
+# 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
---
diff --git a/test/Driver/trivial-driver.test b/test/Driver/trivial-driver.test
index 196d6cfa9d4d..46de60c543f6 100644
--- a/test/Driver/trivial-driver.test
+++ b/test/Driver/trivial-driver.test
@@ -1,5 +1,5 @@
# This test, tests the Gnu lld option --help
-RUN: lld -flavor gnu --help | FileCheck %s
+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
index f942d5c8e904..7b11a7e8c982 100644
--- a/test/Driver/undef-basic.objtxt
+++ b/test/Driver/undef-basic.objtxt
@@ -1,4 +1,4 @@
-# RUN: lld -flavor gnu -u undefinedsymbol -e entrysymbol %s \
+# RUN: lld -flavor old-gnu -u undefinedsymbol -e entrysymbol %s \
# RUN: --output-filetype=yaml --noinhibit-exec | FileCheck %s
#
diff --git a/test/ELF/Inputs/abs.s b/test/ELF/Inputs/abs.s
new file mode 100644
index 000000000000..dc7f67a3c251
--- /dev/null
+++ b/test/ELF/Inputs/abs.s
@@ -0,0 +1,4 @@
+.global abs
+abs = 0x42
+.global big
+big = 0x1000000000
diff --git a/test/ELF/Inputs/abs255.s b/test/ELF/Inputs/abs255.s
new file mode 100644
index 000000000000..844ae7d863d2
--- /dev/null
+++ b/test/ELF/Inputs/abs255.s
@@ -0,0 +1,2 @@
+.global foo
+foo = 255
diff --git a/test/ELF/Inputs/abs256.s b/test/ELF/Inputs/abs256.s
new file mode 100644
index 000000000000..3f53bc5ec9f6
--- /dev/null
+++ b/test/ELF/Inputs/abs256.s
@@ -0,0 +1,2 @@
+.global foo
+foo = 256
diff --git a/test/ELF/Inputs/abs257.s b/test/ELF/Inputs/abs257.s
new file mode 100644
index 000000000000..4ae7fe8fe5ef
--- /dev/null
+++ b/test/ELF/Inputs/abs257.s
@@ -0,0 +1,2 @@
+.global foo
+foo = 257
diff --git a/test/ELF/Inputs/allow-multiple-definition.s b/test/ELF/Inputs/allow-multiple-definition.s
new file mode 100644
index 000000000000..c2655a437ae3
--- /dev/null
+++ b/test/ELF/Inputs/allow-multiple-definition.s
@@ -0,0 +1,4 @@
+.globl _bar
+.type _bar, @function
+_bar:
+ mov $2, %eax
diff --git a/test/ELF/Inputs/allow-shlib-undefined.s b/test/ELF/Inputs/allow-shlib-undefined.s
new file mode 100644
index 000000000000..e2fb7de2301a
--- /dev/null
+++ b/test/ELF/Inputs/allow-shlib-undefined.s
@@ -0,0 +1,3 @@
+.globl _shared
+_shared:
+ call _unresolved
diff --git a/test/ELF/Inputs/archive.s b/test/ELF/Inputs/archive.s
new file mode 100644
index 000000000000..42ccfd47b48b
--- /dev/null
+++ b/test/ELF/Inputs/archive.s
@@ -0,0 +1,5 @@
+.globl _start;
+_start:
+
+.globl end;
+end:
diff --git a/test/ELF/Inputs/archive2.s b/test/ELF/Inputs/archive2.s
new file mode 100644
index 000000000000..ade79556db7b
--- /dev/null
+++ b/test/ELF/Inputs/archive2.s
@@ -0,0 +1,2 @@
+.global foo
+foo:
diff --git a/test/ELF/Inputs/archive3.s b/test/ELF/Inputs/archive3.s
new file mode 100644
index 000000000000..3e11d4314104
--- /dev/null
+++ b/test/ELF/Inputs/archive3.s
@@ -0,0 +1,2 @@
+.global bar
+bar:
diff --git a/test/ELF/Inputs/archive4.s b/test/ELF/Inputs/archive4.s
new file mode 100644
index 000000000000..e842874f187c
--- /dev/null
+++ b/test/ELF/Inputs/archive4.s
@@ -0,0 +1 @@
+.quad bar
diff --git a/test/ELF/Inputs/comdat.s b/test/ELF/Inputs/comdat.s
new file mode 100644
index 000000000000..467bfa4b8da2
--- /dev/null
+++ b/test/ELF/Inputs/comdat.s
@@ -0,0 +1,3 @@
+ .section .text3,"axG",@progbits,zed,comdat,unique,0
+ .global abc
+abc:
diff --git a/test/ELF/Inputs/common.s b/test/ELF/Inputs/common.s
new file mode 100644
index 000000000000..ea8ba91cb156
--- /dev/null
+++ b/test/ELF/Inputs/common.s
@@ -0,0 +1,3 @@
+.comm sym1,8,4
+.comm sym2,4,4
+.comm sym4,4,16
diff --git a/test/ELF/Inputs/discard-merge-unnamed.o b/test/ELF/Inputs/discard-merge-unnamed.o
new file mode 100644
index 000000000000..040addf04f4e
--- /dev/null
+++ b/test/ELF/Inputs/discard-merge-unnamed.o
Binary files differ
diff --git a/test/ELF/Inputs/dynamic-reloc.s b/test/ELF/Inputs/dynamic-reloc.s
new file mode 100644
index 000000000000..82fa7a17f078
--- /dev/null
+++ b/test/ELF/Inputs/dynamic-reloc.s
@@ -0,0 +1,2 @@
+.global main
+main:
diff --git a/test/ELF/Inputs/invalid-binding.elf b/test/ELF/Inputs/invalid-binding.elf
new file mode 100644
index 000000000000..61b5af9b456c
--- /dev/null
+++ b/test/ELF/Inputs/invalid-binding.elf
Binary files differ
diff --git a/test/ELF/Inputs/invalid-data-encoding.a b/test/ELF/Inputs/invalid-data-encoding.a
new file mode 100644
index 000000000000..ff2b37318c1e
--- /dev/null
+++ b/test/ELF/Inputs/invalid-data-encoding.a
Binary files differ
diff --git a/test/ELF/Inputs/invalid-file-class.a b/test/ELF/Inputs/invalid-file-class.a
new file mode 100644
index 000000000000..f0ce607b4fdc
--- /dev/null
+++ b/test/ELF/Inputs/invalid-file-class.a
Binary files differ
diff --git a/test/ELF/Inputs/invalid-multiple-eh-relocs.elf b/test/ELF/Inputs/invalid-multiple-eh-relocs.elf
new file mode 100644
index 000000000000..62914596256a
--- /dev/null
+++ b/test/ELF/Inputs/invalid-multiple-eh-relocs.elf
Binary files differ
diff --git a/test/ELF/Inputs/invalid-section-index.elf b/test/ELF/Inputs/invalid-section-index.elf
new file mode 100644
index 000000000000..ec5adcf3b0b8
--- /dev/null
+++ b/test/ELF/Inputs/invalid-section-index.elf
Binary files differ
diff --git a/test/ELF/Inputs/invalid-shentsize-zero.elf b/test/ELF/Inputs/invalid-shentsize-zero.elf
new file mode 100644
index 000000000000..5fa7df245619
--- /dev/null
+++ b/test/ELF/Inputs/invalid-shentsize-zero.elf
Binary files differ
diff --git a/test/ELF/Inputs/invalid-shstrndx.so b/test/ELF/Inputs/invalid-shstrndx.so
new file mode 100755
index 000000000000..dc332b9292ea
--- /dev/null
+++ b/test/ELF/Inputs/invalid-shstrndx.so
Binary files differ
diff --git a/test/ELF/Inputs/invalid-symtab-sh_info.elf b/test/ELF/Inputs/invalid-symtab-sh_info.elf
new file mode 100644
index 000000000000..aa63d582d757
--- /dev/null
+++ b/test/ELF/Inputs/invalid-symtab-sh_info.elf
Binary files differ
diff --git a/test/ELF/Inputs/libsearch-dyn.s b/test/ELF/Inputs/libsearch-dyn.s
new file mode 100644
index 000000000000..c0c33f92944d
--- /dev/null
+++ b/test/ELF/Inputs/libsearch-dyn.s
@@ -0,0 +1,3 @@
+.globl _bar,_dynamic;
+_bar:
+_dynamic:
diff --git a/test/ELF/Inputs/libsearch-st.s b/test/ELF/Inputs/libsearch-st.s
new file mode 100644
index 000000000000..c02ee741c803
--- /dev/null
+++ b/test/ELF/Inputs/libsearch-st.s
@@ -0,0 +1,3 @@
+.globl _bar,_static;
+_bar:
+_static:
diff --git a/test/ELF/Inputs/merge.s b/test/ELF/Inputs/merge.s
new file mode 100644
index 000000000000..a8e1144fbc27
--- /dev/null
+++ b/test/ELF/Inputs/merge.s
@@ -0,0 +1,6 @@
+ .section .mysec,"aM",@progbits,4
+ .align 4
+ .long 0x42
+
+ .text
+ movl .mysec, %eax
diff --git a/test/ELF/Inputs/mips-dynamic.s b/test/ELF/Inputs/mips-dynamic.s
new file mode 100644
index 000000000000..eba5b7f327b4
--- /dev/null
+++ b/test/ELF/Inputs/mips-dynamic.s
@@ -0,0 +1,4 @@
+ .text
+ .globl _foo
+_foo:
+ nop
diff --git a/test/elf/Inputs/stripped-empty.x86_64 b/test/ELF/Inputs/no-symtab.o
index 7368ba280d79..7368ba280d79 100644
--- a/test/elf/Inputs/stripped-empty.x86_64
+++ b/test/ELF/Inputs/no-symtab.o
Binary files differ
diff --git a/test/ELF/Inputs/relocation-copy-align.s b/test/ELF/Inputs/relocation-copy-align.s
new file mode 100644
index 000000000000..83dedc7218d5
--- /dev/null
+++ b/test/ELF/Inputs/relocation-copy-align.s
@@ -0,0 +1,9 @@
+.data
+ .balign 16
+ .zero 12
+
+ .type x,@object
+ .globl x
+x:
+ .long 0
+ .size x, 4
diff --git a/test/ELF/Inputs/relocation-copy.s b/test/ELF/Inputs/relocation-copy.s
new file mode 100644
index 000000000000..6b113aba294e
--- /dev/null
+++ b/test/ELF/Inputs/relocation-copy.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/relocation-size-shared.s b/test/ELF/Inputs/relocation-size-shared.s
new file mode 100644
index 000000000000..02b4cf027b58
--- /dev/null
+++ b/test/ELF/Inputs/relocation-size-shared.s
@@ -0,0 +1,6 @@
+.data
+.global fooshared
+.type fooshared,%object
+.size fooshared,26
+fooshared:
+.zero 26
diff --git a/test/ELF/Inputs/resolution.s b/test/ELF/Inputs/resolution.s
new file mode 100644
index 000000000000..70afb163278f
--- /dev/null
+++ b/test/ELF/Inputs/resolution.s
@@ -0,0 +1,107 @@
+local:
+
+.weak RegularWeak_with_RegularWeak
+.size RegularWeak_with_RegularWeak, 32
+RegularWeak_with_RegularWeak:
+
+.global RegularWeak_with_RegularStrong
+.size RegularWeak_with_RegularStrong, 33
+RegularWeak_with_RegularStrong:
+
+.weak RegularStrong_with_RegularWeak
+.size RegularStrong_with_RegularWeak, 34
+RegularStrong_with_RegularWeak:
+
+.weak RegularWeak_with_UndefWeak
+.size RegularWeak_with_UndefWeak, 35
+.quad RegularWeak_with_UndefWeak
+
+.size RegularWeak_with_UndefStrong, 36
+.quad RegularWeak_with_UndefStrong
+
+.weak RegularStrong_with_UndefWeak
+.size RegularStrong_with_UndefWeak, 37
+.quad RegularStrong_with_UndefWeak
+
+.size RegularStrong_with_UndefStrong, 38
+.quad RegularStrong_with_UndefStrong
+
+.weak RegularWeak_with_CommonWeak
+.comm RegularWeak_with_CommonWeak,39,4
+
+.comm RegularWeak_with_CommonStrong,40,4
+
+.weak RegularStrong_with_CommonWeak
+.comm RegularStrong_with_CommonWeak,41,4
+
+.comm RegularStrong_with_CommonStrong,42,4
+
+.weak UndefWeak_with_RegularWeak
+.size UndefWeak_with_RegularWeak, 43
+UndefWeak_with_RegularWeak:
+
+.global UndefWeak_with_RegularStrong
+.size UndefWeak_with_RegularStrong, 44
+UndefWeak_with_RegularStrong:
+
+.weak UndefStrong_with_RegularWeak
+.size UndefStrong_with_RegularWeak, 45
+UndefStrong_with_RegularWeak:
+
+.global UndefStrong_with_RegularStrong
+.size UndefStrong_with_RegularStrong, 46
+UndefStrong_with_RegularStrong:
+
+.weak UndefWeak_with_UndefWeak
+.size UndefWeak_with_UndefWeak, 47
+.quad UndefWeak_with_UndefWeak
+
+.weak UndefWeak_with_CommonWeak
+.comm UndefWeak_with_CommonWeak,48,4
+
+.comm UndefWeak_with_CommonStrong,49,4
+
+.weak UndefStrong_with_CommonWeak
+.comm UndefStrong_with_CommonWeak,50,4
+
+.comm UndefStrong_with_CommonStrong,51,4
+
+.weak CommonWeak_with_RegularWeak
+.size CommonWeak_with_RegularWeak, 52
+CommonWeak_with_RegularWeak:
+
+.global CommonWeak_with_RegularStrong
+.size CommonWeak_with_RegularStrong, 53
+CommonWeak_with_RegularStrong:
+
+.weak CommonStrong_with_RegularWeak
+.size CommonStrong_with_RegularWeak, 54
+CommonStrong_with_RegularWeak:
+
+.global CommonStrong_with_RegularStrong
+.size CommonStrong_with_RegularStrong, 55
+CommonStrong_with_RegularStrong:
+
+.weak CommonWeak_with_UndefWeak
+.size CommonWeak_with_UndefWeak, 56
+.quad CommonWeak_with_UndefWeak
+
+.size CommonWeak_with_UndefStrong, 57
+.quad CommonWeak_with_UndefStrong
+
+.weak CommonStrong_with_UndefWeak
+.size CommonStrong_with_UndefWeak, 58
+.quad CommonStrong_with_UndefWeak
+
+.size CommonStrong_with_UndefStrong, 59
+.quad CommonStrong_with_UndefStrong
+
+.weak CommonWeak_with_CommonWeak
+.comm CommonWeak_with_CommonWeak,60,4
+
+.comm CommonWeak_with_CommonStrong,61,4
+
+.weak CommonStrong_with_CommonWeak
+.comm CommonStrong_with_CommonWeak,62,4
+
+.comm CommonStrong_with_CommonStrong,63,4
diff --git a/test/ELF/Inputs/shared-ppc64.s b/test/ELF/Inputs/shared-ppc64.s
new file mode 100644
index 000000000000..b0117ac42963
--- /dev/null
+++ b/test/ELF/Inputs/shared-ppc64.s
@@ -0,0 +1,9 @@
+.section ".opd","aw"
+.global bar
+bar:
+.quad .Lbar,.TOC.@tocbase,0
+.quad .Lbar,0,0
+
+.text
+.Lbar:
+ blr
diff --git a/test/ELF/Inputs/shared.s b/test/ELF/Inputs/shared.s
new file mode 100644
index 000000000000..1cfebbfaf373
--- /dev/null
+++ b/test/ELF/Inputs/shared.s
@@ -0,0 +1,6 @@
+.global bar
+.type bar, @function
+bar:
+
+.global zed
+zed:
diff --git a/test/ELF/Inputs/shared2.s b/test/ELF/Inputs/shared2.s
new file mode 100644
index 000000000000..a723902e890e
--- /dev/null
+++ b/test/ELF/Inputs/shared2.s
@@ -0,0 +1,6 @@
+.global bar2
+.type bar2, @function
+bar2:
+
+.global zed2
+zed2:
diff --git a/test/ELF/Inputs/shared3.s b/test/ELF/Inputs/shared3.s
new file mode 100644
index 000000000000..d1f6ffea1332
--- /dev/null
+++ b/test/ELF/Inputs/shared3.s
@@ -0,0 +1,3 @@
+.global baz
+.type barz, @function
+baz:
diff --git a/test/ELF/Inputs/tls-got.s b/test/ELF/Inputs/tls-got.s
new file mode 100644
index 000000000000..5681d001fd9d
--- /dev/null
+++ b/test/ELF/Inputs/tls-got.s
@@ -0,0 +1,14 @@
+.type tls0,@object
+.section .tbss,"awT",@nobits
+.globl tls0
+.align 4
+tls0:
+ .long 0
+ .size tls0, 4
+
+.type tls1,@object
+.globl tls1
+.align 4
+tls1:
+ .long 0
+ .size tls1, 4
diff --git a/test/ELF/Inputs/tls-mismatch.s b/test/ELF/Inputs/tls-mismatch.s
new file mode 100644
index 000000000000..8c14f58a742f
--- /dev/null
+++ b/test/ELF/Inputs/tls-mismatch.s
@@ -0,0 +1,4 @@
+.tbss
+.globl tlsvar
+tlsvar:
+ .space 4
diff --git a/test/ELF/Inputs/tls-opt-gdie.s b/test/ELF/Inputs/tls-opt-gdie.s
new file mode 100644
index 000000000000..361578f21407
--- /dev/null
+++ b/test/ELF/Inputs/tls-opt-gdie.s
@@ -0,0 +1,20 @@
+.type tlsshared0,@object
+.section .tbss,"awT",@nobits
+.globl tlsshared0
+.align 4
+tlsshared0:
+ .long 0
+ .size tlsshared0, 4
+
+.type tlsshared1,@object
+.globl tlsshared1
+.align 4
+tlsshared1:
+ .long 0
+ .size tlsshared1, 4
+
+.text
+.globl __tls_get_addr
+.align 16, 0x90
+.type __tls_get_addr,@function
+__tls_get_addr:
diff --git a/test/ELF/Inputs/tls-opt-gdiele-i686.s b/test/ELF/Inputs/tls-opt-gdiele-i686.s
new file mode 100644
index 000000000000..ab72b9d7cb74
--- /dev/null
+++ b/test/ELF/Inputs/tls-opt-gdiele-i686.s
@@ -0,0 +1,20 @@
+.type tlsshared0,@object
+.section .tbss,"awT",@nobits
+.globl tlsshared0
+.align 4
+tlsshared0:
+ .long 0
+ .size tlsshared0, 4
+
+.type tlsshared1,@object
+.globl tlsshared1
+.align 4
+tlsshared1:
+ .long 0
+ .size tlsshared1, 4
+
+.text
+ .globl __tls_get_addr
+ .align 16, 0x90
+ .type __tls_get_addr,@function
+__tls_get_addr:
diff --git a/test/ELF/Inputs/tls-opt-iele-i686-nopic.s b/test/ELF/Inputs/tls-opt-iele-i686-nopic.s
new file mode 100644
index 000000000000..a090065ecf9a
--- /dev/null
+++ b/test/ELF/Inputs/tls-opt-iele-i686-nopic.s
@@ -0,0 +1,15 @@
+.type tlsshared0,@object
+.section .tbss,"awT",@nobits
+.globl tlsshared0
+.align 4
+tlsshared0:
+ .long 0
+ .size tlsshared0, 4
+
+.type tlsshared1,@object
+.section .tbss,"awT",@nobits
+.globl tlsshared1
+.align 4
+tlsshared1:
+ .long 0
+ .size tlsshared1, 4
diff --git a/test/ELF/Inputs/visibility.s b/test/ELF/Inputs/visibility.s
new file mode 100644
index 000000000000..6ef027d315fa
--- /dev/null
+++ b/test/ELF/Inputs/visibility.s
@@ -0,0 +1,13 @@
+.quad default
+
+.protected protected
+.quad protected
+
+.hidden hidden
+.quad hidden
+
+.internal internal
+.quad internal
+
+.hidden protected_with_hidden
+.quad protected_with_hidden
diff --git a/test/ELF/Inputs/whole-archive.s b/test/ELF/Inputs/whole-archive.s
new file mode 100644
index 000000000000..f9d56fc2fa21
--- /dev/null
+++ b/test/ELF/Inputs/whole-archive.s
@@ -0,0 +1,2 @@
+.globl _bar;
+_bar:
diff --git a/test/ELF/aarch64-abs16.s b/test/ELF/aarch64-abs16.s
new file mode 100644
index 000000000000..e41abc43ee0d
--- /dev/null
+++ b/test/ELF/aarch64-abs16.s
@@ -0,0 +1,27 @@
+// REQUIRES: aarch64
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %S/Inputs/abs255.s -o %t255.o
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %S/Inputs/abs256.s -o %t256.o
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %S/Inputs/abs257.s -o %t257.o
+
+.globl _start
+_start:
+.data
+ .hword foo + 0xfeff
+ .hword foo - 0x8100
+
+// RUN: ld.lld %t.o %t256.o -o %t2
+// RUN: llvm-objdump -s -section=.data %t2 | FileCheck %s
+
+// CHECK: Contents of section .data:
+// 11000: S = 0x100, A = 0xfeff
+// S + A = 0xffff
+// 11002: S = 0x100, A = -0x8100
+// S + A = 0x8000
+// CHECK-NEXT: 11000 ffff0080
+
+// RUN: not ld.lld %t.o %t255.o -o %t2
+// | FileCheck %s --check-prefix=OVERFLOW
+// RUN: not ld.lld %t.o %t257.o -o %t2
+// | FileCheck %s --check-prefix=OVERFLOW
+// OVERFLOW: Relocation R_AARCH64_ABS16 out of range
diff --git a/test/ELF/aarch64-abs32.s b/test/ELF/aarch64-abs32.s
new file mode 100644
index 000000000000..c2460d15e825
--- /dev/null
+++ b/test/ELF/aarch64-abs32.s
@@ -0,0 +1,27 @@
+// REQUIRES: aarch64
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %S/Inputs/abs255.s -o %t255.o
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %S/Inputs/abs256.s -o %t256.o
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %S/Inputs/abs257.s -o %t257.o
+
+.globl _start
+_start:
+.data
+ .word foo + 0xfffffeff
+ .word foo - 0x80000100
+
+// RUN: ld.lld %t.o %t256.o -o %t2
+// RUN: llvm-objdump -s -section=.data %t2 | FileCheck %s
+
+// CHECK: Contents of section .data:
+// 11000: S = 0x100, A = 0xfffffeff
+// S + A = 0xffffffff
+// 11004: S = 0x100, A = -0x80000100
+// S + A = 0x80000000
+// CHECK-NEXT: 11000 ffffffff 00000080
+
+// RUN: not ld.lld %t.o %t255.o -o %t2
+// | FileCheck %s --check-prefix=OVERFLOW
+// RUN: not ld.lld %t.o %t257.o -o %t2
+// | FileCheck %s --check-prefix=OVERFLOW
+// OVERFLOW: Relocation R_AARCH64_ABS32 out of range
diff --git a/test/ELF/aarch64-call26-error.s b/test/ELF/aarch64-call26-error.s
new file mode 100644
index 000000000000..4b666c69011a
--- /dev/null
+++ b/test/ELF/aarch64-call26-error.s
@@ -0,0 +1,11 @@
+// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %S/Inputs/abs.s -o %tabs
+// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %s -o %t
+// RUN: not ld.lld %t %tabs -o %t2 2>&1 | FileCheck %s
+// REQUIRES: aarch64
+
+.text
+.globl _start
+_start:
+ bl big
+
+// CHECK: R_AARCH64_CALL26 out of range
diff --git a/test/ELF/aarch64-copy.s b/test/ELF/aarch64-copy.s
new file mode 100644
index 000000000000..86d972057df0
--- /dev/null
+++ b/test/ELF/aarch64-copy.s
@@ -0,0 +1,93 @@
+// REQUIRES: aarch64
+// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %p/Inputs/relocation-copy.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 %t3 | FileCheck -check-prefix=CODE %s
+// RUN: llvm-objdump -s -section=.data %t3 | FileCheck -check-prefix=DATA %s
+
+.text
+.globl _start
+_start:
+ adr x1, x
+ adrp x2, y
+ add x2, x2, :lo12:y
+.data
+ .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: 0x13010
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 24
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment: 16
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset: 0x13010
+// 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: Type: R_AARCH64_COPY
+// CHECK-NEXT: Symbol: y
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset: 0x13024
+// CHECK-NEXT: Type: R_AARCH64_COPY
+// CHECK-NEXT: Symbol: z
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+// CHECK: Symbols [
+// CHECK: Name: x
+// 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: y
+// CHECK-NEXT: Value: 0x13020
+// 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: Size: 4
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other:
+// CHECK-NEXT: Section: .bss
+// CHECK: ]
+
+// 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
+// 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
+
+// DATA: Contents of section .data:
+// S(z) = 0x13024
+// DATA-NEXT: 13000 24300100
diff --git a/test/ELF/aarch64-data-relocs.s b/test/ELF/aarch64-data-relocs.s
new file mode 100644
index 000000000000..30770836f787
--- /dev/null
+++ b/test/ELF/aarch64-data-relocs.s
@@ -0,0 +1,23 @@
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %S/Inputs/abs256.s -o %t256.o
+// RUN: ld.lld %t %t256.o -o %t2
+// RUN: llvm-objdump -s %t2 | FileCheck %s
+// REQUIRES: aarch64
+
+.globl _start
+_start:
+.section .R_AARCH64_ABS64, "ax",@progbits
+ .xword foo + 0x24
+
+// S = 0x100, A = 0x24
+// S + A = 0x124
+// CHECK: Contents of section .R_AARCH64_ABS64:
+// CHECK-NEXT: 11000 24010000 00000000
+
+.section .R_AARCH64_PREL64, "ax",@progbits
+ .xword foo - . + 0x24
+
+// S = 0x100, A = 0x24, P = 0x11008
+// S + A - P = 0xfffffffffffef11c
+// CHECK: Contents of section .R_AARCH64_PREL64:
+// CHECK-NEXT: 11008 1cf1feff ffffffff
diff --git a/test/ELF/aarch64-fpic-abs16.s b/test/ELF/aarch64-fpic-abs16.s
new file mode 100644
index 000000000000..02ac90d3a1f2
--- /dev/null
+++ b/test/ELF/aarch64-fpic-abs16.s
@@ -0,0 +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.
+
+.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
new file mode 100644
index 000000000000..9e3216b1e090
--- /dev/null
+++ b/test/ELF/aarch64-fpic-add_abs_lo12_nc.s
@@ -0,0 +1,10 @@
+// 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.
+
+ add x0, x0, :lo12:dat
+.data
+.globl dat
+dat:
+ .word 0
diff --git a/test/ELF/aarch64-fpic-adr_prel_lo21.s b/test/ELF/aarch64-fpic-adr_prel_lo21.s
new file mode 100644
index 000000000000..2246b64c6a71
--- /dev/null
+++ b/test/ELF/aarch64-fpic-adr_prel_lo21.s
@@ -0,0 +1,10 @@
+// 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.
+
+ adr x0, dat
+.data
+.globl dat
+dat:
+ .word 0
diff --git a/test/ELF/aarch64-fpic-adr_prel_pg_hi21.s b/test/ELF/aarch64-fpic-adr_prel_pg_hi21.s
new file mode 100644
index 000000000000..af6ebfc3e879
--- /dev/null
+++ b/test/ELF/aarch64-fpic-adr_prel_pg_hi21.s
@@ -0,0 +1,10 @@
+// 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.
+
+ adrp x0, dat
+.data
+.globl dat
+dat:
+ .word 0
diff --git a/test/ELF/aarch64-fpic-ldst32_abs_lo12_nc.s b/test/ELF/aarch64-fpic-ldst32_abs_lo12_nc.s
new file mode 100644
index 000000000000..2b1e6769e1a0
--- /dev/null
+++ b/test/ELF/aarch64-fpic-ldst32_abs_lo12_nc.s
@@ -0,0 +1,10 @@
+// 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.
+
+ ldr s4, [x0, :lo12:dat]
+.data
+.globl dat
+dat:
+ .word 0
diff --git a/test/ELF/aarch64-fpic-ldst64_abs_lo12_nc.s b/test/ELF/aarch64-fpic-ldst64_abs_lo12_nc.s
new file mode 100644
index 000000000000..f2553879cf37
--- /dev/null
+++ b/test/ELF/aarch64-fpic-ldst64_abs_lo12_nc.s
@@ -0,0 +1,10 @@
+// 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.
+
+ ldr x0, [x0, :lo12:dat]
+.data
+.globl dat
+dat:
+ .word 0
diff --git a/test/ELF/aarch64-fpic-ldst8_abs_lo12_nc.s b/test/ELF/aarch64-fpic-ldst8_abs_lo12_nc.s
new file mode 100644
index 000000000000..f7b465731b46
--- /dev/null
+++ b/test/ELF/aarch64-fpic-ldst8_abs_lo12_nc.s
@@ -0,0 +1,10 @@
+// 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.
+
+ ldrsb x0, [x1, :lo12:dat]
+.data
+.globl dat
+dat:
+ .word 0
diff --git a/test/ELF/aarch64-fpic-prel16.s b/test/ELF/aarch64-fpic-prel16.s
new file mode 100644
index 000000000000..d80b6e88a67a
--- /dev/null
+++ b/test/ELF/aarch64-fpic-prel16.s
@@ -0,0 +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.
+
+.data
+ .hword foo - .
diff --git a/test/ELF/aarch64-fpic-prel32.s b/test/ELF/aarch64-fpic-prel32.s
new file mode 100644
index 000000000000..af540ce734bb
--- /dev/null
+++ b/test/ELF/aarch64-fpic-prel32.s
@@ -0,0 +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.
+
+.data
+ .word foo - .
diff --git a/test/ELF/aarch64-fpic-prel64.s b/test/ELF/aarch64-fpic-prel64.s
new file mode 100644
index 000000000000..2cf4cc916b3e
--- /dev/null
+++ b/test/ELF/aarch64-fpic-prel64.s
@@ -0,0 +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.
+
+.data
+ .xword foo - .
diff --git a/test/ELF/aarch64-hi21-error.s b/test/ELF/aarch64-hi21-error.s
new file mode 100644
index 000000000000..9e2b283ea118
--- /dev/null
+++ b/test/ELF/aarch64-hi21-error.s
@@ -0,0 +1,10 @@
+// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %S/Inputs/abs.s -o %tabs
+// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %s -o %t
+// RUN: not ld.lld %tabs %t -o %t2 2>&1 | FileCheck %s
+// REQUIRES: aarch64
+
+.globl _start
+_start:
+adrp x0, big
+
+#CHECK: R_AARCH64_ADR_PREL_PG_HI21 out of range
diff --git a/test/ELF/aarch64-jump26-error.s b/test/ELF/aarch64-jump26-error.s
new file mode 100644
index 000000000000..81fbba1f4551
--- /dev/null
+++ b/test/ELF/aarch64-jump26-error.s
@@ -0,0 +1,11 @@
+// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %S/Inputs/abs.s -o %tabs
+// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %s -o %t
+// RUN: not ld.lld %t %tabs -o %t2 2>&1 | FileCheck %s
+// REQUIRES: aarch64
+
+.text
+.globl _start
+_start:
+ b big
+
+// CHECK: R_AARCH64_JUMP26 out of range
diff --git a/test/ELF/aarch64-lo21-error.s b/test/ELF/aarch64-lo21-error.s
new file mode 100644
index 000000000000..055f8948f6a3
--- /dev/null
+++ b/test/ELF/aarch64-lo21-error.s
@@ -0,0 +1,10 @@
+// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %S/Inputs/abs.s -o %tabs
+// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %s -o %t
+// RUN: not ld.lld %tabs %t -o %t2 2>&1 | FileCheck %s
+// REQUIRES: aarch64
+
+.globl _start
+_start:
+adr x0, big
+
+#CHECK: R_AARCH64_ADR_PREL_LO21 out of range
diff --git a/test/ELF/aarch64-prel16.s b/test/ELF/aarch64-prel16.s
new file mode 100644
index 000000000000..083cda908608
--- /dev/null
+++ b/test/ELF/aarch64-prel16.s
@@ -0,0 +1,31 @@
+// REQUIRES: aarch64
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %S/Inputs/abs255.s -o %t255.o
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %S/Inputs/abs256.s -o %t256.o
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %S/Inputs/abs257.s -o %t257.o
+
+.globl _start
+_start:
+.data
+ .hword foo - . + 0x20eff
+ .hword foo - . + 0x8f02
+
+// Note: If this test fails, it probably happens because of
+// the change of the address of the .data section.
+// You may found the correct address in the aarch64_abs16.s test,
+// if it is already fixed. Then, update addends accordingly.
+// RUN: ld.lld %t.o %t256.o -o %t2
+// RUN: llvm-objdump -s -section=.data %t2 | FileCheck %s
+
+// CHECK: Contents of section .data:
+// 11000: S = 0x100, A = 0x20eff, P = 0x11000
+// S + A - P = 0xffff
+// 11002: S = 0x100, A = 0x8f02, P = 0x11002
+// S + A - P = 0x8000
+// CHECK-NEXT: 11000 ffff0080
+
+// RUN: not ld.lld %t.o %t255.o -o %t2
+// | FileCheck %s --check-prefix=OVERFLOW
+// RUN: not ld.lld %t.o %t257.o -o %t2
+// | FileCheck %s --check-prefix=OVERFLOW
+// OVERFLOW: Relocation R_AARCH64_PREL16 out of range
diff --git a/test/ELF/aarch64-prel32.s b/test/ELF/aarch64-prel32.s
new file mode 100644
index 000000000000..c440b984eaa6
--- /dev/null
+++ b/test/ELF/aarch64-prel32.s
@@ -0,0 +1,31 @@
+// REQUIRES: aarch64
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %S/Inputs/abs255.s -o %t255.o
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %S/Inputs/abs256.s -o %t256.o
+// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %S/Inputs/abs257.s -o %t257.o
+
+.globl _start
+_start:
+.data
+ .word foo - . + 0x100010eff
+ .word foo - . - 0x7ffef0fc
+
+// Note: If this test fails, it probably happens because of
+// the change of the address of the .data section.
+// You may found the correct address in the aarch64_abs32.s test,
+// if it is already fixed. Then, update addends accordingly.
+// RUN: ld.lld %t.o %t256.o -o %t2
+// RUN: llvm-objdump -s -section=.data %t2 | FileCheck %s
+
+// CHECK: Contents of section .data:
+// 11000: S = 0x100, A = 0x100010eff, P = 0x11000
+// S + A - P = 0xffffffff
+// 11004: S = 0x100, A = -0x7ffef0fc, P = 0x11004
+// S + A - P = 0x80000000
+// CHECK-NEXT: 11000 ffffffff 00000080
+
+// RUN: not ld.lld %t.o %t255.o -o %t2
+// | FileCheck %s --check-prefix=OVERFLOW
+// RUN: not ld.lld %t.o %t257.o -o %t2
+// | FileCheck %s --check-prefix=OVERFLOW
+// OVERFLOW: Relocation R_AARCH64_PREL32 out of range
diff --git a/test/ELF/aarch64-relocs.s b/test/ELF/aarch64-relocs.s
new file mode 100644
index 000000000000..56b04a679111
--- /dev/null
+++ b/test/ELF/aarch64-relocs.s
@@ -0,0 +1,122 @@
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %t
+# RUN: ld.lld %t -o %t2
+# RUN: llvm-objdump -d %t2 | FileCheck %s
+# REQUIRES: aarch64
+
+.section .R_AARCH64_ADR_PREL_LO21,"ax",@progbits
+.globl _start
+_start:
+ adr x1,msg
+msg: .asciz "Hello, world\n"
+msgend:
+
+# CHECK: Disassembly of section .R_AARCH64_ADR_PREL_LO21:
+# CHECK: _start:
+# CHECK: 0: 21 00 00 10 adr x1, #4
+# CHECK: msg:
+# CHECK: 4:
+# #4 is the adr immediate value.
+
+.section .R_AARCH64_ADR_PREL_PG_H121,"ax",@progbits
+ adrp x1,mystr
+mystr:
+ .asciz "blah"
+ .size mystr, 4
+
+# S = 0x11012, A = 0x4, P = 0x11012
+# PAGE(S + A) = 0x11000
+# PAGE(P) = 0x11000
+#
+# CHECK: Disassembly of section .R_AARCH64_ADR_PREL_PG_H121:
+# CHECK-NEXT: $x.2:
+# CHECK-NEXT: 11012: 01 00 00 90 adrp x1, #0
+
+.section .R_AARCH64_ADD_ABS_LO12_NC,"ax",@progbits
+ add x0, x0, :lo12:.L.str
+.L.str:
+ .asciz "blah"
+ .size mystr, 4
+
+# S = 0x1101b, A = 0x4
+# R = (S + A) & 0xFFF = 0x1f
+# R << 10 = 0x7c00
+#
+# CHECK: Disassembly of section .R_AARCH64_ADD_ABS_LO12_NC:
+# CHECK-NEXT: $x.4:
+# CHECK-NEXT: 1101b: 00 7c 00 91 add x0, x0, #31
+
+.section .R_AARCH64_LDST64_ABS_LO12_NC,"ax",@progbits
+ ldr x28, [x27, :lo12:foo]
+foo:
+ .asciz "foo"
+ .size mystr, 3
+
+# S = 0x11024, A = 0x4
+# R = ((S + A) & 0xFFF) << 7 = 0x00001400
+# 0x00001400 | 0xf940177c = 0xf940177c
+# CHECK: Disassembly of section .R_AARCH64_LDST64_ABS_LO12_NC:
+# CHECK-NEXT: $x.6:
+# CHECK-NEXT: 11024: 7c 17 40 f9 ldr x28, [x27, #40]
+
+.section .SUB,"ax",@progbits
+ nop
+sub:
+ nop
+
+# CHECK: Disassembly of section .SUB:
+# CHECK-NEXT: $x.8:
+# CHECK-NEXT: 1102c: 1f 20 03 d5 nop
+# CHECK: sub:
+# CHECK-NEXT: 11030: 1f 20 03 d5 nop
+
+.section .R_AARCH64_CALL26,"ax",@progbits
+call26:
+ bl sub
+
+# S = 0x1102c, A = 0x4, P = 0x11034
+# R = S + A - P = -0x4 = 0xfffffffc
+# (R & 0x0ffffffc) >> 2 = 0x03ffffff
+# 0x94000000 | 0x03ffffff = 0x97ffffff
+# CHECK: Disassembly of section .R_AARCH64_CALL26:
+# CHECK-NEXT: call26:
+# CHECK-NEXT: 11034: ff ff ff 97 bl #-4
+
+.section .R_AARCH64_JUMP26,"ax",@progbits
+jump26:
+ b sub
+
+# S = 0x1102c, A = 0x4, P = 0x11038
+# R = S + A - P = -0x8 = 0xfffffff8
+# (R & 0x0ffffffc) >> 2 = 0x03fffffe
+# 0x14000000 | 0x03fffffe = 0x17fffffe
+# CHECK: Disassembly of section .R_AARCH64_JUMP26:
+# CHECK-NEXT: jump26:
+# CHECK-NEXT: 11038: fe ff ff 17 b #-8
+
+.section .R_AARCH64_LDST32_ABS_LO12_NC,"ax",@progbits
+ldst32:
+ ldr s4, [x5, :lo12:foo32]
+foo32:
+ .asciz "foo"
+ .size mystr, 3
+
+# S = 0x1103c, A = 0x4
+# R = ((S + A) & 0xFFC) << 8 = 0x00004000
+# 0x00004000 | 0xbd4000a4 = 0xbd4040a4
+# CHECK: Disassembly of section .R_AARCH64_LDST32_ABS_LO12_NC:
+# CHECK-NEXT: ldst32:
+# CHECK-NEXT: 1103c: a4 40 40 bd ldr s4, [x5, #64]
+
+.section .R_AARCH64_LDST8_ABS_LO12_NC,"ax",@progbits
+ldst8:
+ ldrsb x11, [x13, :lo12:foo8]
+foo8:
+ .asciz "foo"
+ .size mystr, 3
+
+# S = 0x11044, A = 0x4
+# R = ((S + A) & 0xFFF) << 10 = 0x00012000
+# 0x00012000 | 0x398001ab = 0x398121ab
+# CHECK: Disassembly of section .R_AARCH64_LDST8_ABS_LO12_NC:
+# CHECK-NEXT: ldst8:
+# CHECK-NEXT: 11044: ab 21 81 39 ldrsb x11, [x13, #72]
diff --git a/test/ELF/allow-multiple-definition.s b/test/ELF/allow-multiple-definition.s
new file mode 100644
index 000000000000..89ea8c865822
--- /dev/null
+++ b/test/ELF/allow-multiple-definition.s
@@ -0,0 +1,29 @@
+# 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/allow-multiple-definition.s -o %t2
+# RUN: not ld.lld %t1 %t2 -o %t3
+# RUN: ld.lld --allow-multiple-definition %t1 %t2 -o %t3
+# RUN: ld.lld --allow-multiple-definition %t2 %t1 -o %t4
+# RUN: llvm-objdump -d %t3 | FileCheck %s
+# RUN: llvm-objdump -d %t4 | FileCheck -check-prefix=REVERT %s
+
+# inputs contain different constants for instuction movl.
+# Tests below checks that order of files in command line
+# affects on what symbol will be used.
+# If flag allow-multiple-definition is enabled the first
+# meet symbol should be used.
+
+# CHECK: _bar:
+# CHECK-NEXT: 11000: b8 01 00 00 00 movl $1, %eax
+
+# REVERT: _bar:
+# REVERT-NEXT: 11000: b8 02 00 00 00 movl $2, %eax
+
+.globl _bar
+.type _bar, @function
+_bar:
+ mov $1, %eax
+
+.globl _start
+_start:
diff --git a/test/ELF/allow-shlib-undefined.s b/test/ELF/allow-shlib-undefined.s
new file mode 100644
index 000000000000..541a7e12007b
--- /dev/null
+++ b/test/ELF/allow-shlib-undefined.s
@@ -0,0 +1,25 @@
+# --allow-shlib-undefined and --no-allow-shlib-undefined are fully
+# ignored in linker implementation.
+# --allow-shlib-undefined is set by default
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+# RUN: %p/Inputs/allow-shlib-undefined.s -o %t
+# RUN: ld.lld -shared %t -o %t.so
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1
+
+# Executable: should link with DSO containing undefined symbols in any case.
+# RUN: ld.lld %t1 %t.so -o %t2
+# RUN: ld.lld --no-allow-shlib-undefined %t1 %t.so -o %t2
+# RUN: ld.lld --allow-shlib-undefined %t1 %t.so -o %t2
+
+# DSO with undefines:
+# should link with or without any of these options.
+# RUN: ld.lld -shared %t -o %t.so
+# RUN: ld.lld -shared --allow-shlib-undefined %t -o %t.so
+# RUN: ld.lld -shared --no-allow-shlib-undefined %t -o %t.so
+
+# Executable still should not link when have undefines inside.
+# RUN: not ld.lld %t -o %t.so
+
+.globl _start
+_start:
+ call _shared
diff --git a/test/ELF/archive.s b/test/ELF/archive.s
new file mode 100644
index 000000000000..41d74451cdd6
--- /dev/null
+++ b/test/ELF/archive.s
@@ -0,0 +1,36 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/archive.s -o %t2
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/archive2.s -o %t3
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/archive3.s -o %t4
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/archive4.s -o %t5
+# RUN: llvm-ar rcs %tar %t2 %t3 %t4
+# RUN: ld.lld %t %tar %t5 -o %tout
+# RUN: llvm-nm %tout | FileCheck %s
+# REQUIRES: x86
+
+# Nothing here. Just needed for the linker to create a undefined _start symbol.
+
+.quad end
+
+.weak foo
+.quad foo
+
+.weak bar
+.quad bar
+
+
+# CHECK: T _start
+# CHECK-NEXT: T bar
+# CHECK-NEXT: T end
+# CHECK-NEXT: w foo
+
+
+# Test that the hitting the first object file after having a lazy symbol for
+# _start is handled correctly.
+# RUN: ld.lld %tar %t -o %tout
+# RUN: llvm-nm %tout | FileCheck --check-prefix=AR-FIRST %s
+
+# AR-FIRST: T _start
+# AR-FIRST-NEXT: w bar
+# AR-FIRST-NEXT: T end
+# AR-FIRST-NEXT: w foo
diff --git a/test/ELF/as-needed.s b/test/ELF/as-needed.s
new file mode 100644
index 000000000000..2c5174d54077
--- /dev/null
+++ b/test/ELF/as-needed.s
@@ -0,0 +1,44 @@
+// 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/shared.s -o %t2.o
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared2.s -o %t3.o
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared3.s -o %t4.o
+// RUN: ld.lld -shared %t2.o -soname shared1 -o %t2.so
+// RUN: ld.lld -shared %t3.o -soname shared2 -o %t3.so
+// RUN: ld.lld -shared %t4.o -soname shared3 -o %t4.so
+
+/// Check if --as-needed actually works.
+
+// RUN: ld.lld %t.o %t2.so %t3.so %t4.so -o %t2
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s
+
+// RUN: ld.lld --as-needed %t.o %t2.so %t3.so %t4.so -o %t2
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck -check-prefix=CHECK2 %s
+
+// RUN: ld.lld --as-needed %t.o %t2.so --no-as-needed %t3.so %t4.so -o %t2
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s
+
+/// GROUP directive is the same as --as-needed.
+
+// 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: ld.lld %t.o %t.script -o %t2
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck -check-prefix=CHECK2 %s
+
+// CHECK: NEEDED SharedLibrary (shared1)
+// CHECK: NEEDED SharedLibrary (shared2)
+// CHECK: NEEDED SharedLibrary (shared3)
+
+// CHECK2: NEEDED SharedLibrary (shared1)
+// CHECK2-NOT: NEEDED SharedLibrary (shared2)
+// CHECK2-NOT: NEEDED SharedLibrary (shared3)
+
+.global _start
+_start:
+.long bar
+.long zed
+.weak baz
+ call baz
diff --git a/test/ELF/basic-aarch64.s b/test/ELF/basic-aarch64.s
new file mode 100644
index 000000000000..28fb10d82edf
--- /dev/null
+++ b/test/ELF/basic-aarch64.s
@@ -0,0 +1,193 @@
+# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %t
+# RUN: ld.lld %t -o %t2
+# RUN: llvm-readobj -file-headers -sections -program-headers -symbols %t2 \
+# RUN: | FileCheck %s
+# REQUIRES: aarch64
+
+# exits with return code 42 on FreeBSD/AArch64
+.globl _start;
+_start:
+ mov x0, 42
+ mov x8, 1
+ svc 0
+
+# CHECK: 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: FreeBSD (0x9)
+# CHECK-NEXT: ABIVersion: 0
+# CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
+# CHECK-NEXT: }
+# CHECK-NEXT: Type: Executable (0x2)
+# CHECK-NEXT: Machine: EM_AARCH64 (0xB7)
+# CHECK-NEXT: Version: 1
+# CHECK-NEXT: Entry: [[ENTRY:0x[0-9A-F]+]]
+# CHECK-NEXT: ProgramHeaderOffset: 0x40
+# CHECK-NEXT: SectionHeaderOffset: 0x1088
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: HeaderSize: 64
+# CHECK-NEXT: ProgramHeaderEntrySize: 56
+# CHECK-NEXT: ProgramHeaderCount: 4
+# CHECK-NEXT: SectionHeaderEntrySize: 64
+# CHECK-NEXT: SectionHeaderCount: 5
+# CHECK-NEXT: StringTableSectionIndex: 3
+# CHECK-NEXT: }
+# CHECK-NEXT: Sections [
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 0
+# CHECK-NEXT: Name: (0)
+# CHECK-NEXT: Type: SHT_NULL (0x0)
+# CHECK-NEXT: Flags [ (0x0)
+# 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: .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: 0x11000
+# CHECK-NEXT: Offset: 0x1000
+# CHECK-NEXT: Size: 12
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 4
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 2
+# CHECK-NEXT: Name: .symtab
+# CHECK-NEXT: Type: SHT_SYMTAB (0x2)
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x0
+# CHECK-NEXT: Offset: 0x1010
+# CHECK-NEXT: Size: 72
+# CHECK-NEXT: Link: 4
+# CHECK-NEXT: Info: 2
+# CHECK-NEXT: AddressAlignment: 8
+# CHECK-NEXT: EntrySize: 24
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 3
+# CHECK-NEXT: Name: .shstrtab
+# CHECK-NEXT: Type: SHT_STRTAB (0x3)
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x0
+# CHECK-NEXT: Offset: 0x1058
+# CHECK-NEXT: Size: 33
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 1
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 4
+# CHECK-NEXT: Name: .strtab (17)
+# CHECK-NEXT: Type: SHT_STRTAB (0x3)
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x0
+# CHECK-NEXT: Offset: 0x1079
+# CHECK-NEXT: Size: 13
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 1
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: 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: $x.0
+# CHECK-NEXT: Value: 0x11000
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Local (0x0)
+# CHECK-NEXT: Type: None (0x0)
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: .text
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: _start
+# CHECK-NEXT: Value: [[ENTRY]]
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global (0x1)
+# CHECK-NEXT: Type: None (0x0)
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: .text
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: 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: 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: 0x10000
+# CHECK-NEXT: PhysicalAddress: 0x10000
+# CHECK-NEXT: FileSize: 288
+# CHECK-NEXT: MemSize: 288
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# 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: 12
+# CHECK-NEXT: MemSize: 12
+# 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
+# CHECK-NEXT: Offset: 0x0
+# CHECK-NEXT: VirtualAddress: 0x0
+# CHECK-NEXT: PhysicalAddress: 0x0
+# CHECK-NEXT: FileSize: 0
+# CHECK-NEXT: MemSize: 0
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: PF_W
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
diff --git a/test/ELF/basic-freebsd.s b/test/ELF/basic-freebsd.s
new file mode 100644
index 000000000000..375fdb5f8078
--- /dev/null
+++ b/test/ELF/basic-freebsd.s
@@ -0,0 +1,25 @@
+# Verify that OSABI is set to the correct value.
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t
+# RUN: ld.lld %t -o %t2
+# RUN: llvm-readobj -file-headers %t2 | FileCheck %s
+# REQUIRES: x86
+
+.globl _start
+_start:
+ mov $1, %rax
+ mov $42, %rdi
+ syscall
+
+# CHECK: 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: FreeBSD (0x9)
+# CHECK-NEXT: ABIVersion: 0
+# CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
+# CHECK-NEXT: }
+# CHECK-NEXT: Type: Executable (0x2)
+# CHECK-NEXT: Machine: EM_X86_64 (0x3E)
diff --git a/test/ELF/basic-mips.s b/test/ELF/basic-mips.s
new file mode 100644
index 000000000000..0c8733f8c9c4
--- /dev/null
+++ b/test/ELF/basic-mips.s
@@ -0,0 +1,272 @@
+# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t.exe
+# RUN: llvm-readobj -file-headers -sections -program-headers -symbols %t.exe \
+# RUN: | FileCheck %s
+
+# REQUIRES: mips
+
+# Exits with return code 1 on Linux.
+ .globl __start
+__start:
+ li $a0,1
+ li $v0,4001
+ syscall
+
+# CHECK: 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: Executable (0x2)
+# CHECK-NEXT: Machine: EM_MIPS (0x8)
+# CHECK-NEXT: Version: 1
+# CHECK-NEXT: Entry: 0x20000
+# CHECK-NEXT: ProgramHeaderOffset: 0x34
+# CHECK-NEXT: SectionHeaderOffset: 0x20084
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: EF_MIPS_ABI_O32
+# CHECK-NEXT: EF_MIPS_ARCH_32R2
+# CHECK-NEXT: EF_MIPS_CPIC
+# CHECK-NEXT: ]
+# CHECK-NEXT: HeaderSize: 52
+# CHECK-NEXT: ProgramHeaderEntrySize: 32
+# CHECK-NEXT: ProgramHeaderCount: 5
+# CHECK-NEXT: SectionHeaderEntrySize: 40
+# CHECK-NEXT: SectionHeaderCount: 9
+# CHECK-NEXT: StringTableSectionIndex: 7
+# CHECK-NEXT: }
+# CHECK-NEXT: Sections [
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 0
+# CHECK-NEXT: Name: (0)
+# CHECK-NEXT: Type: SHT_NULL (0x0)
+# CHECK-NEXT: Flags [ (0x0)
+# 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: .reginfo
+# CHECK-NEXT: Type: SHT_MIPS_REGINFO (0x70000006)
+# CHECK-NEXT: Flags [ (0x2)
+# CHECK-NEXT: SHF_ALLOC (0x2)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x100D4
+# CHECK-NEXT: Offset: 0xD4
+# CHECK-NEXT: Size: 24
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 4
+# CHECK-NEXT: EntrySize: 24
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 2
+# CHECK-NEXT: Name: .MIPS.abiflags
+# CHECK-NEXT: Type: SHT_MIPS_ABIFLAGS (0x7000002A)
+# CHECK-NEXT: Flags [ (0x2)
+# CHECK-NEXT: SHF_ALLOC (0x2)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x100F0
+# CHECK-NEXT: Offset: 0xF0
+# CHECK-NEXT: Size: 24
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 8
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 3
+# CHECK-NEXT: Name: .text (1)
+# 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: 0x20000
+# CHECK-NEXT: Offset: 0x10000
+# CHECK-NEXT: Size: 12
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 16
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 4
+# 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: 0x30000
+# CHECK-NEXT: Offset: 0x20000
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 16
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 5
+# CHECK-NEXT: Name: .bss (7)
+# 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: Size: 0
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 16
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 6
+# 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: Size: 48
+# CHECK-NEXT: Link: 8
+# CHECK-NEXT: Info: 1
+# CHECK-NEXT: AddressAlignment: 4
+# CHECK-NEXT: EntrySize: 16
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 7
+# 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: 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 (46)
+# CHECK-NEXT: Type: SHT_STRTAB (0x3)
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x0
+# CHECK-NEXT: Offset: 0x20074
+# CHECK-NEXT: Size: 13
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 1
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: 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: _gp
+# 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: Absolute (0xFFF1)
+# CHECK-NEXT: }
+# CHECK-NEXT: Symbol {
+# CHECK-NEXT: Name: __start
+# CHECK-NEXT: Value: 0x20000
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global (0x1)
+# CHECK-NEXT: Type: None (0x0)
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: .text
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: ProgramHeaders [
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_PHDR (0x6)
+# CHECK-NEXT: Offset: 0x34
+# CHECK-NEXT: VirtualAddress: 0x10034
+# CHECK-NEXT: PhysicalAddress: 0x10034
+# CHECK-NEXT: FileSize: 160
+# CHECK-NEXT: MemSize: 160
+# 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: 264
+# CHECK-NEXT: MemSize: 264
+# CHECK-NEXT: Flags [ (0x4)
+# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 65536
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD (0x1)
+# CHECK-NEXT: Offset: 0x10000
+# CHECK-NEXT: VirtualAddress: 0x20000
+# CHECK-NEXT: PhysicalAddress: 0x20000
+# CHECK-NEXT: FileSize: 12
+# CHECK-NEXT: MemSize: 12
+# CHECK-NEXT: Flags [ (0x5)
+# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: PF_X (0x1)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 65536
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD (0x1)
+# CHECK-NEXT: Offset: 0x20000
+# CHECK-NEXT: VirtualAddress: 0x30000
+# CHECK-NEXT: PhysicalAddress: 0x30000
+# CHECK-NEXT: FileSize: 0
+# CHECK-NEXT: MemSize: 0
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: PF_W
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 65536
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_GNU_STACK
+# CHECK-NEXT: Offset: 0x0
+# CHECK-NEXT: VirtualAddress: 0x0
+# CHECK-NEXT: PhysicalAddress: 0x0
+# CHECK-NEXT: FileSize: 0
+# CHECK-NEXT: MemSize: 0
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: PF_W
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 0
+# CHECK-NEXT: }
+# CHECK-NEXT:]
diff --git a/test/ELF/basic.s b/test/ELF/basic.s
new file mode 100644
index 000000000000..47b28d41b5bb
--- /dev/null
+++ b/test/ELF/basic.s
@@ -0,0 +1,216 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t2
+# RUN: llvm-readobj -file-headers -sections -program-headers -symbols %t2 \
+# RUN: | FileCheck %s
+
+# exits with return code 42 on linux
+.globl _start;
+_start:
+ mov $60, %rax
+ mov $42, %rdi
+ syscall
+
+# CHECK: 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: Executable (0x2)
+# CHECK-NEXT: Machine: EM_X86_64 (0x3E)
+# CHECK-NEXT: Version: 1
+# CHECK-NEXT: Entry: [[ENTRY:0x[0-9A-F]+]]
+# CHECK-NEXT: ProgramHeaderOffset: 0x40
+# CHECK-NEXT: SectionHeaderOffset: 0x1070
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: HeaderSize: 64
+# CHECK-NEXT: ProgramHeaderEntrySize: 56
+# CHECK-NEXT: ProgramHeaderCount: 4
+# CHECK-NEXT: SectionHeaderEntrySize: 64
+# CHECK-NEXT: SectionHeaderCount: 5
+# CHECK-NEXT: StringTableSectionIndex: 3
+# CHECK-NEXT: }
+# CHECK-NEXT: Sections [
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 0
+# CHECK-NEXT: Name: (0)
+# CHECK-NEXT: Type: SHT_NULL (0x0)
+# CHECK-NEXT: Flags [ (0x0)
+# 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: .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: 0x11000
+# CHECK-NEXT: Offset: 0x1000
+# CHECK-NEXT: Size: 16
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 4
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 2
+# CHECK-NEXT: Name: .symtab
+# CHECK-NEXT: Type: SHT_SYMTAB (0x2)
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x0
+# CHECK-NEXT: Offset: 0x1010
+# CHECK-NEXT: Size: 48
+# CHECK-NEXT: Link: 4
+# CHECK-NEXT: Info: 1
+# CHECK-NEXT: AddressAlignment: 8
+# CHECK-NEXT: EntrySize: 24
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 3
+# CHECK-NEXT: Name: .shstrtab
+# CHECK-NEXT: Type: SHT_STRTAB (0x3)
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x0
+# CHECK-NEXT: Offset: 0x1040
+# CHECK-NEXT: Size: 33
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 1
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 4
+# CHECK-NEXT: Name: .strtab (17)
+# CHECK-NEXT: Type: SHT_STRTAB (0x3)
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x0
+# CHECK-NEXT: Offset: 0x1061
+# CHECK-NEXT: Size: 8
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 1
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: 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: _start
+# CHECK-NEXT: Value: [[ENTRY]]
+# CHECK-NEXT: Size: 0
+# CHECK-NEXT: Binding: Global (0x1)
+# CHECK-NEXT: Type: None (0x0)
+# CHECK-NEXT: Other: 0
+# CHECK-NEXT: Section: .text
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: 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: 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: 0x10000
+# CHECK-NEXT: PhysicalAddress: 0x10000
+# CHECK-NEXT: FileSize: 288
+# CHECK-NEXT: MemSize: 288
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# 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: 16
+# CHECK-NEXT: MemSize: 16
+# 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
+# CHECK-NEXT: Offset: 0x0
+# CHECK-NEXT: VirtualAddress: 0x0
+# CHECK-NEXT: PhysicalAddress: 0x0
+# CHECK-NEXT: FileSize: 0
+# CHECK-NEXT: MemSize: 0
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: PF_W
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+
+# Test for the response file
+# RUN: echo " -o %t2" > %t.responsefile
+# RUN: ld.lld %t @%t.responsefile
+# RUN: llvm-readobj -file-headers -sections -program-headers -symbols %t2 \
+# RUN: | FileCheck %s
+
+# 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
+
+# RUN: not ld.lld -o %t2 2>&1 | \
+# RUN: FileCheck --check-prefix=NO_INPUT %s
+# NO_INPUT: no input files.
+
+# RUN: not ld.lld %t.no.such.file -o %t2 2>&1 | \
+# RUN: FileCheck --check-prefix=CANNOT_OPEN %s
+# CANNOT_OPEN: cannot open {{.*}}.no.such.file: {{[Nn]}}o such file or directory
+
+# RUN: not ld.lld %t -o 2>&1 | FileCheck --check-prefix=NO_O_VAL %s
+# NO_O_VAL: missing arg value for "-o", expected 1 argument.
+
+# RUN: not ld.lld --foo 2>&1 | FileCheck --check-prefix=UNKNOWN %s
+# UNKNOWN: unknown argument: --foo
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: not ld.lld %t %t -o %t2 2>&1 | FileCheck --check-prefix=DUP %s
+# 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
diff --git a/test/ELF/basic32.s b/test/ELF/basic32.s
new file mode 100644
index 000000000000..e5b5c359d59f
--- /dev/null
+++ b/test/ELF/basic32.s
@@ -0,0 +1,163 @@
+# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t2
+# RUN: llvm-readobj -file-headers -sections -program-headers %t2 | FileCheck %s
+# REQUIRES: x86
+
+# exits with return code 42 on linux
+.globl _start;
+_start:
+ mov $1, %eax
+ mov $42, %ebx
+ int $0x80
+
+# CHECK: 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: Executable (0x2)
+# CHECK-NEXT: Machine: EM_386 (0x3)
+# CHECK-NEXT: Version: 1
+# CHECK-NEXT: Entry: 0x11000
+# CHECK-NEXT: ProgramHeaderOffset: 0x34
+# CHECK-NEXT: SectionHeaderOffset: 0x1058
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: HeaderSize: 52
+# CHECK-NEXT: ProgramHeaderEntrySize: 32
+# CHECK-NEXT: ProgramHeaderCount: 4
+# CHECK-NEXT: SectionHeaderEntrySize: 40
+# CHECK-NEXT: SectionHeaderCount: 5
+# CHECK-NEXT: StringTableSectionIndex: 3
+# CHECK-NEXT: }
+# CHECK-NEXT: Sections [
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 0
+# CHECK-NEXT: Name: (0)
+# CHECK-NEXT: Type: SHT_NULL (0x0)
+# CHECK-NEXT: Flags [ (0x0)
+# 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: .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: 0x11000
+# CHECK-NEXT: Offset: 0x1000
+# CHECK-NEXT: Size: 12
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 4
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 2
+# CHECK-NEXT: Name: .symtab
+# CHECK-NEXT: Type: SHT_SYMTAB
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x0
+# CHECK-NEXT: Offset: 0x100C
+# CHECK-NEXT: Size: 32
+# CHECK-NEXT: Link: 4
+# CHECK-NEXT: Info: 1
+# CHECK-NEXT: AddressAlignment: 4
+# CHECK-NEXT: EntrySize: 16
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 3
+# CHECK-NEXT: Name: .shstrtab
+# CHECK-NEXT: Type: SHT_STRTAB (0x3)
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x0
+# CHECK-NEXT: Offset: 0x102C
+# CHECK-NEXT: Size: 33
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 1
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 4
+# CHECK-NEXT: Name: .strtab (17)
+# CHECK-NEXT: Type: SHT_STRTAB (0x3)
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x0
+# CHECK-NEXT: Offset: 0x104D
+# CHECK-NEXT: Size: 8
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 1
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: ProgramHeaders [
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_PHDR (0x6)
+# CHECK-NEXT: Offset: 0x34
+# CHECK-NEXT: VirtualAddress: 0x10034
+# CHECK-NEXT: PhysicalAddress: 0x10034
+# CHECK-NEXT: FileSize: 128
+# CHECK-NEXT: MemSize: 128
+# 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: 180
+# CHECK-NEXT: MemSize: 180
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# 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: 12
+# CHECK-NEXT: MemSize: 12
+# 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
+# CHECK-NEXT: Offset: 0x0
+# CHECK-NEXT: VirtualAddress: 0x0
+# CHECK-NEXT: PhysicalAddress: 0x0
+# CHECK-NEXT: FileSize: 0
+# CHECK-NEXT: MemSize: 0
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: PF_W
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
diff --git a/test/ELF/basic64be.s b/test/ELF/basic64be.s
new file mode 100644
index 000000000000..9534e05b47e0
--- /dev/null
+++ b/test/ELF/basic64be.s
@@ -0,0 +1,260 @@
+# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t
+# RUN: ld.lld -discard-all %t -o %t2
+# RUN: llvm-readobj -file-headers -sections -section-data -program-headers %t2 | FileCheck %s
+# REQUIRES: ppc
+
+# exits with return code 42 on linux
+.section ".opd","aw"
+.global _start
+_start:
+.quad .Lfoo,.TOC.@tocbase,0
+
+# generate .toc and .toc1 sections to make sure that the ordering is as
+# intended (.toc before .toc1, and both before .opd).
+.section ".toc1","aw"
+.quad 22, 37, 89, 47
+
+.section ".toc","aw"
+.quad 45, 86, 72, 24
+
+.text
+.Lfoo:
+ li 0,1
+ li 3,42
+ sc
+
+# CHECK: ElfHeader {
+# CHECK-NEXT: Ident {
+# CHECK-NEXT: Magic: (7F 45 4C 46)
+# CHECK-NEXT: Class: 64-bit (0x2)
+# CHECK-NEXT: DataEncoding: BigEndian (0x2)
+# 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: Executable (0x2)
+# CHECK-NEXT: Machine: EM_PPC64 (0x15)
+# CHECK-NEXT: Version: 1
+# CHECK-NEXT: Entry: 0x10020040
+# CHECK-NEXT: ProgramHeaderOffset: 0x40
+# CHECK-NEXT: SectionHeaderOffset: 0x200C8
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: HeaderSize: 64
+# CHECK-NEXT: ProgramHeaderEntrySize: 56
+# CHECK-NEXT: ProgramHeaderCount: 5
+# CHECK-NEXT: SectionHeaderEntrySize: 64
+# CHECK-NEXT: SectionHeaderCount: 8
+# CHECK-NEXT: StringTableSectionIndex: 6
+# CHECK-NEXT: }
+# CHECK-NEXT: Sections [
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 0
+# CHECK-NEXT: Name: (0)
+# CHECK-NEXT: Type: SHT_NULL (0x0)
+# CHECK-NEXT: Flags [ (0x0)
+# 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: SectionData (
+# CHECK-NEXT: )
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 1
+# CHECK-NEXT: Name: .text (1)
+# 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: 0x10010000
+# CHECK-NEXT: Offset: 0x10000
+# CHECK-NEXT: Size: 12
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 4
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: SectionData (
+# CHECK: )
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 2
+# CHECK-NEXT: Name: .toc
+# 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: 0x10020000
+# CHECK-NEXT: Offset: 0x20000
+# 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: 00000000 0000002D 00000000 00000056 |.......-.......V|
+# CHECK-NEXT: 0010: 00000000 00000048 00000000 00000018 |.......H........|
+# CHECK-NEXT: )
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 3
+# CHECK-NEXT: Name: .toc1
+# 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: 0x10020020
+# CHECK-NEXT: Offset: 0x20020
+# 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: 00000000 00000016 00000000 00000025 |...............%|
+# CHECK-NEXT: 0010: 00000000 00000059 00000000 0000002F |.......Y......./|
+# CHECK-NEXT: )
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 4
+# CHECK-NEXT: Name: .opd
+# 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: 0x10020040
+# CHECK-NEXT: Offset: 0x20040
+# CHECK-NEXT: Size: 24
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# 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: )
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 5
+# CHECK-NEXT: Name: .symtab
+# CHECK-NEXT: Type: SHT_SYMTAB (0x2)
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x0
+# CHECK-NEXT: Offset: 0x20058
+# CHECK-NEXT: Size: 48
+# CHECK-NEXT: Link: 7
+# CHECK-NEXT: Info: 1
+# CHECK-NEXT: AddressAlignment: 8
+# CHECK-NEXT: EntrySize: 24
+# CHECK-NEXT: SectionData (
+# CHECK: )
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 6
+# CHECK-NEXT: Name: .shstrtab
+# CHECK-NEXT: Type: SHT_STRTAB (0x3)
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x0
+# CHECK-NEXT: Offset: 0x20088
+# CHECK-NEXT: Size: 49
+# CHECK-NEXT: Link: 0
+# CHECK-NEXT: Info: 0
+# CHECK-NEXT: AddressAlignment: 1
+# CHECK-NEXT: EntrySize: 0
+# CHECK-NEXT: SectionData (
+# CHECK: )
+# CHECK-NEXT: }
+# CHECK-NEXT: Section {
+# CHECK-NEXT: Index: 7
+# CHECK-NEXT: Name: .strtab (27)
+# CHECK-NEXT: Type: SHT_STRTAB (0x3)
+# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address: 0x0
+# CHECK-NEXT: Offset: 0x200B9
+# 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: 005F7374 61727400 |._start.|
+# CHECK-NEXT: )
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
+# CHECK-NEXT: ProgramHeaders [
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_PHDR (0x6)
+# 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: ]
+# CHECK-NEXT: Alignment: 8
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD (0x1)
+# CHECK-NEXT: Offset: 0x0
+# CHECK-NEXT: VirtualAddress: 0x10000000
+# CHECK-NEXT: PhysicalAddress: 0x10000000
+# CHECK-NEXT: FileSize: 344
+# CHECK-NEXT: MemSize: 344
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 65536
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD (0x1)
+# CHECK-NEXT: Offset: 0x10000
+# CHECK-NEXT: VirtualAddress: 0x10010000
+# CHECK-NEXT: PhysicalAddress: 0x10010000
+# CHECK-NEXT: FileSize: 12
+# CHECK-NEXT: MemSize: 12
+# CHECK-NEXT: Flags [ (0x5)
+# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: PF_X (0x1)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 65536
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD (0x1)
+# CHECK-NEXT: Offset: 0x20000
+# CHECK-NEXT: VirtualAddress: 0x10020000
+# CHECK-NEXT: PhysicalAddress: 0x10020000
+# CHECK-NEXT: FileSize: 88
+# CHECK-NEXT: MemSize: 88
+# CHECK-NEXT: Flags [ (0x6)
+# CHECK-NEXT: PF_R (0x4)
+# CHECK-NEXT: PF_W (0x2)
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 65536
+# 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: ] \ No newline at end of file
diff --git a/test/ELF/bss.s b/test/ELF/bss.s
new file mode 100644
index 000000000000..d0b43ec5a262
--- /dev/null
+++ b/test/ELF/bss.s
@@ -0,0 +1,27 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: ld.lld %t -o %t2
+// RUN: llvm-readobj -sections %t2 | FileCheck %s
+// REQUIRES: x86
+
+// Test that bss takes no space on disk.
+
+// CHECK: Name: .bss
+// CHECK-NEXT: Type: SHT_NOBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x11000
+// CHECK-NEXT: Offset: 0x1000
+// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment:
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: }
+
+ .global _start
+_start:
+
+ .bss
+ .zero 4
diff --git a/test/ELF/comdat.s b/test/ELF/comdat.s
new file mode 100644
index 000000000000..4f8955e289d5
--- /dev/null
+++ b/test/ELF/comdat.s
@@ -0,0 +1,72 @@
+// 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/comdat.s -o %t2.o
+// RUN: ld.lld -shared %t.o %t.o %t2.o -o %t
+// RUN: llvm-objdump -d %t | FileCheck %s
+// RUN: llvm-readobj -s -t %t | FileCheck --check-prefix=READ %s
+// REQUIRES: x86
+
+ .section .text2,"axG",@progbits,foo,comdat,unique,0
+foo:
+ nop
+
+// CHECK: Disassembly of section .text2:
+// CHECK-NEXT: foo:
+// CHECK-NEXT: 1000: {{.*}} nop
+// CHECK-NOT: nop
+
+ .section bar, "ax"
+ call foo
+
+// CHECK: Disassembly of section bar:
+// CHECK-NEXT: bar:
+// 0x1000 - 0x1001 - 5 = -6
+// 0 - 0x1006 - 5 = -4107
+// CHECK-NEXT: 1001: {{.*}} callq -6
+// CHECK-NEXT: 1006: {{.*}} callq -4107
+
+ .section .text3,"axG",@progbits,zed,comdat,unique,0
+
+
+// READ: Name: .text2
+// READ-NEXT: Type: SHT_PROGBITS
+// READ-NEXT: Flags [
+// READ-NEXT: SHF_ALLOC
+// READ-NEXT: SHF_EXECINSTR
+// READ-NEXT: ]
+
+// READ: Name: .text3
+// READ-NEXT: Type: SHT_PROGBITS
+// READ-NEXT: Flags [
+// READ-NEXT: SHF_ALLOC
+// READ-NEXT: SHF_EXECINSTR
+// READ-NEXT: ]
+
+// READ: Symbols [
+// READ-NEXT: Symbol {
+// READ-NEXT: Name: (0)
+// READ-NEXT: Value: 0x0
+// READ-NEXT: Size: 0
+// READ-NEXT: Binding: Local
+// READ-NEXT: Type: None
+// READ-NEXT: Other: 0
+// READ-NEXT: Section: Undefined
+// READ-NEXT: }
+// READ-NEXT: Symbol {
+// READ-NEXT: Name: foo
+// READ-NEXT: Value
+// READ-NEXT: Size: 0
+// READ-NEXT: Binding: Local
+// READ-NEXT: Type: None
+// READ-NEXT: Other: 0
+// READ-NEXT: Section: .text
+// READ-NEXT: }
+// READ-NEXT: Symbol {
+// READ-NEXT: Name: abc
+// READ-NEXT: Value: 0x0
+// READ-NEXT: Size: 0
+// READ-NEXT: Binding: Global
+// READ-NEXT: Type: None
+// READ-NEXT: Other: 0
+// READ-NEXT: Section: Undefined
+// READ-NEXT: }
+// READ-NEXT: ]
diff --git a/test/ELF/common.s b/test/ELF/common.s
new file mode 100644
index 000000000000..67cedbccb866
--- /dev/null
+++ b/test/ELF/common.s
@@ -0,0 +1,56 @@
+// 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/common.s -o %t2
+// RUN: ld.lld %t %t2 -o %t3
+// RUN: llvm-readobj -t -s %t3 | FileCheck %s
+// REQUIRES: x86
+
+// CHECK: Name: .bss
+// CHECK-NEXT: Type: SHT_NOBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x11000
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 22
+
+// CHECK: Name: sym1
+// CHECK-NEXT: Value: 0x11004
+// CHECK-NEXT: Size: 8
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .bss
+
+// CHECK: Name: sym2
+// CHECK-NEXT: Value: 0x1100C
+// CHECK-NEXT: Size: 8
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .bss
+
+// CHECK: Name: sym3
+// CHECK-NEXT: Value: 0x11014
+// CHECK-NEXT: Size: 2
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .bss
+
+// CHECK: Name: sym4
+// CHECK-NEXT: Value: 0x11000
+// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .bss
+
+
+.globl _start
+_start:
+
+.comm sym1,4,4
+.comm sym2,8,4
+.comm sym3,2,2
+.comm sym4,4,2
diff --git a/test/ELF/default-output.s b/test/ELF/default-output.s
new file mode 100644
index 000000000000..8da3bb40eac0
--- /dev/null
+++ b/test/ELF/default-output.s
@@ -0,0 +1,16 @@
+# REQUIRES: x86
+# Verify that default output filename is a.out.
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: mkdir -p %t.dir
+# RUN: cd %t.dir
+# RUN: rm -f a.out
+# RUN: not llvm-readobj a.out > /dev/null 2>&1
+# RUN: ld.lld %t
+# RUN: llvm-readobj a.out > /dev/null 2>&1
+
+.globl _start;
+_start:
+ mov $60, %rax
+ mov $42, %rdi
+ syscall
diff --git a/test/ELF/discard-locals.s b/test/ELF/discard-locals.s
new file mode 100644
index 000000000000..073e891c3143
--- /dev/null
+++ b/test/ELF/discard-locals.s
@@ -0,0 +1,50 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -save-temp-labels %s -o %t
+// RUN: ld.lld -discard-locals %t -o %t2
+// RUN: llvm-readobj -s -sd -t %t2 | FileCheck %s
+// REQUIRES: x86
+
+.global _start
+_start:
+
+.text
+.Lmyvar:
+.Lmyothervar:
+
+// CHECK: Section {
+// 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: 005F7374 61727400 |._start.|
+// CHECK-NEXT: )
+// CHECK-NEXT: }
+// 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: ]
diff --git a/test/ELF/discard-merge-locals.s b/test/ELF/discard-merge-locals.s
new file mode 100644
index 000000000000..51676da192ca
--- /dev/null
+++ b/test/ELF/discard-merge-locals.s
@@ -0,0 +1,24 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: ld.lld %t -o %t2 -shared
+// RUN: llvm-readobj -t %t2 | FileCheck %s
+// REQUIRES: x86
+
+ leaq .L.str(%rip), %rdi
+
+ .section .rodata.str1.1,"aMS",@progbits,1
+.L.str:
+ .asciz "foobar"
+
+// Test that the .L symbol is omitted
+
+// 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: ]
diff --git a/test/ELF/discard-merge-unnamed.s b/test/ELF/discard-merge-unnamed.s
new file mode 100644
index 000000000000..bd0058cbd7db
--- /dev/null
+++ b/test/ELF/discard-merge-unnamed.s
@@ -0,0 +1,16 @@
+// RUN: ld.lld %p/Inputs/discard-merge-unnamed.o -o %t2 -shared
+// RUN: llvm-readobj -t %t2 | FileCheck %s
+
+// Test that the unnamed symbol is SHF_MERGE is omitted.
+
+// 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: ]
diff --git a/test/ELF/discard-none.s b/test/ELF/discard-none.s
new file mode 100644
index 000000000000..a9d54bae9ace
--- /dev/null
+++ b/test/ELF/discard-none.s
@@ -0,0 +1,54 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -save-temp-labels %s -o %t
+// RUN: ld.lld -discard-none -shared %t -o %t2
+// RUN: llvm-readobj -s -sd -t %t2 | FileCheck %s
+// REQUIRES: x86
+
+.text
+.Lmyvar:
+.Lmyothervar:
+
+// CHECK: Section {
+// 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: 002E4C6D 79766172 002E4C6D 796F7468 |..Lmyvar..Lmyoth|
+// CHECK-NEXT: 0010: 65727661 7200 |ervar.|
+// CHECK-NEXT: )
+// CHECK-NEXT: }
+
+// CHECK: 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: .Lmyothervar
+// CHECK-NEXT: Value: 0x1000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: .Lmyvar
+// CHECK-NEXT: Value: 0x1000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
diff --git a/test/ELF/dt_flags.s b/test/ELF/dt_flags.s
new file mode 100644
index 000000000000..a1d8d77433a5
--- /dev/null
+++ b/test/ELF/dt_flags.s
@@ -0,0 +1,21 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld -shared %t -o %t.so
+# RUN: ld.lld -z now -z nodelete -z origin -Bsymbolic %t %t.so -o %t1
+# RUN: ld.lld %t %t.so -o %t2
+# RUN: llvm-readobj -dynamic-table %t1 | FileCheck -check-prefix=FLAGS %s
+# RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s
+
+# FLAGS: DynamicSection [
+# FLAGS: 0x000000000000001E FLAGS ORIGIN SYMBOLIC BIND_NOW
+# FLAGS: 0x000000006FFFFFFB FLAGS_1 NOW NODELETE ORIGIN
+# FLAGS: ]
+
+# CHECK: DynamicSection [
+# CHECK-NOT: 0x000000000000001E FLAGS ORIGIN SYMBOLIC BIND_NOW
+# CHECK-NOT: 0x000000006FFFFFFB FLAGS_1 NOW NODELETE ORIGIN
+# CHECK: ]
+
+.globl _start
+_start:
diff --git a/test/ELF/duplicate-internal.s b/test/ELF/duplicate-internal.s
new file mode 100644
index 000000000000..2395a6cae0db
--- /dev/null
+++ b/test/ELF/duplicate-internal.s
@@ -0,0 +1,11 @@
+# Should print an expected message in case of conflict with an internally generated symbol.
+
+# 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 {{.*}}
+
+# REQUIRES: mips
+
+ .globl _gp
+_gp = 0
diff --git a/test/ELF/dynamic-reloc-index.s b/test/ELF/dynamic-reloc-index.s
new file mode 100644
index 000000000000..2d38c014a307
--- /dev/null
+++ b/test/ELF/dynamic-reloc-index.s
@@ -0,0 +1,21 @@
+// 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: ld.lld -shared %t2.o -o %t2.so
+// RUN: ld.lld %t.o %t2.so -o %t
+// RUN: llvm-readobj -r %t | FileCheck %s
+
+// We used to record the wrong symbol index for this test
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.plt {
+// CHECK-NEXT: 0x13018 R_X86_64_JUMP_SLOT bar 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+ .global foobar
+foobar:
+ .global zedx
+zedx:
+ .global _start
+_start:
+.quad bar
diff --git a/test/ELF/dynamic-reloc-weak.s b/test/ELF/dynamic-reloc-weak.s
new file mode 100644
index 000000000000..fe1b7eedb6d7
--- /dev/null
+++ b/test/ELF/dynamic-reloc-weak.s
@@ -0,0 +1,33 @@
+// 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: ld.lld -shared %t2.o -o %t2.so
+// RUN: ld.lld %t.o %t2.so -o %t
+// RUN: llvm-readobj -r %t | FileCheck %s
+// REQUIRES: x86
+
+ .globl _start
+_start:
+ .type sym1,@function
+ .weak sym1
+ .long sym1@gotpcrel
+
+ .type sym2,@function
+ .weak sym2
+ .long sym2@plt
+
+ .type sym3,@function
+ .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.
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: 0x{{.*}} R_X86_64_GLOB_DAT sym1 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: Section ({{.*}}) .rela.plt {
+// CHECK-NEXT: 0x{{.*}} R_X86_64_JUMP_SLOT sym2 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ] \ No newline at end of file
diff --git a/test/ELF/dynamic-reloc.s b/test/ELF/dynamic-reloc.s
new file mode 100644
index 000000000000..ab2a2405726b
--- /dev/null
+++ b/test/ELF/dynamic-reloc.s
@@ -0,0 +1,64 @@
+// 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.s -o %t3.o
+// RUN: ld.lld -shared %t2.o -o %t2.so
+// RUN: ld.lld %t.o %t3.o %t2.so -o %t
+// RUN: llvm-readobj -dynamic-table -r --expand-relocs -s %t | FileCheck %s
+// REQUIRES: x86
+
+// CHECK: Index: 1
+// CHECK-NEXT: Name: .dynsym
+
+// CHECK: Name: .rela.plt
+// CHECK-NEXT: Type: SHT_RELA
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: [[RELAADDR:.*]]
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: [[RELASIZE:.*]]
+// CHECK-NEXT: Link: 1
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 8
+// CHECK-NEXT: EntrySize: 24
+
+// 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: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.plt {
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset: 0x13018
+// CHECK-NEXT: Type: R_X86_64_JUMP_SLOT
+// CHECK-NEXT: Symbol: bar
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+// CHECK: DynamicSection [
+// CHECK-NEXT: Tag Type Name/Value
+// CHECK-NEXT: 0x0000000000000017 JMPREL
+// CHECK-NEXT: 0x0000000000000002 PLTRELSZ 24 (bytes)
+// CHECK-NEXT: 0x0000000000000003 PLTGOT
+// CHECK-NEXT: 0x0000000000000014 PLTREL RELA
+// CHECK-NEXT: 0x0000000000000006 SYMTAB
+// CHECK-NEXT: 0x000000000000000B SYMENT 24 (bytes)
+// CHECK-NEXT: 0x0000000000000005 STRTAB
+// CHECK-NEXT: 0x000000000000000A STRSZ
+// CHECK-NEXT: 0x0000000000000004 HASH
+// CHECK-NEXT: 0x0000000000000001 NEEDED SharedLibrary ({{.*}}2.so)
+// CHECK-NEXT: 0x0000000000000000 NULL 0x0
+// CHECK-NEXT: ]
+
+.global _start
+_start:
+.quad bar + 0x42
+.weak foo
+.quad foo
+call main
diff --git a/test/ELF/eh-align-cie.s b/test/ELF/eh-align-cie.s
new file mode 100644
index 000000000000..e85cbd27d4fd
--- /dev/null
+++ b/test/ELF/eh-align-cie.s
@@ -0,0 +1,57 @@
+// REQUIRES: x86
+
+ .cfi_startproc
+ .cfi_personality 0x1b, bar
+ .cfi_endproc
+
+.global bar
+.hidden bar
+bar:
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: llvm-readobj -s -section-data %t.o | FileCheck --check-prefix=OBJ %s
+
+// Check the size of the CIE (0x18 + 4) an FDE (0x10 + 4)
+// OBJ: Name: .eh_frame
+// OBJ-NEXT: Type:
+// OBJ-NEXT: Flags [
+// OBJ-NEXT: SHF_ALLOC
+// OBJ-NEXT: ]
+// OBJ-NEXT: Address:
+// OBJ-NEXT: Offset:
+// OBJ-NEXT: Size:
+// OBJ-NEXT: Link:
+// OBJ-NEXT: Info:
+// OBJ-NEXT: AddressAlignment:
+// OBJ-NEXT: EntrySize:
+// OBJ-NEXT: SectionData (
+// OBJ-NEXT: 0000: 18000000 00000000 017A5052 00017810
+// OBJ-NEXT: 0010: 061B0000 00001B0C 07089001 10000000
+// OBJ-NEXT: 0020: 20000000 00000000 00000000 00000000
+// OBJ-NEXT: )
+
+
+// RUN: ld.lld %t.o -o %t -shared
+// RUN: llvm-readobj -s -section-data %t | FileCheck %s
+
+// Check that the size of the CIE was changed to (0x1C + 4) and the FDE one was
+// changed to (0x14 + 4)
+
+// CHECK: Name: .eh_frame
+// CHECK-NEXT: Type:
+// CHECK-NEXT: Flags
+// CHECK-NEXT: SHF_ALLOC
+// 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: 1C000000 00000000 017A5052 00017810
+// CHECK-NEXT: 0010: 061B260E 00001B0C 07089001 00000000
+// CHECK-NEXT: 0020: 14000000 24000000 100E0000 00000000
+// CHECK-NEXT: 0030: 00000000 00000000
+// CHECK-NEXT: )
diff --git a/test/ELF/eh-frame-merge.s b/test/ELF/eh-frame-merge.s
new file mode 100644
index 000000000000..2b0e4a52822d
--- /dev/null
+++ b/test/ELF/eh-frame-merge.s
@@ -0,0 +1,58 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o %t.o -o %t -shared
+// RUN: llvm-readobj -s -section-data %t | FileCheck %s
+
+ .section foo,"ax",@progbits
+ .cfi_startproc
+ nop
+ .cfi_endproc
+
+ .section bar,"axG",@progbits,foo,comdat
+ .cfi_startproc
+ nop
+ nop
+ .cfi_endproc
+
+// FIXME: We could really use a .eh_frame parser.
+// The intention is to show that:
+// * There is only one copy of the CIE
+// * There are two copies of the first FDE
+// * There is only one copy of the second FDE
+
+// CHECK: Name: .eh_frame
+// CHECK-NEXT: Type: SHT_X86_64_UNWIND
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address:
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 96
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 8
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 14000000 00000000 017A5200 01781001 |
+// CHECK-NEXT: 0010: 1B0C0708 90010000 14000000 1C000000 |
+// CHECK-NEXT: 0020: 180E0000 01000000 00000000 00000000 |
+// CHECK-NEXT: 0030: 14000000 34000000 020E0000 02000000 |
+// CHECK-NEXT: 0040: 00000000 00000000 14000000 4C000000 |
+// CHECK-NEXT: 0050: E90D0000 01000000 00000000 00000000 |
+// CHECK-NEXT: )
+
+// CHECK: Name: foo
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_EXECINSTR
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x1000
+
+// CHECK: Name: bar
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_EXECINSTR
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x1002
diff --git a/test/ELF/eh-frame-plt.s b/test/ELF/eh-frame-plt.s
new file mode 100644
index 000000000000..e84d93c7f88b
--- /dev/null
+++ b/test/ELF/eh-frame-plt.s
@@ -0,0 +1,16 @@
+// 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 %t
+// RUN: llvm-readobj -r %t | FileCheck %s
+
+ .globl _start
+_start:
+ .cfi_startproc
+ .cfi_personality 3, bar
+ .cfi_endproc
+
+// CHECK: Section ({{.*}}) .rela.plt {
+// CHECK-NEXT: R_X86_64_JUMP_SLOT bar 0x0
+// CHECK-NEXT: }
diff --git a/test/ELF/eh-frame-rel.s b/test/ELF/eh-frame-rel.s
new file mode 100644
index 000000000000..a417dc126087
--- /dev/null
+++ b/test/ELF/eh-frame-rel.s
@@ -0,0 +1,7 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o %t.o -o %t -shared
+// We used to try to read the relocations as RELA and error out
+
+ .cfi_startproc
+ .cfi_endproc
diff --git a/test/ELF/eh-frame-type.test b/test/ELF/eh-frame-type.test
new file mode 100644
index 000000000000..f59ab116d7dd
--- /dev/null
+++ b/test/ELF/eh-frame-type.test
@@ -0,0 +1,16 @@
+# RUN: yaml2obj -format elf %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
+
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .eh_frame
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
diff --git a/test/ELF/ehframe-relocation.s b/test/ELF/ehframe-relocation.s
new file mode 100644
index 000000000000..f952ebc60865
--- /dev/null
+++ b/test/ELF/ehframe-relocation.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
+// 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: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x10120
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 0
+
+// 0x10120 = 65824
+// 0x10120 + 5 = 65829
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: _start:
+// DISASM-NEXT: 11000: {{.*}} movq 65824, %rax
+// DISASM-NEXT: 11008: {{.*}} movq 65829, %rax
+
+.section .eh_frame,"ax",@unwind
+
+.section .text
+.globl _start
+_start:
+ movq .eh_frame, %rax
+ movq .eh_frame + 5, %rax
diff --git a/test/ELF/empty-archive.s b/test/ELF/empty-archive.s
new file mode 100644
index 000000000000..ffb0a7814419
--- /dev/null
+++ b/test/ELF/empty-archive.s
@@ -0,0 +1,3 @@
+// RUN: llvm-ar rc %t.a
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld -shared %t.o %t.a -o t
diff --git a/test/ELF/emulation.s b/test/ELF/emulation.s
new file mode 100644
index 000000000000..a8a8f398c42c
--- /dev/null
+++ b/test/ELF/emulation.s
@@ -0,0 +1,177 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %tx64
+# RUN: ld.lld -m elf_x86_64 %tx64 -o %t2x64
+# RUN: llvm-readobj -file-headers %t2x64 | FileCheck --check-prefix=X86-64 %s
+# RUN: ld.lld %tx64 -o %t3x64
+# RUN: llvm-readobj -file-headers %t3x64 | FileCheck --check-prefix=X86-64 %s
+# X86-64: ElfHeader {
+# X86-64-NEXT: Ident {
+# X86-64-NEXT: Magic: (7F 45 4C 46)
+# X86-64-NEXT: Class: 64-bit (0x2)
+# X86-64-NEXT: DataEncoding: LittleEndian (0x1)
+# X86-64-NEXT: FileVersion: 1
+# X86-64-NEXT: OS/ABI: SystemV (0x0)
+# X86-64-NEXT: ABIVersion: 0
+# X86-64-NEXT: Unused: (00 00 00 00 00 00 00)
+# X86-64-NEXT: }
+# X86-64-NEXT: Type: Executable (0x2)
+# X86-64-NEXT: Machine: EM_X86_64 (0x3E)
+# X86-64-NEXT: Version: 1
+# X86-64-NEXT: Entry:
+# X86-64-NEXT: ProgramHeaderOffset: 0x40
+# X86-64-NEXT: SectionHeaderOffset:
+# X86-64-NEXT: Flags [ (0x0)
+# X86-64-NEXT: ]
+# X86-64-NEXT: HeaderSize: 64
+# X86-64-NEXT: ProgramHeaderEntrySize: 56
+# X86-64-NEXT: ProgramHeaderCount:
+# X86-64-NEXT: SectionHeaderEntrySize: 64
+# X86-64-NEXT: SectionHeaderCount:
+# X86-64-NEXT: StringTableSectionIndex:
+# X86-64-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
+# RUN: ld.lld %tx86 -o %t3x86
+# RUN: llvm-readobj -file-headers %t3x86 | FileCheck --check-prefix=X86 %s
+# X86: ElfHeader {
+# X86-NEXT: Ident {
+# X86-NEXT: Magic: (7F 45 4C 46)
+# X86-NEXT: Class: 32-bit (0x1)
+# X86-NEXT: DataEncoding: LittleEndian (0x1)
+# X86-NEXT: FileVersion: 1
+# X86-NEXT: OS/ABI: SystemV (0x0)
+# X86-NEXT: ABIVersion: 0
+# X86-NEXT: Unused: (00 00 00 00 00 00 00)
+# X86-NEXT: }
+# X86-NEXT: Type: Executable (0x2)
+# X86-NEXT: Machine: EM_386 (0x3)
+# X86-NEXT: Version: 1
+# X86-NEXT: Entry:
+# X86-NEXT: ProgramHeaderOffset: 0x34
+# X86-NEXT: SectionHeaderOffset:
+# X86-NEXT: Flags [ (0x0)
+# X86-NEXT: ]
+# X86-NEXT: HeaderSize: 52
+# X86-NEXT: ProgramHeaderEntrySize: 32
+# X86-NEXT: ProgramHeaderCount:
+# X86-NEXT: SectionHeaderEntrySize: 40
+# X86-NEXT: SectionHeaderCount:
+# X86-NEXT: StringTableSectionIndex:
+# X86-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
+# RUN: ld.lld %tppc64 -o %t3ppc64
+# RUN: llvm-readobj -file-headers %t3ppc64 | FileCheck --check-prefix=PPC64 %s
+# PPC64: ElfHeader {
+# PPC64-NEXT: Ident {
+# PPC64-NEXT: Magic: (7F 45 4C 46)
+# PPC64-NEXT: Class: 64-bit (0x2)
+# PPC64-NEXT: DataEncoding: BigEndian (0x2)
+# PPC64-NEXT: FileVersion: 1
+# PPC64-NEXT: OS/ABI: SystemV (0x0)
+# PPC64-NEXT: ABIVersion: 0
+# PPC64-NEXT: Unused: (00 00 00 00 00 00 00)
+# PPC64-NEXT: }
+# PPC64-NEXT: Type: Executable (0x2)
+# PPC64-NEXT: Machine: EM_PPC64 (0x15)
+# PPC64-NEXT: Version: 1
+# PPC64-NEXT: Entry:
+# PPC64-NEXT: ProgramHeaderOffset: 0x40
+# PPC64-NEXT: SectionHeaderOffset:
+# PPC64-NEXT: Flags [ (0x0)
+# PPC64-NEXT: ]
+# PPC64-NEXT: HeaderSize: 64
+# PPC64-NEXT: ProgramHeaderEntrySize: 56
+# PPC64-NEXT: ProgramHeaderCount:
+# PPC64-NEXT: SectionHeaderEntrySize: 64
+# PPC64-NEXT: SectionHeaderCount:
+# PPC64-NEXT: StringTableSectionIndex:
+# PPC64-NEXT: }
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %tmips
+# RUN: ld.lld -m elf32btsmip -e _start %tmips -o %t2mips
+# RUN: llvm-readobj -file-headers %t2mips | FileCheck --check-prefix=MIPS %s
+# RUN: ld.lld %tmips -e _start -o %t3mips
+# RUN: llvm-readobj -file-headers %t3mips | FileCheck --check-prefix=MIPS %s
+# MIPS: ElfHeader {
+# MIPS-NEXT: Ident {
+# MIPS-NEXT: Magic: (7F 45 4C 46)
+# MIPS-NEXT: Class: 32-bit (0x1)
+# MIPS-NEXT: DataEncoding: BigEndian (0x2)
+# MIPS-NEXT: FileVersion: 1
+# MIPS-NEXT: OS/ABI: SystemV (0x0)
+# MIPS-NEXT: ABIVersion: 0
+# MIPS-NEXT: Unused: (00 00 00 00 00 00 00)
+# MIPS-NEXT: }
+# MIPS-NEXT: Type: Executable (0x2)
+# MIPS-NEXT: Machine: EM_MIPS (0x8)
+# MIPS-NEXT: Version: 1
+# MIPS-NEXT: Entry:
+# MIPS-NEXT: ProgramHeaderOffset: 0x34
+# MIPS-NEXT: SectionHeaderOffset:
+# MIPS-NEXT: Flags [
+# MIPS-NEXT: EF_MIPS_ABI_O32
+# MIPS-NEXT: EF_MIPS_ARCH_32R2
+# MIPS-NEXT: EF_MIPS_CPIC
+# MIPS-NEXT: ]
+
+# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %tmipsel
+# RUN: ld.lld -m elf32ltsmip -e _start %tmipsel -o %t2mipsel
+# RUN: llvm-readobj -file-headers %t2mipsel | FileCheck --check-prefix=MIPSEL %s
+# RUN: ld.lld -melf32ltsmip -e _start %tmipsel -o %t2mipsel
+# RUN: llvm-readobj -file-headers %t2mipsel | FileCheck --check-prefix=MIPSEL %s
+# RUN: ld.lld %tmipsel -e _start -o %t3mipsel
+# RUN: llvm-readobj -file-headers %t3mipsel | FileCheck --check-prefix=MIPSEL %s
+# MIPSEL: ElfHeader {
+# MIPSEL-NEXT: Ident {
+# MIPSEL-NEXT: Magic: (7F 45 4C 46)
+# MIPSEL-NEXT: Class: 32-bit (0x1)
+# MIPSEL-NEXT: DataEncoding: LittleEndian (0x1)
+# MIPSEL-NEXT: FileVersion: 1
+# MIPSEL-NEXT: OS/ABI: SystemV (0x0)
+# MIPSEL-NEXT: ABIVersion: 0
+# MIPSEL-NEXT: Unused: (00 00 00 00 00 00 00)
+# MIPSEL-NEXT: }
+# MIPSEL-NEXT: Type: Executable (0x2)
+# MIPSEL-NEXT: Machine: EM_MIPS (0x8)
+# MIPSEL-NEXT: Version: 1
+# MIPSEL-NEXT: Entry:
+# MIPSEL-NEXT: ProgramHeaderOffset: 0x34
+# MIPSEL-NEXT: SectionHeaderOffset:
+# MIPSEL-NEXT: Flags [
+# MIPSEL-NEXT: EF_MIPS_ABI_O32
+# MIPSEL-NEXT: EF_MIPS_ARCH_32R2
+# MIPSEL-NEXT: EF_MIPS_CPIC
+# MIPSEL-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
+# RUN: ld.lld %taarch64 -o %t3aarch64
+# RUN: llvm-readobj -file-headers %t3aarch64 | FileCheck --check-prefix=AARCH64 %s
+# AARCH64: ElfHeader {
+# AARCH64-NEXT: Ident {
+# AARCH64-NEXT: Magic: (7F 45 4C 46)
+# AARCH64-NEXT: Class: 64-bit (0x2)
+# AARCH64-NEXT: DataEncoding: LittleEndian (0x1)
+# AARCH64-NEXT: FileVersion: 1
+# AARCH64-NEXT: OS/ABI: SystemV (0x0)
+# AARCH64-NEXT: ABIVersion: 0
+# AARCH64-NEXT: Unused: (00 00 00 00 00 00 00)
+# AARCH64-NEXT: }
+# AARCH64-NEXT: Type: Executable (0x2)
+# AARCH64-NEXT: Machine: EM_AARCH64 (0xB7)
+# AARCH64-NEXT: Version: 1
+# AARCH64-NEXT: Entry:
+# AARCH64-NEXT: ProgramHeaderOffset: 0x40
+# AARCH64-NEXT: SectionHeaderOffset:
+# AARCH64-NEXT: Flags [ (0x0)
+# AARCH64-NEXT: ]
+
+# REQUIRES: x86,ppc,mips,aarch64
+
+.globl _start;
+_start:
diff --git a/test/ELF/end-preserve.s b/test/ELF/end-preserve.s
new file mode 100644
index 000000000000..71d86d1c8faf
--- /dev/null
+++ b/test/ELF/end-preserve.s
@@ -0,0 +1,16 @@
+// Should preserve the value of the "end" symbol if it is defined.
+// 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-nm %t | FileCheck %s
+
+// CHECK: 0000000000000005 A end
+
+.global _start,end
+end = 5
+.text
+_start:
+ nop
+.bss
+ .space 6
diff --git a/test/ELF/end-update.s b/test/ELF/end-update.s
new file mode 100644
index 000000000000..8654ef1e92eb
--- /dev/null
+++ b/test/ELF/end-update.s
@@ -0,0 +1,29 @@
+// Should set the value of the "end" symbol if it is undefined.
+// 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
+
+// CHECK: Sections [
+// CHECK: Name: .bss
+// CHECK-NEXT: Type:
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x12000
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 6
+// CHECK: ]
+// CHECK: Symbols [
+// CHECK: Name: end
+// CHECK-NEXT: Value: 0x12006
+// CHECK: ]
+
+.global _start,end
+.text
+_start:
+ nop
+.bss
+ .space 6
diff --git a/test/ELF/end.s b/test/ELF/end.s
new file mode 100644
index 000000000000..390e4445e2d8
--- /dev/null
+++ b/test/ELF/end.s
@@ -0,0 +1,79 @@
+// Should set the value of the "_end" symbol to the end of the data segment.
+// REQUIRES: x86
+
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+
+// By default, the .bss section is the latest section of the data segment.
+// RUN: ld.lld %t.o -o %t
+// RUN: llvm-readobj -sections -symbols %t | FileCheck %s --check-prefix=DEFAULT
+
+// DEFAULT: Sections [
+// DEFAULT: Name: .bss
+// DEFAULT-NEXT: Type:
+// DEFAULT-NEXT: Flags [
+// DEFAULT-NEXT: SHF_ALLOC
+// DEFAULT-NEXT: SHF_WRITE
+// DEFAULT-NEXT: ]
+// DEFAULT-NEXT: Address: 0x12002
+// DEFAULT-NEXT: Offset:
+// DEFAULT-NEXT: Size: 6
+// DEFAULT: ]
+// DEFAULT: Symbols [
+// DEFAULT: Name: _end
+// DEFAULT-NEXT: Value: 0x12008
+// DEFAULT: ]
+
+// If there is no .bss section, "_end" should point to the end of the .data section.
+// RUN: echo "SECTIONS { \
+// RUN: /DISCARD/ : { *(.bss) } }" > %t.script
+// RUN: ld.lld %t.o --script %t.script -o %t
+// RUN: llvm-readobj -sections -symbols %t | FileCheck %s --check-prefix=NOBSS
+
+// NOBSS: Sections [
+// NOBSS: Name: .data
+// NOBSS-NEXT: Type:
+// NOBSS-NEXT: Flags [
+// NOBSS-NEXT: SHF_ALLOC
+// NOBSS-NEXT: SHF_WRITE
+// NOBSS-NEXT: ]
+// NOBSS-NEXT: Address: 0x12000
+// NOBSS-NEXT: Offset:
+// NOBSS-NEXT: Size: 2
+// NOBSS: ]
+// NOBSS: Symbols [
+// NOBSS: Name: _end
+// NOBSS-NEXT: Value: 0x12002
+// NOBSS: ]
+
+// If the layout of the sections is changed, "_end" should point to the end of allocated address space.
+// 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-prefix=TEXTATEND
+
+// TEXTATEND: Sections [
+// TEXTATEND: Name: .text
+// TEXTATEND-NEXT: Type:
+// TEXTATEND-NEXT: Flags [
+// TEXTATEND-NEXT: SHF_ALLOC
+// TEXTATEND-NEXT: SHF_EXECINSTR
+// TEXTATEND-NEXT: ]
+// TEXTATEND-NEXT: Address: 0x12000
+// TEXTATEND-NEXT: Offset:
+// TEXTATEND-NEXT: Size: 1
+// TEXTATEND: ]
+// TEXTATEND: Symbols [
+// TEXTATEND: Name: _end
+// TEXTATEND-NEXT: Value: 0x12001
+// TEXTATEND: ]
+
+.global _start,_end
+.text
+_start:
+ nop
+.data
+ .word 1
+.bss
+ .space 6
diff --git a/test/ELF/entry.s b/test/ELF/entry.s
new file mode 100644
index 000000000000..c8758ece69eb
--- /dev/null
+++ b/test/ELF/entry.s
@@ -0,0 +1,21 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1
+# RUN: not ld.lld %t1 -o %t2
+# RUN: ld.lld %t1 -o %t2 -e entry
+# 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: llvm-readobj -file-headers %t2 | FileCheck -check-prefix=DEC %s
+# RUN: ld.lld %t1 -o %t2 -e 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
+
+# SYM: Entry: 0x11000
+# DSO: Entry: 0x1000
+# DEC: Entry: 0x1000
+# HEX: Entry: 0xCAFE
+# OCT: Entry: 0x1FF
+
+.globl entry
+entry:
diff --git a/test/ELF/gc-sections-eh.s b/test/ELF/gc-sections-eh.s
new file mode 100644
index 000000000000..042b68ebdfe2
--- /dev/null
+++ b/test/ELF/gc-sections-eh.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 %t2 --gc-sections
+# RUN: llvm-readobj -t %t2 | FileCheck %s
+
+# CHECK-NOT: foo
+
+ .section .text,"ax",@progbits,unique,0
+ .globl foo
+foo:
+ .cfi_startproc
+ .cfi_endproc
+
+ .section .text,"ax",@progbits,unique,1
+ .globl _start
+_start:
+ .cfi_startproc
+ .cfi_endproc
diff --git a/test/ELF/gc-sections-print.s b/test/ELF/gc-sections-print.s
new file mode 100644
index 000000000000..59177a65367e
--- /dev/null
+++ b/test/ELF/gc-sections-print.s
@@ -0,0 +1,23 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld %t --gc-sections --print-gc-sections -o %t2 2>&1 | FileCheck -check-prefix=PRINT %s
+
+# PRINT: removing unused section from '.text.x' in file
+# PRINT-NEXT: removing unused section from '.text.y' in file
+
+.globl _start
+.protected a, x, y
+_start:
+ call a
+
+.section .text.a,"ax",@progbits
+a:
+ nop
+
+.section .text.x,"ax",@progbits
+x:
+ nop
+
+.section .text.y,"ax",@progbits
+y:
+ nop
diff --git a/test/ELF/gc-sections.s b/test/ELF/gc-sections.s
new file mode 100644
index 000000000000..93f7dc67023f
--- /dev/null
+++ b/test/ELF/gc-sections.s
@@ -0,0 +1,102 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t2
+# RUN: llvm-readobj -sections -symbols %t2 | FileCheck -check-prefix=NOGC %s
+# RUN: ld.lld --gc-sections %t -o %t2
+# RUN: llvm-readobj -sections -symbols %t2 | FileCheck -check-prefix=GC1 %s
+# RUN: ld.lld --export-dynamic --gc-sections %t -o %t2
+# RUN: llvm-readobj -sections -symbols %t2 | FileCheck -check-prefix=GC2 %s
+
+# NOGC: Name: .eh_frame
+# NOGC: Name: .text
+# NOGC: Name: .ctors
+# NOGC: Name: .dtors
+# NOGC: Name: .init
+# NOGC: Name: .fini
+# NOGC: Name: a
+# NOGC: Name: b
+# NOGC: Name: c
+# NOGC: Name: x
+# NOGC: Name: y
+# NOGC: Name: __preinit_array_start
+# NOGC: Name: __preinit_array_end
+# NOGC: Name: d
+
+# GC1: Name: .eh_frame
+# GC1: Name: .text
+# GC1: Name: .ctors
+# GC1: Name: .dtors
+# GC1: Name: .init
+# GC1: Name: .fini
+# GC1: Name: a
+# GC1: Name: b
+# GC1: Name: c
+# GC1-NOT: Name: x
+# GC1-NOT: Name: y
+# GC1: Name: __preinit_array_start
+# GC1: Name: __preinit_array_end
+# GC1-NOT: Name: d
+
+# GC2: Name: .eh_frame
+# GC2: Name: .text
+# GC2: Name: .ctors
+# GC2: Name: .dtors
+# GC2: Name: .init
+# GC2: Name: .fini
+# GC2: Name: a
+# GC2: Name: b
+# GC2: Name: c
+# GC2-NOT: Name: x
+# GC2-NOT: Name: y
+# GC2: Name: __preinit_array_start
+# GC2: Name: __preinit_array_end
+# GC2: Name: d
+
+.globl _start, d
+.protected a, b, c, x, y
+_start:
+ call a
+
+.section .text.a,"ax",@progbits
+a:
+ call _start
+ call b
+
+.section .text.b,"ax",@progbits
+b:
+ call c
+
+.section .text.c,"ax",@progbits
+c:
+ nop
+
+.section .text.d,"ax",@progbits
+d:
+ nop
+
+.section .text.x,"ax",@progbits
+x:
+ call y
+
+.section .text.y,"ax",@progbits
+y:
+ call x
+
+.section .ctors,"aw",@progbits
+ .quad 0
+
+.section .dtors,"aw",@progbits
+ .quad 0
+
+.section .init,"aw",@init_array
+ .quad 0
+
+.section .fini,"aw",@fini_array
+ .quad 0
+
+.section .preinit_array,"aw",@preinit_array
+ .quad 0
+
+.section .eh_frame,"a",@unwind
+ .quad 0
diff --git a/test/ELF/global_offset_table.s b/test/ELF/global_offset_table.s
new file mode 100644
index 000000000000..47e95e9f9b84
--- /dev/null
+++ b/test/ELF/global_offset_table.s
@@ -0,0 +1,5 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: ld.lld %t -o %t2
+.global _start
+_start:
+.long _GLOBAL_OFFSET_TABLE_
diff --git a/test/ELF/gnu-hash-table.s b/test/ELF/gnu-hash-table.s
new file mode 100644
index 000000000000..4e845998f167
--- /dev/null
+++ b/test/ELF/gnu-hash-table.s
@@ -0,0 +1,195 @@
+# REQUIRES: x86,ppc
+
+# RUN: echo ".globl foo" > %te.s
+# RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %te.s -o %te-i386.o
+# RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t-i386.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t-x86_64.o
+# RUN: llvm-mc -filetype=obj -triple=powerpc64-pc-linux %s -o %t-ppc64.o
+
+# RUN: ld.lld -shared --hash-style=gnu -o %te-i386.so %te-i386.o
+# RUN: ld.lld -shared -hash-style=gnu -o %t-i386.so %t-i386.o
+# RUN: ld.lld -shared -hash-style=gnu -o %t-x86_64.so %t-x86_64.o
+# RUN: ld.lld -shared --hash-style both -o %t-ppc64.so %t-ppc64.o
+
+# RUN: llvm-readobj -dyn-symbols -gnu-hash-table %te-i386.so \
+# RUN: | FileCheck %s -check-prefix=EMPTY
+# RUN: llvm-readobj -sections -dyn-symbols -gnu-hash-table %t-i386.so \
+# RUN: | FileCheck %s -check-prefix=I386
+# RUN: llvm-readobj -sections -dyn-symbols -gnu-hash-table %t-x86_64.so \
+# RUN: | FileCheck %s -check-prefix=X86_64
+# RUN: llvm-readobj -sections -dyn-symbols -gnu-hash-table %t-ppc64.so \
+# RUN: | FileCheck %s -check-prefix=PPC64
+
+# EMPTY: DynamicSymbols [
+# EMPTY: Symbol {
+# EMPTY: Name: foo@
+# EMPTY-NEXT: Value: 0x0
+# EMPTY-NEXT: Size: 0
+# EMPTY-NEXT: Binding: Global
+# EMPTY-NEXT: Type: None
+# EMPTY-NEXT: Other: 0
+# EMPTY-NEXT: Section: Undefined
+# EMPTY-NEXT: }
+# EMPTY-NEXT: ]
+# EMPTY: GnuHashTable {
+# EMPTY-NEXT: Num Buckets: 0
+# EMPTY-NEXT: First Hashed Symbol Index: 2
+# EMPTY-NEXT: Num Mask Words: 1
+# EMPTY-NEXT: Shift Count: 5
+# EMPTY-NEXT: Bloom Filter: [0x0]
+# EMPTY-NEXT: Buckets: []
+# EMPTY-NEXT: Values: []
+# EMPTY-NEXT: }
+
+# I386: Format: ELF32-i386
+# I386: Arch: i386
+# I386: AddressSize: 32bit
+# I386: Sections [
+# I386: Name: .gnu.hash
+# I386-NEXT: Type: SHT_GNU_HASH
+# I386-NEXT: Flags [
+# I386-NEXT: SHF_ALLOC
+# I386-NEXT: ]
+# I386-NEXT: Address:
+# I386-NEXT: Offset:
+# I386-NEXT: Size: 32
+# I386-NEXT: Link:
+# I386-NEXT: Info: 0
+# I386-NEXT: AddressAlignment: 4
+# I386-NEXT: EntrySize: 4
+# I386: ]
+# I386: DynamicSymbols [
+# I386: Symbol {
+# I386: Name: @
+# I386: Binding: Local
+# I386: Section: Undefined
+# I386: }
+# I386: Symbol {
+# I386: Name: baz@
+# I386: Binding: Global
+# I386: Section: Undefined
+# I386: }
+# I386: Symbol {
+# I386: Name: bar@
+# I386: Binding: Global
+# I386: Section: .text
+# I386: }
+# I386: Symbol {
+# I386: Name: foo@
+# I386: Binding: Global
+# I386: Section: .text
+# I386: }
+# I386: ]
+# I386: GnuHashTable {
+# I386-NEXT: Num Buckets: 1
+# I386-NEXT: First Hashed Symbol Index: 2
+# I386-NEXT: Num Mask Words: 1
+# I386-NEXT: Shift Count: 5
+# I386-NEXT: Bloom Filter: [0x14000220]
+# I386-NEXT: Buckets: [2]
+# I386-NEXT: Values: [0xB8860BA, 0xB887389]
+# I386-NEXT: }
+
+# X86_64: Format: ELF64-x86-64
+# X86_64: Arch: x86_64
+# X86_64: AddressSize: 64bit
+# X86_64: Sections [
+# X86_64: Name: .gnu.hash
+# X86_64-NEXT: Type: SHT_GNU_HASH
+# X86_64-NEXT: Flags [
+# X86_64-NEXT: SHF_ALLOC
+# X86_64-NEXT: ]
+# X86_64-NEXT: Address:
+# X86_64-NEXT: Offset:
+# X86_64-NEXT: Size: 36
+# X86_64-NEXT: Link:
+# X86_64-NEXT: Info: 0
+# X86_64-NEXT: AddressAlignment: 8
+# X86_64-NEXT: EntrySize: 0
+# X86_64-NEXT: }
+# X86_64: ]
+# X86_64: DynamicSymbols [
+# X86_64: Symbol {
+# X86_64: Name: @
+# X86_64: Binding: Local
+# X86_64: Section: Undefined
+# X86_64: }
+# X86_64: Symbol {
+# X86_64: Name: baz@
+# X86_64: Binding: Global
+# X86_64: Section: Undefined
+# X86_64: }
+# X86_64: Symbol {
+# X86_64: Name: bar@
+# X86_64: Binding: Global
+# X86_64: Section: .text
+# X86_64: }
+# X86_64: Symbol {
+# X86_64: Name: foo@
+# X86_64: Binding: Global
+# X86_64: Section: .text
+# X86_64: }
+# X86_64: ]
+# X86_64: GnuHashTable {
+# X86_64-NEXT: Num Buckets: 1
+# X86_64-NEXT: First Hashed Symbol Index: 2
+# X86_64-NEXT: Num Mask Words: 1
+# X86_64-NEXT: Shift Count: 6
+# X86_64-NEXT: Bloom Filter: [0x400000000004204]
+# X86_64-NEXT: Buckets: [2]
+# X86_64-NEXT: Values: [0xB8860BA, 0xB887389]
+# X86_64-NEXT: }
+
+# PPC64: Format: ELF64-ppc64
+# PPC64: Arch: powerpc64
+# PPC64: AddressSize: 64bit
+# PPC64: Sections [
+# PPC64: Name: .gnu.hash
+# PPC64-NEXT: Type: SHT_GNU_HASH
+# PPC64-NEXT: Flags [
+# PPC64-NEXT: SHF_ALLOC
+# PPC64-NEXT: ]
+# PPC64-NEXT: Address: 0x228
+# PPC64-NEXT: Offset: 0x228
+# PPC64-NEXT: Size: 36
+# PPC64-NEXT: Link: 1
+# PPC64-NEXT: Info: 0
+# PPC64-NEXT: AddressAlignment: 8
+# PPC64-NEXT: EntrySize: 0
+# PPC64-NEXT: }
+# PPC64: ]
+# PPC64: DynamicSymbols [
+# PPC64: Symbol {
+# PPC64: Name: @
+# PPC64: Binding: Local
+# PPC64: Section: Undefined
+# PPC64: }
+# PPC64: Symbol {
+# PPC64: Name: baz@
+# PPC64: Binding: Global
+# PPC64: Section: Undefined
+# PPC64: }
+# PPC64: Symbol {
+# PPC64: Name: bar@
+# PPC64: Binding: Global
+# PPC64: Section: .text
+# PPC64: }
+# PPC64: Symbol {
+# PPC64: Name: foo@
+# PPC64: Binding: Global
+# PPC64: Section: .text
+# PPC64: }
+# PPC64: ]
+# PPC64: GnuHashTable {
+# PPC64-NEXT: Num Buckets: 1
+# PPC64-NEXT: First Hashed Symbol Index: 2
+# PPC64-NEXT: Num Mask Words: 1
+# PPC64-NEXT: Shift Count: 6
+# PPC64-NEXT: Bloom Filter: [0x400000000004204]
+# PPC64-NEXT: Buckets: [2]
+# PPC64-NEXT: Values: [0xB8860BA, 0xB887389]
+# PPC64-NEXT: }
+
+.globl foo,bar,baz
+foo:
+bar:
diff --git a/test/ELF/gnu-ifunc-i386.s b/test/ELF/gnu-ifunc-i386.s
new file mode 100644
index 000000000000..6dcdf256d70c
--- /dev/null
+++ b/test/ELF/gnu-ifunc-i386.s
@@ -0,0 +1,130 @@
+// 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
+// REQUIRES: x86
+
+// 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: [[RELA:.*]]
+// CHECK-NEXT: Offset: 0xD4
+// CHECK-NEXT: Size: 16
+// CHECK-NEXT: Link: 5
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 4
+// CHECK-NEXT: EntrySize: 8
+// CHECK-NEXT: }
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rel.plt {
+// CHECK-NEXT: 0x1200C R_386_IRELATIVE
+// CHECK-NEXT: 0x12010 R_386_IRELATIVE
+// CHECK-NEXT: }
+// 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: __rel_iplt_end
+// CHECK-NEXT: Value: 0x100E4
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Absolute
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: __rel_iplt_start
+// CHECK-NEXT: Value: [[RELA]]
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Absolute
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: _start
+// CHECK-NEXT: Value: 0x11002
+// 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: bar
+// CHECK-NEXT: Value: 0x11001
+// 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: }
+// CHECK-NEXT:]
+
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: foo:
+// DISASM-NEXT: 11000: c3 retl
+// DISASM: bar:
+// DISASM-NEXT: 11001: c3 retl
+// DISASM: _start:
+// DISASM-NEXT: 11002: e8 29 00 00 00 calll 41
+// DISASM-NEXT: 11007: e8 34 00 00 00 calll 52
+// DISASM-NEXT: 1100c: ba d4 00 01 00 movl $65748, %edx
+// DISASM-NEXT: 11011: ba e4 00 01 00 movl $65764, %edx
+// DISASM-NEXT: Disassembly of section .plt:
+// DISASM-NEXT: .plt:
+// DISASM-NEXT: 11020: ff 35 04 20 01 00 pushl 73732
+// DISASM-NEXT: 11026: ff 25 08 20 01 00 jmpl *73736
+// DISASM-NEXT: 1102c: 90 nop
+// DISASM-NEXT: 1102d: 90 nop
+// DISASM-NEXT: 1102e: 90 nop
+// DISASM-NEXT: 1102f: 90 nop
+// DISASM-NEXT: 11030: ff 25 0c 20 01 00 jmpl *73740
+// DISASM-NEXT: 11036: 68 00 00 00 00 pushl $0
+// DISASM-NEXT: 1103b: e9 e0 ff ff ff jmp -32 <.plt>
+// DISASM-NEXT: 11040: ff 25 10 20 01 00 jmpl *73744
+// DISASM-NEXT: 11046: 68 08 00 00 00 pushl $8
+// DISASM-NEXT: 1104b: e9 d0 ff ff ff jmp -48 <.plt>
+
+.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
+
+.globl _start
+_start:
+ call foo
+ call bar
+ movl $__rel_iplt_start,%edx
+ movl $__rel_iplt_end,%edx
diff --git a/test/ELF/gnu-ifunc-nosym-i386.s b/test/ELF/gnu-ifunc-nosym-i386.s
new file mode 100644
index 000000000000..1101b6d763d5
--- /dev/null
+++ b/test/ELF/gnu-ifunc-nosym-i386.s
@@ -0,0 +1,29 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
+// RUN: ld.lld -static %t.o -o %tout
+// RUN: llvm-readobj -symbols %tout | FileCheck %s
+// REQUIRES: x86
+
+// 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: ]
+
+.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
+
+.globl _start
+_start:
+ call foo
+ call bar
diff --git a/test/ELF/gnu-ifunc-nosym.s b/test/ELF/gnu-ifunc-nosym.s
new file mode 100644
index 000000000000..c97fd749c02b
--- /dev/null
+++ b/test/ELF/gnu-ifunc-nosym.s
@@ -0,0 +1,29 @@
+// 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 -symbols %tout | FileCheck %s
+// REQUIRES: x86
+
+// 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: ]
+
+.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
+
+.globl _start
+_start:
+ call foo
+ call bar
diff --git a/test/ELF/gnu-ifunc.s b/test/ELF/gnu-ifunc.s
new file mode 100644
index 000000000000..b04f2758e22c
--- /dev/null
+++ b/test/ELF/gnu-ifunc.s
@@ -0,0 +1,126 @@
+// 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
+// REQUIRES: x86
+
+// CHECK: Sections [
+// CHECK: Section {
+// CHECK: Index: 1
+// CHECK-NEXT: Name: .rela.plt
+// CHECK-NEXT: Type: SHT_RELA
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: [[RELA:.*]]
+// CHECK-NEXT: Offset: 0x158
+// CHECK-NEXT: Size: 48
+// CHECK-NEXT: Link: 5
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 8
+// CHECK-NEXT: EntrySize: 24
+// CHECK-NEXT: }
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.plt {
+// CHECK-NEXT: 0x12018 R_X86_64_IRELATIVE
+// CHECK-NEXT: 0x12020 R_X86_64_IRELATIVE
+// CHECK-NEXT: }
+// 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: __rela_iplt_end
+// CHECK-NEXT: Value: 0x10188
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Absolute
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: __rela_iplt_start
+// CHECK-NEXT: Value: [[RELA]]
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Absolute
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: _start
+// CHECK-NEXT: Value: 0x11002
+// 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: bar
+// CHECK-NEXT: Value: 0x11001
+// 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: }
+// CHECK-NEXT: ]
+
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: foo:
+// DISASM-NEXT: 11000: c3 retq
+// DISASM: bar:
+// DISASM-NEXT: 11001: c3 retq
+// DISASM: _start:
+// DISASM-NEXT: 11002: e8 29 00 00 00 callq 41
+// 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: Disassembly of section .plt:
+// DISASM-NEXT: .plt:
+// DISASM-NEXT: 11020: ff 35 e2 0f 00 00 pushq 4066(%rip)
+// DISASM-NEXT: 11026: ff 25 e4 0f 00 00 jmpq *4068(%rip)
+// DISASM-NEXT: 1102c: 0f 1f 40 00 nopl (%rax)
+// DISASM-NEXT: 11030: ff 25 e2 0f 00 00 jmpq *4066(%rip)
+// DISASM-NEXT: 11036: 68 00 00 00 00 pushq $0
+// DISASM-NEXT: 1103b: e9 e0 ff ff ff jmp -32
+// DISASM-NEXT: 11040: ff 25 da 0f 00 00 jmpq *4058(%rip)
+// DISASM-NEXT: 11046: 68 01 00 00 00 pushq $1
+// DISASM-NEXT: 1104b: e9 d0 ff ff ff jmp -48
+
+.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
+
+.globl _start
+_start:
+ call foo
+ call bar
+ movl $__rela_iplt_start,%edx
+ movl $__rela_iplt_end,%edx
diff --git a/test/ELF/gnu-unique.s b/test/ELF/gnu-unique.s
new file mode 100644
index 000000000000..f7206cf8c97f
--- /dev/null
+++ b/test/ELF/gnu-unique.s
@@ -0,0 +1,24 @@
+// 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
+
+// Check that STB_GNU_UNIQUE is treated as a global and ends up in the dynamic
+// symbol table as STB_GNU_UNIQUE.
+
+.global _start
+.text
+_start:
+
+.data
+.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: }
diff --git a/test/ELF/gnustack.s b/test/ELF/gnustack.s
new file mode 100644
index 000000000000..6fc937354e69
--- /dev/null
+++ b/test/ELF/gnustack.s
@@ -0,0 +1,30 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1
+# RUN: ld.lld %t1 -z execstack -o %t
+# RUN: llvm-readobj --program-headers -s %t | FileCheck --check-prefix=RWX %s
+# RUN: ld.lld %t1 -o %t
+# RUN: llvm-readobj --program-headers -s %t | FileCheck --check-prefix=RW %s
+
+# RW: Sections [
+# RW-NOT: Name: .note.GNU-stack
+# RW: ProgramHeaders [
+# RW: ProgramHeader {
+# RW: Type: PT_GNU_STACK
+# RW-NEXT: Offset: 0x0
+# RW-NEXT: VirtualAddress: 0x0
+# RW-NEXT: PhysicalAddress: 0x0
+# RW-NEXT: FileSize: 0
+# RW-NEXT: MemSize: 0
+# RW-NEXT: Flags [
+# RW-NEXT: PF_R
+# RW-NEXT: PF_W
+# RW-NEXT: ]
+# RW-NEXT: Alignment: 0
+# RW-NEXT: }
+# RW-NEXT: ]
+
+# RWX-NOT: Name: .note.GNU-stack
+# RWX-NOT: Type: PT_GNU_STACK
+
+.globl _start
+_start:
diff --git a/test/ELF/got-aarch64.s b/test/ELF/got-aarch64.s
new file mode 100644
index 000000000000..b4aa456b4e81
--- /dev/null
+++ b/test/ELF/got-aarch64.s
@@ -0,0 +1,40 @@
+// RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %t.o
+// RUN: ld.lld -shared %t.o -o %t.so
+// RUN: llvm-readobj -s -r %t.so | FileCheck %s
+// RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s
+// REQUIRES: aarch64
+
+// 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-NEXT: Offset:
+// CHECK-NEXT: Size: 8
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 8
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: 0x2090 R_AARCH64_GLOB_DAT dat 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+// Page(0x2098) - Page(0x1000) = 0x1000 = 4096
+// 0x2098 & 0xff8 = 0x98 = 152
+
+// DISASM: main:
+// DISASM-NEXT: 1000: {{.*}} adrp x0, #4096
+// DISASM-NEXT: 1004: {{.*}} ldr x0, [x0, #144]
+
+.global main,foo,dat
+.text
+main:
+ adrp x0, :got:dat
+ ldr x0, [x0, :got_lo12:dat]
+.data
+dat:
+ .word 42
diff --git a/test/ELF/got-i386.s b/test/ELF/got-i386.s
new file mode 100644
index 000000000000..679eb2e4f5ca
--- /dev/null
+++ b/test/ELF/got-i386.s
@@ -0,0 +1,56 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t
+// RUN: llvm-readobj -s -r -t %t | FileCheck %s
+// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
+// REQUIRES: x86
+
+// 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: 0
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment:
+
+// 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
+// CHECK-NEXT: }
+
+// 0x12000 - 0 = addr(.got) = 0x12000
+// 0x1200A - 10 = addr(.got) = 0x12000
+// 0x1200A + 5 - 15 = addr(.got) = 0x12000
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: _start:
+// DISASM-NEXT: 11000: c7 81 00 00 00 00 01 00 00 00 movl $1, (%ecx)
+// DISASM-NEXT: 1100a: c7 81 0a 00 00 00 02 00 00 00 movl $2, 10(%ecx)
+// DISASM-NEXT: 11014: c7 81 0f 00 00 00 03 00 00 00 movl $3, 15(%ecx)
+
+.global _start
+_start:
+ movl $1, bar@GOTOFF(%ecx)
+ movl $2, obj@GOTOFF(%ecx)
+ movl $3, obj+5@GOTOFF(%ecx)
+ .type bar, @object
+ .comm bar, 10
+ .type obj, @object
+ .comm obj, 10
diff --git a/test/ELF/got.s b/test/ELF/got.s
new file mode 100644
index 000000000000..5fa1c2a7251f
--- /dev/null
+++ b/test/ELF/got.s
@@ -0,0 +1,45 @@
+// 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: ld.lld -shared %t2.o -o %t2.so
+// RUN: ld.lld %t.o %t2.so -o %t
+// RUN: llvm-readobj -s -r %t | FileCheck %s
+// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
+// REQUIRES: x86
+
+// CHECK: Name: .got
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x120A0
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 16
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 8
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: 0x120A0 R_X86_64_GLOB_DAT bar 0x0
+// CHECK-NEXT: 0x120A8 R_X86_64_GLOB_DAT zed 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+
+// Unfortunately FileCheck can't do math, so we have to check for explicit
+// values:
+// 0x120A0 - (0x11000 + 2) - 4 = 4250
+// 0x120A0 - (0x11006 + 2) - 4 = 4244
+// 0x120A8 - (0x1100c + 2) - 4 = 4246
+
+// DISASM: _start:
+// DISASM-NEXT: 11000: {{.*}} jmpq *4250(%rip)
+// DISASM-NEXT: 11006: {{.*}} jmpq *4244(%rip)
+// DISASM-NEXT: 1100c: {{.*}} jmpq *4246(%rip)
+
+.global _start
+_start:
+ jmp *bar@GOTPCREL(%rip)
+ jmp *bar@GOTPCREL(%rip)
+ jmp *zed@GOTPCREL(%rip)
diff --git a/test/ELF/incompatible-ar-first.s b/test/ELF/incompatible-ar-first.s
new file mode 100644
index 000000000000..8a8aaec220dd
--- /dev/null
+++ b/test/ELF/incompatible-ar-first.s
@@ -0,0 +1,11 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/archive.s -o %ta.o
+// RUN: llvm-ar rc %t.a %ta.o
+// RUN: llvm-mc -filetype=obj -triple=i686-linux %s -o %tb.o
+// RUN: not ld.lld %t.a %tb.o 2>&1 | FileCheck %s
+
+// We used to crash when
+// * The first object seen by the symbol table is from an archive.
+// * -m was not used.
+// CHECK: a.o is incompatible with {{.*}}b.o
+
+// REQUIRES: x86
diff --git a/test/ELF/incompatible.s b/test/ELF/incompatible.s
new file mode 100644
index 000000000000..1696d83de7ac
--- /dev/null
+++ b/test/ELF/incompatible.s
@@ -0,0 +1,58 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %ta.o
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %tb.o
+// RUN: ld.lld -shared %tb.o -o %ti686.so
+// RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %tc.o
+
+// RUN: not ld.lld %ta.o %tb.o -o %t 2>&1 | \
+// RUN: FileCheck --check-prefix=A-AND-B %s
+// A-AND-B: b.o is incompatible with {{.*}}a.o
+
+// RUN: not ld.lld %tb.o %tc.o -o %t 2>&1 | \
+// RUN: FileCheck --check-prefix=B-AND-C %s
+// B-AND-C: c.o is incompatible with {{.*}}b.o
+
+// RUN: not ld.lld %ta.o %ti686.so -o %t 2>&1 | \
+// RUN: FileCheck --check-prefix=A-AND-SO %s
+// A-AND-SO: i686.so is incompatible with {{.*}}a.o
+
+// RUN: not ld.lld %tc.o %ti686.so -o %t 2>&1 | \
+// RUN: FileCheck --check-prefix=C-AND-SO %s
+// C-AND-SO: i686.so is incompatible with {{.*}}c.o
+
+// RUN: not ld.lld %ti686.so %tc.o -o %t 2>&1 | \
+// RUN: FileCheck --check-prefix=SO-AND-C %s
+// SO-AND-C: c.o is incompatible with {{.*}}i686.so
+
+// RUN: not ld.lld -m elf64ppc %ta.o -o %t 2>&1 | \
+// RUN: FileCheck --check-prefix=A-ONLY %s
+// A-ONLY: a.o is incompatible with elf64ppc
+
+// RUN: not ld.lld -m elf64ppc %tb.o -o %t 2>&1 | \
+// RUN: FileCheck --check-prefix=B-ONLY %s
+// B-ONLY: b.o is incompatible with elf64ppc
+
+// RUN: not ld.lld -m elf64ppc %tc.o -o %t 2>&1 | \
+// RUN: FileCheck --check-prefix=C-ONLY %s
+// C-ONLY: c.o is incompatible with elf64ppc
+
+// RUN: not ld.lld -m elf_i386 %tc.o %ti686.so -o %t 2>&1 | \
+// RUN: FileCheck --check-prefix=C-AND-SO-I386 %s
+// C-AND-SO-I386: c.o is incompatible with elf_i386
+
+// RUN: not ld.lld -m elf_i386 %ti686.so %tc.o -o %t 2>&1 | \
+// RUN: FileCheck --check-prefix=SO-AND-C-I386 %s
+// SO-AND-C-I386: c.o is incompatible with elf_i386
+
+
+// We used to fail to identify this incompatibility and crash trying to
+// read a 64 bit file as a 32 bit one.
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/archive2.s -o %ta.o
+// RUN: llvm-ar rc %t.a %ta.o
+// RUN: llvm-mc -filetype=obj -triple=i686-linux %s -o %tb.o
+// RUN: not ld.lld %t.a %tb.o 2>&1 | FileCheck --check-prefix=ARCHIVE %s
+// ARCHIVE: a.o is incompatible with {{.*}}b.o
+.global _start
+_start:
+ .long foo
+
+// REQUIRES: x86,aarch64
diff --git a/test/ELF/init-fini.s b/test/ELF/init-fini.s
new file mode 100644
index 000000000000..d2b24088d1e1
--- /dev/null
+++ b/test/ELF/init-fini.s
@@ -0,0 +1,43 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+// Should use "_init" and "_fini" by default when fills dynamic table
+// RUN: ld.lld -shared %t -o %t2
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=BYDEF %s
+// BYDEF: INIT 0x11010
+// BYDEF: FINI 0x11020
+
+// -init and -fini override symbols to use
+// RUN: ld.lld -shared %t -o %t2 -init _foo -fini _bar
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=OVR %s
+// OVR: INIT 0x11030
+// OVR: FINI 0x11040
+
+// Check aliases as well
+// RUN: ld.lld -shared %t -o %t2 -init=_foo -fini=_bar
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=OVR %s
+
+// Should add a dynamic table entry even if a given symbol stay undefined
+// RUN: ld.lld -shared %t -o %t2 -init=_undef -fini=_undef
+// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=UNDEF %s
+// UNDEF: INIT 0x0
+// UNDEF: FINI 0x0
+
+// Should not add new entries to the symbol table
+// and should not require given symbols to be resolved
+// RUN: ld.lld -shared %t -o %t2 -init=_unknown -fini=_unknown
+// RUN: llvm-readobj -symbols -dynamic-table %t2 | FileCheck --check-prefix=NOENTRY %s
+// NOENTRY: Symbols [
+// NOENTRY-NOT: Name: _unknown
+// NOENTRY: ]
+// NOENTRY: DynamicSection [
+// NOENTRY-NOT: INIT
+// NOENTRY-NOT: FINI
+// NOENTRY: ]
+
+.global _start,_init,_fini,_foo,_bar,_undef;
+_start:
+_init = 0x11010
+_fini = 0x11020
+_foo = 0x11030
+_bar = 0x11040
diff --git a/test/ELF/invalid-cie-length.s b/test/ELF/invalid-cie-length.s
new file mode 100644
index 000000000000..36d1e03fb567
--- /dev/null
+++ b/test/ELF/invalid-cie-length.s
@@ -0,0 +1,9 @@
+// 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
+ .byte 0
+
+// CHECK: Truncated CIE/FDE length
diff --git a/test/ELF/invalid-cie-length2.s b/test/ELF/invalid-cie-length2.s
new file mode 100644
index 000000000000..94a677eb8913
--- /dev/null
+++ b/test/ELF/invalid-cie-length2.s
@@ -0,0 +1,9 @@
+// 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 42
+
+// CHECK: CIE/FIE ends past the end of the section
diff --git a/test/ELF/invalid-cie-length3.s b/test/ELF/invalid-cie-length3.s
new file mode 100644
index 000000000000..8f3ab1cf29d0
--- /dev/null
+++ b/test/ELF/invalid-cie-length3.s
@@ -0,0 +1,9 @@
+// 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 0xFFFFFFFC
+
+// CHECK: CIE/FIE size is too large
diff --git a/test/ELF/invalid-cie-length4.s b/test/ELF/invalid-cie-length4.s
new file mode 100644
index 000000000000..4a51ca1f812d
--- /dev/null
+++ b/test/ELF/invalid-cie-length4.s
@@ -0,0 +1,10 @@
+// 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
+ .byte 0
+
+// CHECK: Truncated CIE/FDE length
diff --git a/test/ELF/invalid-cie-length5.s b/test/ELF/invalid-cie-length5.s
new file mode 100644
index 000000000000..14054a2dee84
--- /dev/null
+++ b/test/ELF/invalid-cie-length5.s
@@ -0,0 +1,10 @@
+// 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 0xFFFFFFFFFFFFFFF4
+
+// CHECK: CIE/FIE size is too large
diff --git a/test/ELF/invalid-cie-reference.s b/test/ELF/invalid-cie-reference.s
new file mode 100644
index 000000000000..1b099d19b7e1
--- /dev/null
+++ b/test/ELF/invalid-cie-reference.s
@@ -0,0 +1,32 @@
+// 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 0x14
+ .long 0x0
+ .byte 0x01
+ .byte 0x7a
+ .byte 0x52
+ .byte 0x00
+ .byte 0x01
+ .byte 0x78
+ .byte 0x10
+ .byte 0x01
+ .byte 0x1b
+ .byte 0x0c
+ .byte 0x07
+ .byte 0x08
+ .byte 0x90
+ .byte 0x01
+ .short 0x0
+
+ .long 0x14
+ .long 0x1b
+ .long .text
+ .long 0x0
+ .long 0x0
+ .long 0x0
+
+// CHECK: Invalid CIE reference
diff --git a/test/ELF/invalid-elf.test b/test/ELF/invalid-elf.test
new file mode 100644
index 000000000000..05e95cab0d27
--- /dev/null
+++ b/test/ELF/invalid-elf.test
@@ -0,0 +1,34 @@
+# RUN: llvm-mc %s -o %t -filetype=obj -triple x86_64-pc-linux
+
+# 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
+
+# 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
+
+# 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
+
+# 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: not ld.lld %p/Inputs/invalid-shstrndx.so -o %t2 2>&1 | \
+# RUN: FileCheck --check-prefix=INVALID-SECTION-INDEX %s
+
+# RUN: not ld.lld %p/Inputs/invalid-shentsize-zero.elf -o %t2 2>&1 | \
+# RUN: FileCheck --check-prefix=INVALID-SHENTSIZE-ZERO %s
+# INVALID-SHENTSIZE-ZERO: SHF_MERGE section size must be a multiple of sh_entsize
+
+# 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
+
+.long foo
diff --git a/test/ELF/invalid-fde-rel.s b/test/ELF/invalid-fde-rel.s
new file mode 100644
index 000000000000..9fb73d2158de
--- /dev/null
+++ b/test/ELF/invalid-fde-rel.s
@@ -0,0 +1,32 @@
+// 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 0x14
+ .long 0x0
+ .byte 0x01
+ .byte 0x7a
+ .byte 0x52
+ .byte 0x00
+ .byte 0x01
+ .byte 0x78
+ .byte 0x10
+ .byte 0x01
+ .byte 0x1b
+ .byte 0x0c
+ .byte 0x07
+ .byte 0x08
+ .byte 0x90
+ .byte 0x01
+ .short 0x0
+
+ .long 0x14
+ .long 0x1c
+ .long 0x0
+ .long 0x0
+ .long 0x0
+ .long 0x0
+
+// CHECK: FDE doesn't reference another section
diff --git a/test/ELF/invalid-relocations.test b/test/ELF/invalid-relocations.test
new file mode 100644
index 000000000000..2b4a6c4a4210
--- /dev/null
+++ b/test/ELF/invalid-relocations.test
@@ -0,0 +1,22 @@
+# RUN: yaml2obj -format elf %s -o %t
+# RUN: not ld.lld %t -o %tout 2>&1 | FileCheck %s
+
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Type: SHT_PROGBITS
+ - Name: .rela.text
+ Type: SHT_RELA
+ Info: 12 # Invalid index
+ Relocations:
+ - Offset: 0x0000000000000001
+ Symbol: lulz
+ Type: R_X86_64_PC32
+Symbols:
+ Global:
+ - Name: lulz
+
+# CHECK: Invalid relocated section index
diff --git a/test/ELF/libsearch.s b/test/ELF/libsearch.s
new file mode 100644
index 000000000000..c965b9ba91fc
--- /dev/null
+++ b/test/ELF/libsearch.s
@@ -0,0 +1,83 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+// RUN: %p/Inputs/libsearch-dyn.s -o %tdyn.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+// RUN: %p/Inputs/libsearch-st.s -o %tst.o
+// RUN: mkdir -p %t.dir
+// RUN: ld.lld -shared %tdyn.o -o %t.dir/libls.so
+// RUN: cp -f %t.dir/libls.so %t.dir/libls2.so
+// RUN: rm -f %t.dir/libls.a
+// RUN: llvm-ar rcs %t.dir/libls.a %tst.o
+// REQUIRES: x86
+
+// Should fail if no library specified
+// RUN: not ld.lld -l 2>&1 \
+// RUN: | FileCheck --check-prefix=NOLIBRARY %s
+// NOLIBRARY: missing arg value for "-l", expected 1 argument.
+
+// Should not link because of undefined symbol _bar
+// RUN: not ld.lld -o %t3 %t.o 2>&1 \
+// RUN: | FileCheck --check-prefix=UNDEFINED %s
+// UNDEFINED: undefined symbol: _bar
+
+// 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
+
+// Should use explicitly specified static library
+// Also ensure that we accept -L <arg>
+// RUN: ld.lld -o %t3 %t.o -L %t.dir -l:libls.a
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s
+// STATIC: Symbols [
+// STATIC: Name: _static
+// STATIC: ]
+
+// Should use explicitly specified dynamic library
+// RUN: ld.lld -o %t3 %t.o -L%t.dir -l:libls.so
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s
+// DYNAMIC: Symbols [
+// DYNAMIC-NOT: Name: _static
+// DYNAMIC: ]
+
+// Should prefer dynamic to static
+// RUN: ld.lld -o %t3 %t.o -L%t.dir -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s
+
+// -L can be placed after -l
+// RUN: ld.lld -o %t3 %t.o -lls -L%t.dir
+
+// Check long forms as well
+// RUN: ld.lld -o %t3 %t.o --library-path=%t.dir --library=ls
+
+// Should not search for dynamic libraries if -Bstatic is specified
+// RUN: ld.lld -o %t3 %t.o -L%t.dir -Bstatic -lls
+// 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
+
+// -Bdynamic should restore default behaviour
+// RUN: ld.lld -o %t3 %t.o -L%t.dir -Bstatic -Bdynamic -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s
+
+// -Bstatic and -Bdynamic should affect only libraries which follow them
+// RUN: ld.lld -o %t3 %t.o -L%t.dir -lls -Bstatic -Bdynamic
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s
+// RUN: ld.lld -o %t3 %t.o -L%t.dir -Bstatic -lls -Bdynamic
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s
+
+// Check aliases as well
+// RUN: ld.lld -o %t3 %t.o -L%t.dir -dn -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s
+// RUN: ld.lld -o %t3 %t.o -L%t.dir -non_shared -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s
+// RUN: ld.lld -o %t3 %t.o -L%t.dir -static -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=STATIC %s
+// RUN: ld.lld -o %t3 %t.o -L%t.dir -Bstatic -dy -lls
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=DYNAMIC %s
+// 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;
+_start:
diff --git a/test/ELF/linkerscript-ouputformat.s b/test/ELF/linkerscript-ouputformat.s
new file mode 100644
index 000000000000..3c6cfdc8f966
--- /dev/null
+++ b/test/ELF/linkerscript-ouputformat.s
@@ -0,0 +1,10 @@
+# REQUIRES: x86
+# RUN: echo "OUTPUT_FORMAT(x, y, z)" > %t.script
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t1
+# RUN: ld.lld -shared -o %t2 %t1 %t.script
+# RUN: llvm-readobj %t2 > /dev/null
+
+# RUN: echo "OUTPUT_FORMAT(x, y)" > %t.script
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t1
+# RUN: not ld.lld -shared -o %t2 %t1 %t.script
+# RUN: llvm-readobj %t2 > /dev/null
diff --git a/test/ELF/linkerscript-outputarch.s b/test/ELF/linkerscript-outputarch.s
new file mode 100644
index 000000000000..99089615cb17
--- /dev/null
+++ b/test/ELF/linkerscript-outputarch.s
@@ -0,0 +1,10 @@
+# REQUIRES: x86
+# RUN: echo "OUTPUT_ARCH(x)" > %t.script
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t1
+# RUN: ld.lld -shared -o %t2 %t1 %t.script
+# RUN: llvm-readobj %t2 > /dev/null
+
+# RUN: echo "OUTPUT_ARCH(x, y)" > %t.script
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t1
+# RUN: not ld.lld -shared -o %t2 %t1 %t.script
+# RUN: llvm-readobj %t2 > /dev/null
diff --git a/test/ELF/linkerscript-sections.s b/test/ELF/linkerscript-sections.s
new file mode 100644
index 000000000000..ea9ae2b2726d
--- /dev/null
+++ b/test/ELF/linkerscript-sections.s
@@ -0,0 +1,119 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+
+# Empty SECTIONS command.
+# RUN: echo "SECTIONS {}" > %t.script
+# RUN: ld.lld -o %t1 --script %t.script %t
+# RUN: llvm-objdump -section-headers %t1 | \
+# RUN: FileCheck -check-prefix=SEC-DEFAULT %s
+
+# SECTIONS command with the same order as default.
+# RUN: echo "SECTIONS { \
+# RUN: .text : { *(.text) } \
+# RUN: .data : { *(.data) } }" > %t.script
+# RUN: ld.lld -o %t2 --script %t.script %t
+# RUN: llvm-objdump -section-headers %t2 | \
+# RUN: FileCheck -check-prefix=SEC-DEFAULT %s
+
+# Idx Name Size
+# SEC-DEFAULT: 1 .text 0000000e {{[0-9a-f]*}} TEXT DATA
+# SEC-DEFAULT: 2 .data 00000020 {{[0-9a-f]*}} DATA
+# SEC-DEFAULT: 3 other 00000003 {{[0-9a-f]*}} DATA
+# 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 00000032 {{[0-9a-f]*}}
+# SEC-DEFAULT: 8 .strtab 00000008 {{[0-9a-f]*}}
+
+# Sections are put in order specified in linker script.
+# RUN: echo "SECTIONS { \
+# RUN: .bss : { *(.bss) } \
+# RUN: other : { *(other) } \
+# RUN: .shstrtab : { *(.shstrtab) } \
+# RUN: .symtab : { *(.symtab) } \
+# RUN: .strtab : { *(.strtab) } \
+# RUN: .data : { *(.data) } \
+# RUN: .text : { *(.text) } }" > %t.script
+# RUN: ld.lld -o %t3 --script %t.script %t
+# RUN: llvm-objdump -section-headers %t3 | \
+# RUN: FileCheck -check-prefix=SEC-ORDER %s
+
+# Idx Name Size
+# 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 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
+# SEC-ORDER: 8 .text 0000000e {{[0-9a-f]*}} TEXT DATA
+
+# .text and .data have swapped names but proper sizes and types.
+# RUN: echo "SECTIONS { \
+# RUN: .data : { *(.text) } \
+# RUN: .text : { *(.data) } }" > %t.script
+# RUN: ld.lld -o %t4 --script %t.script %t
+# RUN: llvm-objdump -section-headers %t4 | \
+# RUN: FileCheck -check-prefix=SEC-SWAP-NAMES %s
+
+# Idx Name Size
+# SEC-SWAP-NAMES: 1 .data 0000000e {{[0-9a-f]*}} TEXT DATA
+# SEC-SWAP-NAMES: 2 .text 00000020 {{[0-9a-f]*}} DATA
+# SEC-SWAP-NAMES: 3 other 00000003 {{[0-9a-f]*}} DATA
+# 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 00000032 {{[0-9a-f]*}}
+# SEC-SWAP-NAMES: 8 .strtab 00000008 {{[0-9a-f]*}}
+
+# .shstrtab from the input object file is discarded.
+# RUN: echo "SECTIONS { \
+# RUN: /DISCARD/ : { *(.shstrtab) } }" > %t.script
+# RUN: ld.lld -o %t5 --script %t.script %t
+# RUN: llvm-objdump -section-headers %t5 | \
+# RUN: FileCheck -check-prefix=SEC-DISCARD %s
+
+# Idx Name Size
+# SEC-DISCARD: 1 .text 0000000e {{[0-9a-f]*}} TEXT DATA
+# SEC-DISCARD: 2 .data 00000020 {{[0-9a-f]*}} DATA
+# SEC-DISCARD: 3 other 00000003 {{[0-9a-f]*}} DATA
+# SEC-DISCARD: 4 .bss 00000002 {{[0-9a-f]*}} BSS
+# SEC-DISCARD: 5 .symtab 00000030 {{[0-9a-f]*}}
+# SEC-DISCARD: 6 .shstrtab 00000032 {{[0-9a-f]*}}
+# SEC-DISCARD: 7 .strtab 00000008 {{[0-9a-f]*}}
+
+# Multiple SECTIONS command specifying additional input section descriptions
+# for the same output section description - input sections are merged into
+# one output section.
+# RUN: echo "SECTIONS { \
+# RUN: .text : { *(.text) } \
+# RUN: .data : { *(.data) } } \
+# RUN: SECTIONS { \
+# RUN: .data : { *(other) } }" > %t.script
+# RUN: ld.lld -o %t6 --script %t.script %t
+# RUN: llvm-objdump -section-headers %t6 | \
+# RUN: FileCheck -check-prefix=SEC-MULTI %s
+
+# Idx Name Size
+# SEC-MULTI: 1 .text 0000000e {{[0-9a-f]*}} TEXT DATA
+# SEC-MULTI: 2 .data 00000023 {{[0-9a-f]*}} DATA
+# 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 0000002c {{[0-9a-f]*}}
+# SEC-MULTI: 7 .strtab 00000008 {{[0-9a-f]*}}
+
+.globl _start;
+_start:
+ mov $60, %rax
+ mov $42, %rdi
+
+.section .data,"aw"
+.quad 10, 10, 20, 20
+.section other,"aw"
+.short 10
+.byte 20
+.section .shstrtab,""
+.short 20
+.section .bss,"",@nobits
+.short 0
diff --git a/test/ELF/linkerscript.s b/test/ELF/linkerscript.s
new file mode 100644
index 000000000000..bff285b97612
--- /dev/null
+++ b/test/ELF/linkerscript.s
@@ -0,0 +1,114 @@
+# REQUIRES: x86
+# RUN: mkdir -p %t.dir
+# 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/libsearch-st.s -o %t2.o
+# RUN: rm -f %t.dir/libxyz.a
+# RUN: llvm-ar rcs %t.dir/libxyz.a %t2.o
+
+# RUN: echo "EXTERN( undef undef2 )" > %t.script
+# RUN: ld.lld %t -o %t2 %t.script
+# RUN: llvm-readobj %t2 > /dev/null
+
+# 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: ld.lld -o %t2 %t.script
+# RUN: llvm-readobj %t2 > /dev/null
+
+# 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: 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: 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: 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: 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: ld.lld -o %t2 %t.script1
+# RUN: llvm-readobj %t2 > /dev/null
+
+# RUN: echo "ENTRY(_label)" > %t.script
+# RUN: ld.lld -o %t2 %t.script %t
+# RUN: llvm-readobj %t2 > /dev/null
+
+# RUN: echo "ENTRY(_wrong_label)" > %t.script
+# RUN: not ld.lld -o %t2 %t.script %t > %t.log 2>&1
+# RUN: FileCheck -check-prefix=ERR-ENTRY %s < %t.log
+
+# ERR-ENTRY: undefined symbol: _wrong_label
+
+# -e has precedence over linker script's ENTRY.
+# RUN: echo "ENTRY(_label)" > %t.script
+# RUN: ld.lld -e _start -o %t2 %t.script %t
+# RUN: llvm-readobj -file-headers -symbols %t2 | \
+# RUN: FileCheck -check-prefix=ENTRY-OVERLOAD %s
+
+# ENTRY-OVERLOAD: Entry: [[ENTRY:0x[0-9A-F]+]]
+# ENTRY-OVERLOAD: Name: _start
+# ENTRY-OVERLOAD-NEXT: Value: [[ENTRY]]
+
+# 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: 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: ld.lld %t.script %t
+# RUN: llvm-readobj %t.out > /dev/null
+
+# RUN: echo "SEARCH_DIR(/lib/foo/blah)" > %t.script
+# RUN: ld.lld %t.script %t
+# RUN: llvm-readobj %t.out > /dev/null
+
+# RUN: echo ";SEARCH_DIR(x);SEARCH_DIR(y);" > %t.script
+# RUN: ld.lld %t.script %t
+# RUN: llvm-readobj %t.out > /dev/null
+
+# RUN: echo ";" > %t.script
+# 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: ld.lld %t.script1
+# RUN: llvm-readobj %t2 > /dev/null
+
+# RUN: echo "FOO(BAR)" > %t.script
+# RUN: not ld.lld -o foo %t.script > %t.log 2>&1
+# RUN: FileCheck -check-prefix=ERR1 %s < %t.log
+
+# ERR1: unknown directive: FOO
+
+.globl _start, _label;
+_start:
+ mov $60, %rax
+ mov $42, %rdi
+_label:
+ syscall
diff --git a/test/ELF/linkerscript2.s b/test/ELF/linkerscript2.s
new file mode 100644
index 000000000000..f83198f759fd
--- /dev/null
+++ b/test/ELF/linkerscript2.s
@@ -0,0 +1,11 @@
+# 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: ld.lld -o %t2 --script %t.script -lls %t
+
+.globl _start,_bar
+_start:
diff --git a/test/ELF/lit.local.cfg b/test/ELF/lit.local.cfg
new file mode 100644
index 000000000000..0011e796e5f4
--- /dev/null
+++ b/test/ELF/lit.local.cfg
@@ -0,0 +1,2 @@
+config.suffixes = ['.test', '.s']
+
diff --git a/test/ELF/local-dynamic.s b/test/ELF/local-dynamic.s
new file mode 100644
index 000000000000..162c58cb57ed
--- /dev/null
+++ b/test/ELF/local-dynamic.s
@@ -0,0 +1,83 @@
+// Check that local symbols are not inserted into dynamic table.
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: ld.lld %t -shared -o %t1.so
+// RUN: llvm-readobj -t -dyn-symbols %t1.so | FileCheck %s
+// REQUIRES: x86
+
+// 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: blah
+// CHECK-NEXT: Value: 0x1000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: foo
+// CHECK-NEXT: Value: 0x1000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: goo
+// CHECK-NEXT: Value: 0x1000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: _start
+// 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: ]
+
+// 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: _start@
+// 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: ]
+
+.global _start
+_start:
+
+blah:
+foo:
+goo:
+
+
diff --git a/test/ELF/local-got-shared.s b/test/ELF/local-got-shared.s
new file mode 100644
index 000000000000..08e6583f481f
--- /dev/null
+++ b/test/ELF/local-got-shared.s
@@ -0,0 +1,35 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t -shared
+// RUN: llvm-readobj -s -r %t | FileCheck %s
+// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
+
+bar:
+ call foo@gotpcrel
+
+ .hidden foo
+ .global foo
+foo:
+ nop
+
+// 0x2090 - 0x1000 - 5 = 4235
+// DISASM: bar:
+// DISASM-NEXT: 1000: {{.*}} callq 4235
+
+// 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: 0x2090
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 8
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: 0x2090 R_X86_64_RELATIVE - 0x1005
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
diff --git a/test/ELF/local-got.s b/test/ELF/local-got.s
new file mode 100644
index 000000000000..015c058e2eb9
--- /dev/null
+++ b/test/ELF/local-got.s
@@ -0,0 +1,48 @@
+// 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: ld.lld -shared %t2.o -o %t2.so
+// RUN: ld.lld %t.o %t2.so -o %t
+// RUN: llvm-readobj -s -r -section-data %t | FileCheck %s
+// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
+
+ .globl _start
+_start:
+ call bar@gotpcrel
+ call foo@gotpcrel
+
+ .global foo
+foo:
+ nop
+
+// 0x120A0 - 0x11000 - 5 = 4251
+// 0x120A8 - 0x11005 - 5 = 4254
+// DISASM: _start:
+// DISASM-NEXT: 11000: {{.*}} callq 4251
+// DISASM-NEXT: 11005: {{.*}} callq 4254
+
+// DISASM: foo:
+// DISASM-NEXT: 1100a: {{.*}} 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: 0x120A0
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 16
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 8
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// 0x1200a in little endian
+// CHECK-NEXT: 0000: 00000000 00000000 0A100100 00000000
+// CHECK-NEXT: )
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: 0x120A0 R_X86_64_GLOB_DAT bar 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
diff --git a/test/ELF/local.s b/test/ELF/local.s
new file mode 100644
index 000000000000..cc879e15c0db
--- /dev/null
+++ b/test/ELF/local.s
@@ -0,0 +1,82 @@
+// Check that symbol table is correctly populated with local symbols.
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: ld.lld %t -o %t1
+// RUN: llvm-readobj -t -s %t1 | FileCheck %s
+// REQUIRES: x86
+
+// Check that Info is equal to the number of local symbols.
+// CHECK: Section {
+// CHECK: Name: .symtab
+// CHECK-NEXT: Type: SHT_SYMTAB
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address:
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info: 5
+
+// 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: abs
+// CHECK-NEXT: Value: 0x2A
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Absolute
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: blah
+// CHECK-NEXT: Value: 0x11000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// 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: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: goo
+// CHECK-NEXT: Value: 0x11000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// 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: ]
+
+.global _start
+_start:
+
+blah:
+foo:
+goo:
+abs = 42
diff --git a/test/ELF/many-sections.s b/test/ELF/many-sections.s
new file mode 100644
index 000000000000..77e76c20a60d
--- /dev/null
+++ b/test/ELF/many-sections.s
@@ -0,0 +1,116 @@
+// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t
+// RUN: llvm-readobj -t %t | FileCheck %s
+
+// Verify that the symbol _start is in a section with an index >= SHN_LORESERVE.
+// CHECK: Name: _start
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: dm (0xFF00)
+
+
+// RUN: ld.lld %t -o %t2
+// RUN: llvm-readobj -t %t2 | FileCheck --check-prefix=LINKED %s
+
+// Test that _start is in the correct section.
+// LINKED: Name: _start
+// LINKED-NEXT: Value: 0x0
+// LINKED-NEXT: Size: 0
+// LINKED-NEXT: Binding: Global
+// LINKED-NEXT: Type: None
+// LINKED-NEXT: Other: 0
+// LINKED-NEXT: Section: dm
+
+.macro gen_sections4 x
+ .section a\x
+ .section b\x
+ .section c\x
+ .section d\x
+.endm
+
+.macro gen_sections8 x
+ gen_sections4 a\x
+ gen_sections4 b\x
+.endm
+
+.macro gen_sections16 x
+ gen_sections8 a\x
+ gen_sections8 b\x
+.endm
+
+.macro gen_sections32 x
+ gen_sections16 a\x
+ gen_sections16 b\x
+.endm
+
+.macro gen_sections64 x
+ gen_sections32 a\x
+ gen_sections32 b\x
+.endm
+
+.macro gen_sections128 x
+ gen_sections64 a\x
+ gen_sections64 b\x
+.endm
+
+.macro gen_sections256 x
+ gen_sections128 a\x
+ gen_sections128 b\x
+.endm
+
+.macro gen_sections512 x
+ gen_sections256 a\x
+ gen_sections256 b\x
+.endm
+
+.macro gen_sections1024 x
+ gen_sections512 a\x
+ gen_sections512 b\x
+.endm
+
+.macro gen_sections2048 x
+ gen_sections1024 a\x
+ gen_sections1024 b\x
+.endm
+
+.macro gen_sections4096 x
+ gen_sections2048 a\x
+ gen_sections2048 b\x
+.endm
+
+.macro gen_sections8192 x
+ gen_sections4096 a\x
+ gen_sections4096 b\x
+.endm
+
+.macro gen_sections16384 x
+ gen_sections8192 a\x
+ gen_sections8192 b\x
+.endm
+
+.macro gen_sections32768 x
+ gen_sections16384 a\x
+ gen_sections16384 b\x
+.endm
+
+ .bss
+ .section bar
+
+gen_sections32768 a
+gen_sections16384 b
+gen_sections8192 c
+gen_sections4096 d
+gen_sections2048 e
+gen_sections1024 f
+gen_sections512 g
+gen_sections128 h
+gen_sections64 i
+gen_sections32 j
+gen_sections16 k
+gen_sections8 l
+gen_sections4 m
+
+.global _start
+_start:
diff --git a/test/ELF/merge-invalid-size.s b/test/ELF/merge-invalid-size.s
new file mode 100644
index 000000000000..2a99e14ad836
--- /dev/null
+++ b/test/ELF/merge-invalid-size.s
@@ -0,0 +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.so 2>&1 | FileCheck %s
+// CHECK: SHF_MERGE section size must be a multiple of sh_entsize
+
+ .section .foo,"aM",@progbits,4
+ .short 42
diff --git a/test/ELF/merge-shared.s b/test/ELF/merge-shared.s
new file mode 100644
index 000000000000..702a4e195f32
--- /dev/null
+++ b/test/ELF/merge-shared.s
@@ -0,0 +1,26 @@
+// 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 %t.so | FileCheck %s
+
+ .section foo,"aM",@progbits,4
+ .long 42
+ .long 42
+
+ .text
+ .quad foo + 6
+
+
+// CHECK: Name: foo
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_MERGE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x1C8
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x1CA
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
diff --git a/test/ELF/merge-string-align.s b/test/ELF/merge-string-align.s
new file mode 100644
index 000000000000..b06920ac0af8
--- /dev/null
+++ b/test/ELF/merge-string-align.s
@@ -0,0 +1,39 @@
+// 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
+
+ .section .rodata.str1.16,"aMS",@progbits,1
+ .align 16
+ .asciz "foo"
+
+ .section .rodata.str1.1,"aMS",@progbits,1
+ .asciz "foo"
+
+// 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: 16
+
+// 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
diff --git a/test/ELF/merge-string-error.s b/test/ELF/merge-string-error.s
new file mode 100644
index 000000000000..58a624329ed9
--- /dev/null
+++ b/test/ELF/merge-string-error.s
@@ -0,0 +1,11 @@
+// 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
+
+ .section .rodata.str1.1,"aMS",@progbits,1
+ .asciz "abc"
+
+ .text
+ .long .rodata.str1.1 + 4
+
+// 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
new file mode 100644
index 000000000000..70d6bbbc32e8
--- /dev/null
+++ b/test/ELF/merge-string-no-null.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
+
+ .section .rodata.str1.1,"aMS",@progbits,1
+ .ascii "abc"
+
+// CHECK: String is not null terminated
diff --git a/test/ELF/merge-string.s b/test/ELF/merge-string.s
new file mode 100644
index 000000000000..40cc4415f956
--- /dev/null
+++ b/test/ELF/merge-string.s
@@ -0,0 +1,85 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld -O2 %t.o -o %t.so -shared
+// 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
+
+ .section .rodata.str1.1,"aMS",@progbits,1
+ .asciz "abc"
+foo:
+ .ascii "a"
+bar:
+ .asciz "bc"
+ .asciz "bc"
+
+ .section .rodata.str2.2,"aMS",@progbits,2
+ .align 2
+zed:
+ .short 20
+ .short 0
+
+// 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: 0x1C8
+// 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: 61626300 |abc.|
+// CHECK-NEXT: )
+
+// NOTAIL: Name: .rodata
+// NOTAIL-NEXT: Type: SHT_PROGBITS
+// NOTAIL-NEXT: Flags [
+// NOTAIL-NEXT: SHF_ALLOC
+// NOTAIL-NEXT: SHF_MERGE
+// NOTAIL-NEXT: SHF_STRINGS
+// NOTAIL-NEXT: ]
+// NOTAIL-NEXT: Address: 0x1C8
+// NOTAIL-NEXT: Offset: 0x1C8
+// NOTAIL-NEXT: Size: 7
+// NOTAIL-NEXT: Link: 0
+// NOTAIL-NEXT: Info: 0
+// NOTAIL-NEXT: AddressAlignment: 1
+// NOTAIL-NEXT: EntrySize: 0
+// NOTAIL-NEXT: SectionData (
+// NOTAIL-NEXT: 0000: 61626300 626300 |abc.bc.|
+// NOTAIL-NEXT: )
+
+// 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: 0x1CC
+// CHECK-NEXT: Offset: 0x1CC
+// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 2
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 14000000 |....|
+// CHECK-NEXT: )
+
+
+// CHECK: Name: bar
+// CHECK-NEXT: Value: 0x1C9
+
+// CHECK: Name: foo
+// CHECK-NEXT: Value: 0x1C8
+
+// CHECK: Name: zed
+// CHECK-NEXT: Value: 0x1CC
+// CHECK-NEXT: Size: 0
diff --git a/test/ELF/merge-sym.s b/test/ELF/merge-sym.s
new file mode 100644
index 000000000000..4a4e9824a0de
--- /dev/null
+++ b/test/ELF/merge-sym.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.so -shared
+// RUN: llvm-readobj -t -s %t.so | FileCheck %s
+
+ .section .rodata.cst4,"aM",@progbits,4
+ .short 0
+foo:
+ .short 42
+
+
+// CHECK: Name: .rodata
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_MERGE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x1C8
+
+// CHECK: Name: foo
+// CHECK-NEXT: Value: 0x1CA
diff --git a/test/ELF/merge.s b/test/ELF/merge.s
new file mode 100644
index 000000000000..9cead642fa8c
--- /dev/null
+++ b/test/ELF/merge.s
@@ -0,0 +1,109 @@
+// 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/merge.s -o %t2.o
+// RUN: ld.lld %t.o %t2.o -o %t
+// RUN: llvm-readobj -s -section-data -t %t | FileCheck %s
+// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
+
+ .section .mysec,"aM",@progbits,4
+ .align 4
+ .global foo
+ .hidden foo
+ .long 0x10
+foo:
+ .long 0x42
+bar:
+ .long 0x42
+zed:
+ .long 0x42
+
+// CHECK: Name: .mysec
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_MERGE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x10120
+// CHECK-NEXT: Offset: 0x120
+// 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: 10000000 42000000
+// CHECK-NEXT: )
+
+
+// Address of the constant 0x10 = 0x10120 = 65824
+// Address of the constant 0x42 = 0x10124 = 65828
+
+// CHECK: Symbols [
+
+// CHECK: Name: bar
+// CHECK-NEXT: Value: 0x10124
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Loca
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .mysec
+
+// CHECK: Name: zed
+// CHECK-NEXT: Value: 0x10124
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .mysec
+
+// CHECK: Name: foo
+// CHECK-NEXT: Value: 0x10124
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 2
+// CHECK-NEXT: Section: .mysec
+
+ // CHECK: ]
+
+ .text
+ .globl _start
+_start:
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: _start:
+
+ movl .mysec, %eax
+// addr(0x10) = 65824
+// DISASM-NEXT: movl 65824, %eax
+
+ movl .mysec+7, %eax
+// addr(0x42) + 3 = 65828 + 3 = 65831
+// DISASM-NEXT: movl 65831, %eax
+
+ movl .mysec+8, %eax
+// addr(0x42) = 65828
+// DISASM-NEXT: movl 65828, %eax
+
+ movl bar+7, %eax
+// addr(0x42) + 7 = 65828 + 7 = 65835
+// DISASM-NEXT: movl 65835, %eax
+
+ movl bar+8, %eax
+// addr(0x42) + 8 = 65828 + 8 = 65836
+// DISASM-NEXT: movl 65836, %eax
+
+ movl foo, %eax
+// addr(0x42) = 65828
+// DISASM-NEXT: movl 65828, %eax
+
+ movl foo+7, %eax
+// addr(0x42) + 7 = = 65828 + 7 = 65835
+// DISASM-NEXT: movl 65835, %eax
+
+ movl foo+8, %eax
+// addr(0x42) + 8 = = 65828 + 8 = 65836
+// DISASM-NEXT: movl 65836, %eax
+
+// From the other file: movl .mysec, %eax
+// addr(0x42) = 65828
+// DISASM-NEXT: movl 65828, %eax
diff --git a/test/ELF/mips-call16.s b/test/ELF/mips-call16.s
new file mode 100644
index 000000000000..4a5d0bf3f871
--- /dev/null
+++ b/test/ELF/mips-call16.s
@@ -0,0 +1,40 @@
+# Check R_MIPS_CALL16 relocation calculation.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -shared -o %t.exe
+# RUN: llvm-objdump -d %t.exe | FileCheck %s
+# RUN: llvm-readobj -mips-plt-got -symbols %t.exe \
+# RUN: | FileCheck -check-prefix=GOT %s
+
+# REQUIRES: mips
+
+ .text
+ .globl __start
+__start:
+ lw $t0,%call16(g1)($gp)
+
+ .globl g1
+ .type g1,@function
+g1:
+ nop
+
+# CHECK: Disassembly of section .text:
+# CHECK-NEXT: __start:
+# CHECK-NEXT: 10000: 8f 88 80 18 lw $8, -32744
+
+# GOT: Name: g1
+# GOT-NEXT: Value: 0x[[ADDR:[0-9A-F]+]]
+
+# GOT: Local entries [
+# GOT-NEXT: ]
+# GOT-NEXT: Global entries [
+# GOT-NEXT: Entry {
+# GOT-NEXT: Address:
+# GOT-NEXT: Access: -32744
+# GOT-NEXT: Initial: 0x[[ADDR]]
+# GOT-NEXT: Value: 0x[[ADDR]]
+# GOT-NEXT: Type: Function
+# GOT-NEXT: Section: .text
+# GOT-NEXT: Name: g1
+# GOT-NEXT: }
+# GOT-NEXT: ]
diff --git a/test/ELF/mips-dynamic.s b/test/ELF/mips-dynamic.s
new file mode 100644
index 000000000000..626a3556d361
--- /dev/null
+++ b/test/ELF/mips-dynamic.s
@@ -0,0 +1,91 @@
+# Check MIPS specific .dynamic section entries.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %p/Inputs/mips-dynamic.s -o %td.o
+# RUN: ld.lld -shared %td.o -o %td.so
+
+# RUN: ld.lld %t.o %td.so -o %t.exe
+# RUN: llvm-readobj -sections -dynamic-table %t.exe \
+# RUN: | FileCheck -check-prefix=EXE %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
+
+# REQUIRES: mips
+
+# EXE: Sections [
+# EXE: Name: .dynamic
+# EXE-NEXT: Type: SHT_DYNAMIC
+# EXE-NEXT: Flags [
+# EXE-NEXT: SHF_ALLOC
+# EXE-NEXT: ]
+# EXE: Name: .got
+# EXE-NEXT: Type: SHT_PROGBITS
+# EXE-NEXT: Flags [ (0x10000003)
+# EXE-NEXT: SHF_ALLOC
+# EXE-NEXT: SHF_WRITE
+# EXE-NEXT: ]
+# EXE-NEXT: Address: [[GOTADDR:0x[0-9a-f]+]]
+# EXE-NEXT: Offset:
+# EXE-NEXT: Size: 8
+# EXE: Name: .rld_map
+# EXE-NEXT: Type: SHT_PROGBITS
+# EXE-NEXT: Flags [
+# EXE-NEXT: SHF_ALLOC
+# EXE-NEXT: SHF_WRITE
+# EXE-NEXT: ]
+# EXE-NEXT: Address: [[RLDMAPADDR:0x[0-9a-f]+]]
+# EXE-NEXT: Offset:
+# EXE-NEXT: Size: 4
+# EXE: ]
+# EXE: DynamicSection [
+# EXE-NEXT: Tag Type Name/Value
+# 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: 0x7000000A MIPS_LOCAL_GOTNO 2
+# EXE-DAG: 0x70000011 MIPS_SYMTABNO 1
+# EXE-DAG: 0x70000013 MIPS_GOTSYM 0x1
+# EXE-DAG: 0x70000016 MIPS_RLD_MAP [[RLDMAPADDR]]
+# EXE: ]
+
+# DSO: Sections [
+# DSO: Name: .dynamic
+# DSO-NEXT: Type: SHT_DYNAMIC
+# DSO-NEXT: Flags [
+# DSO-NEXT: SHF_ALLOC
+# DSO-NEXT: ]
+# DSO: Name: .got
+# DSO-NEXT: Type: SHT_PROGBITS
+# DSO-NEXT: Flags [ (0x10000003)
+# DSO-NEXT: SHF_ALLOC
+# DSO-NEXT: SHF_WRITE
+# DSO-NEXT: ]
+# DSO-NEXT: Address: [[GOTADDR:0x[0-9a-f]+]]
+# DSO-NEXT: Offset:
+# DSO-NEXT: Size: 8
+# DSO: ]
+# DSO: DynamicSymbols [
+# DSO: Name: @
+# DSO: Name: _gp@
+# DSO: Name: __start@
+# DSO: Name: _foo@
+# DSO: ]
+# DSO: DynamicSection [
+# DSO-NEXT: Tag Type Name/Value
+# DSO-DAG: 0x00000003 PLTGOT [[GOTADDR]]
+# DSO-DAG: 0x70000001 MIPS_RLD_VERSION 1
+# 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: ]
+
+ .text
+ .globl __start,_foo
+ .type _foo,@function
+__start:
+ nop
diff --git a/test/ELF/mips-dynsym-sort.s b/test/ELF/mips-dynsym-sort.s
new file mode 100644
index 000000000000..7d4559cf9335
--- /dev/null
+++ b/test/ELF/mips-dynsym-sort.s
@@ -0,0 +1,43 @@
+# Check the order of dynamic symbols for the MIPS target.
+
+# 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-readobj -symbols -dyn-symbols %t-be.so | FileCheck %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-readobj -symbols -dyn-symbols %t-el.so | FileCheck %s
+
+# REQUIRES: mips
+
+ .data
+ .globl v1,v2,v3
+v1:
+ .space 4
+v2:
+ .space 4
+v3:
+ .space 4
+
+ .text
+ .globl __start
+__start:
+ lui $2, %got(v3) # v3 will precede v1 in the GOT
+ lui $2, %got(v1)
+
+# Since all these symbols have global binding,
+# the Symbols section contains them in the original order.
+# CHECK: Symbols [
+# CHECK: Name: v1
+# CHECK: Name: v2
+# CHECK: Name: v3
+# CHECK: ]
+
+# The symbols in the DynamicSymbols section are sorted in compliance with
+# the MIPS rules. v2 comes first as it is not in the GOT.
+# v1 and v3 are sorted according to their order in the GOT.
+# CHECK: DynamicSymbols [
+# CHECK: Name: v2@
+# CHECK: Name: v3@
+# CHECK: Name: v1@
+# CHECK: ]
diff --git a/test/ELF/mips-elf-flags.s b/test/ELF/mips-elf-flags.s
new file mode 100644
index 000000000000..7817e58b5383
--- /dev/null
+++ b/test/ELF/mips-elf-flags.s
@@ -0,0 +1,27 @@
+# Check generation of MIPS specific ELF header flags.
+
+# 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 -h %t.so | FileCheck -check-prefix=SO %s
+# RUN: ld.lld %t.o -o %t.exe
+# RUN: llvm-readobj -h %t.exe | FileCheck -check-prefix=EXE %s
+
+# REQUIRES: mips
+
+ .text
+ .globl __start
+__start:
+ nop
+
+# SO: Flags [
+# SO-NEXT: EF_MIPS_ABI_O32
+# SO-NEXT: EF_MIPS_ARCH_32R2
+# SO-NEXT: EF_MIPS_CPIC
+# SO-NEXT: EF_MIPS_PIC
+# SO-NEXT: ]
+
+# EXE: Flags [
+# EXE-NEXT: EF_MIPS_ABI_O32
+# EXE-NEXT: EF_MIPS_ARCH_32R2
+# EXE-NEXT: EF_MIPS_CPIC
+# EXE-NEXT: ]
diff --git a/test/ELF/mips-gnu-hash.s b/test/ELF/mips-gnu-hash.s
new file mode 100644
index 000000000000..4b11f213518c
--- /dev/null
+++ b/test/ELF/mips-gnu-hash.s
@@ -0,0 +1,15 @@
+# Shouldn't allow the GNU hash style to be selected with the MIPS target.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-be.o
+# RUN: not ld.lld -shared -hash-style=gnu %t-be.o -o %t-be.so 2>&1 | FileCheck %s
+
+# 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.
+
+# REQUIRES: mips
+
+ .globl __start
+__start:
+ nop
diff --git a/test/ELF/mips-got-relocs.s b/test/ELF/mips-got-relocs.s
new file mode 100644
index 000000000000..27180fbf82ea
--- /dev/null
+++ b/test/ELF/mips-got-relocs.s
@@ -0,0 +1,99 @@
+# Check R_MIPS_GOT16 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 -section-headers -t %t-be.exe | FileCheck -check-prefix=EXE_SYM %s
+# RUN: llvm-objdump -s -section=.got %t-be.exe | FileCheck -check-prefix=EXE_GOT_BE %s
+# RUN: llvm-objdump -d %t-be.exe | FileCheck -check-prefix=EXE_DIS_BE %s
+# RUN: llvm-readobj -relocations %t-be.exe | FileCheck -check-prefix=NORELOC %s
+# RUN: llvm-readobj -sections %t-be.exe | FileCheck -check-prefix=SHFLAGS %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 -section-headers -t %t-el.exe | FileCheck -check-prefix=EXE_SYM %s
+# RUN: llvm-objdump -s -section=.got %t-el.exe | FileCheck -check-prefix=EXE_GOT_EL %s
+# RUN: llvm-objdump -d %t-el.exe | FileCheck -check-prefix=EXE_DIS_EL %s
+# RUN: llvm-readobj -relocations %t-el.exe | FileCheck -check-prefix=NORELOC %s
+# RUN: llvm-readobj -sections %t-el.exe | FileCheck -check-prefix=SHFLAGS %s
+
+# RUN: ld.lld -shared %t-be.o -o %t-be.so
+# RUN: llvm-objdump -section-headers -t %t-be.so | FileCheck -check-prefix=DSO_SYM %s
+# RUN: llvm-objdump -s -section=.got %t-be.so | FileCheck -check-prefix=DSO_GOT_BE %s
+# RUN: llvm-objdump -d %t-be.so | FileCheck -check-prefix=DSO_DIS_BE %s
+# RUN: llvm-readobj -relocations %t-be.so | FileCheck -check-prefix=NORELOC %s
+# RUN: llvm-readobj -sections %t-be.so | FileCheck -check-prefix=SHFLAGS %s
+
+# RUN: ld.lld -shared %t-el.o -o %t-el.so
+# RUN: llvm-objdump -section-headers -t %t-el.so | FileCheck -check-prefix=DSO_SYM %s
+# RUN: llvm-objdump -s -section=.got %t-el.so | FileCheck -check-prefix=DSO_GOT_EL %s
+# RUN: llvm-objdump -d %t-el.so | FileCheck -check-prefix=DSO_DIS_EL %s
+# RUN: llvm-readobj -relocations %t-el.so | FileCheck -check-prefix=NORELOC %s
+# RUN: llvm-readobj -sections %t-el.so | FileCheck -check-prefix=SHFLAGS %s
+
+# REQUIRES: mips
+
+ .text
+ .globl __start
+__start:
+ lui $2, %got(v1)
+
+ .data
+ .globl v1
+ .type v1,@object
+ .size v1,4
+v1:
+ .word 0
+
+# EXE_SYM: Sections:
+# EXE_SYM: .got 0000000c 0000000000030000 DATA
+# EXE_SYM: SYMBOL TABLE:
+# EXE_SYM: 00037ff0 *ABS* 00000000 _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)
+# | +-- Module pointer (0x80000000)
+# +-- Lazy resolver (0x0)
+
+# EXE_GOT_EL: Contents of section .got:
+# EXE_GOT_EL: 30000 00000000 00000080 00000400
+# ^ ^ ^-- v1 (0x40000)
+# | +-- Module pointer (0x80000000)
+# +-- Lazy resolver (0x0)
+
+# v1GotAddr (0x3000c) - _gp (0x37ff4) = -0x7fe8 => 0x8018 = 32792
+# EXE_DIS_BE: 20000: 3c 02 80 18 lui $2, 32792
+# EXE_DIS_EL: 20000: 18 80 02 3c lui $2, 32792
+
+# DSO_SYM: Sections:
+# DSO_SYM: .got 0000000c 0000000000020000 DATA
+# DSO_SYM: SYMBOL TABLE:
+# DSO_SYM: 00027ff0 *ABS* 00000000 _gp
+# ^-- .got + GP offset (0x7ff0)
+# DSO_SYM: 00030000 g .data 00000004 v1
+
+# DSO_GOT_BE: Contents of section .got:
+# DSO_GOT_BE: 20000 00000000 80000000 00030000
+# ^ ^ ^-- v1 (0x30000)
+# | +-- Module pointer (0x80000000)
+# +-- Lazy resolver (0x0)
+
+# DSO_GOT_EL: Contents of section .got:
+# DSO_GOT_EL: 20000 00000000 00000080 00000300
+# ^ ^ ^-- v1 (0x30000)
+# | +-- Module pointer (0x80000000)
+# +-- Lazy resolver (0x0)
+
+# v1GotAddr (0x2000c) - _gp (0x27ff4) = -0x7fe8 => 0x8018 = 32792
+# DSO_DIS_BE: 10000: 3c 02 80 18 lui $2, 32792
+# DSO_DIS_EL: 10000: 18 80 02 3c lui $2, 32792
+
+# NORELOC: Relocations [
+# NORELOC-NEXT: ]
+
+# SHFLAGS: Name: .got
+# SHFLAGS-NEXT: Type: SHT_PROGBITS
+# SHFLAGS-NEXT: Flags [ (0x10000003)
+# ^-- SHF_MIPS_GPREL | SHF_ALLOC | SHF_WRITE
diff --git a/test/ELF/mips-gprel32-relocs.s b/test/ELF/mips-gprel32-relocs.s
new file mode 100644
index 000000000000..4f93d50363c0
--- /dev/null
+++ b/test/ELF/mips-gprel32-relocs.s
@@ -0,0 +1,31 @@
+# Check R_MIPS_GPREL32 relocation calculation.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: ld.lld -shared -o %t.so %t.o
+# RUN: llvm-objdump -s -section=.rodata -t %t.so | FileCheck %s
+
+# REQUIRES: mips
+
+ .text
+ .globl __start
+__start:
+ lw $t0,%call16(__start)($gp)
+foo:
+ nop
+bar:
+ nop
+
+ .section .rodata, "a"
+v1:
+ .gpword foo
+ .gpword bar
+
+# CHECK: Contents of section .rodata:
+# CHECK: 0114 fffe8014 fffe8018
+# ^ 0x10004 - 0x27ff0
+# ^ 0x10008 - 0x27ff0
+
+# CHECK: SYMBOL TABLE:
+# CHECK: 00010008 .text 00000000 bar
+# CHECK: 00010004 .text 00000000 foo
+# CHECK: 00027ff0 *ABS* 00000000 _gp
diff --git a/test/ELF/mips-hilo-gp-disp.s b/test/ELF/mips-hilo-gp-disp.s
new file mode 100644
index 000000000000..e2e9ae7bc2e2
--- /dev/null
+++ b/test/ELF/mips-hilo-gp-disp.s
@@ -0,0 +1,42 @@
+# Check R_MIPS_HI16 / LO16 relocations calculation against _gp_disp.
+
+# 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 %t1.o %t2.o -o %t.exe
+# RUN: llvm-objdump -d -t %t.exe | FileCheck -check-prefix=EXE %s
+# RUN: ld.lld %t1.o %t2.o -shared -o %t.so
+# RUN: llvm-objdump -d -t %t.so | FileCheck -check-prefix=SO %s
+
+# REQUIRES: mips
+
+ .text
+ .globl __start
+__start:
+ lui $t0,%hi(_gp_disp)
+ addi $t0,$t0,%lo(_gp_disp)
+ lw $v0,%call16(_foo)($gp)
+
+# EXE: Disassembly of section .text:
+# EXE-NEXT: __start:
+# EXE-NEXT: 20000: 3c 08 00 01 lui $8, 1
+# ^-- %hi(0x37ff0-0x20000)
+# EXE-NEXT: 20004: 21 08 7f f0 addi $8, $8, 32752
+# ^-- %lo(0x37ff0-0x20004+4)
+
+# EXE: SYMBOL TABLE:
+# EXE: 00037ff0 *ABS* 00000000 _gp
+# EXE: 00020000 .text 00000000 __start
+# EXE: 00020010 .text 00000000 _foo
+
+# SO: Disassembly of section .text:
+# SO-NEXT: __start:
+# SO-NEXT: 10000: 3c 08 00 01 lui $8, 1
+# ^-- %hi(0x27ff0-0x10000)
+# SO-NEXT: 10004: 21 08 7f f0 addi $8, $8, 32752
+# ^-- %lo(0x27ff0-0x10004+4)
+
+# SO: SYMBOL TABLE:
+# SO: 00027ff0 *ABS* 00000000 _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
new file mode 100644
index 000000000000..ad18a9f9161a
--- /dev/null
+++ b/test/ELF/mips-hilo-hi-only.s
@@ -0,0 +1,28 @@
+# Check warning on orphaned R_MIPS_HI16 relocations.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t.exe 2>&1 | FileCheck -check-prefix=WARN %s
+# RUN: llvm-objdump -d -t %t.exe | FileCheck %s
+
+# REQUIRES: mips
+
+ .text
+ .globl __start
+__start:
+ lui $t0,%hi(__start+0x10000)
+ addi $t0,$t0,%lo(_label)
+_label:
+ nop
+
+# WARN: Can't find matching R_MIPS_LO16 relocation for R_MIPS_HI16
+
+# CHECK: Disassembly of section .text:
+# CHECK-NEXT: __start:
+# CHECK-NEXT: 20000: 3c 08 00 02 lui $8, 2
+# ^-- %hi(__start) w/o addend
+# CHECK-NEXT 20004: 21 08 00 08 addi $8, $8, 8
+# ^-- %lo(_label)
+
+# CHECK: SYMBOL TABLE:
+# CHECK: 00020008 .text 00000000 _label
+# CHECK: 00020000 .text 00000000 __start
diff --git a/test/ELF/mips-hilo.s b/test/ELF/mips-hilo.s
new file mode 100644
index 000000000000..d5de9422c427
--- /dev/null
+++ b/test/ELF/mips-hilo.s
@@ -0,0 +1,53 @@
+# Check R_MIPS_HI16 / LO16 relocations calculation.
+
+# 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 %s
+
+# REQUIRES: mips
+
+ .text
+ .globl __start
+__start:
+ lui $t0,%hi(__start)
+ lui $t1,%hi(g1)
+ addi $t0,$t0,%lo(__start+4)
+ addi $t0,$t0,%lo(g1+8)
+
+ lui $t0,%hi(l1+0x10000)
+ lui $t1,%hi(l1+0x20000)
+ addi $t0,$t0,%lo(l1+(-4))
+
+ .data
+ .type l1,@object
+ .size l1,4
+l1:
+ .word 0
+
+ .globl g1
+ .type g1,@object
+ .size g1,4
+g1:
+ .word 0
+
+# CHECK: Disassembly of section .text:
+# 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
+# ^-- %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
+# ^-- %hi(l1+0x10000-4)
+# CHECK-NEXT: 20014: 3c 09 00 05 lui $9, 5
+# ^-- %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: 0020000 .text 00000000 __start
+# CHECK: 0030004 g .data 00000004 g1
diff --git a/test/ELF/mips-jalr.test b/test/ELF/mips-jalr.test
new file mode 100644
index 000000000000..4bdf8b6e7f00
--- /dev/null
+++ b/test/ELF/mips-jalr.test
@@ -0,0 +1,47 @@
+# Check that lld ignores R_MIPS_JALR relocation for now.
+
+# RUN: yaml2obj -format elf %s -o %t.o
+# RUN: ld.lld %t.o -o %t.so -shared
+# RUN: llvm-objdump -d %t.so | FileCheck %s
+
+# REQUIRES: mips
+
+# CHECK: 10000: 09 f8 20 03 jalr $25
+
+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: "09f82003"
+# ^-- jalr T1
+
+ - Name: .rel.text
+ Type: SHT_REL
+ Link: .symtab
+ Info: .text
+ Relocations:
+ - Offset: 0
+ Symbol: T1
+ Type: R_MIPS_JALR
+
+Symbols:
+ Local:
+ - Name: T1
+ Type: STT_FUNC
+ Section: .text
+ Value: 0
+ Size: 4
+ Global:
+ - Name: __start
+ Type: STT_FUNC
+ Section: .text
+ Value: 0
+ Size: 4
diff --git a/test/ELF/mips-pc-relocs.s b/test/ELF/mips-pc-relocs.s
new file mode 100644
index 000000000000..631dd433925a
--- /dev/null
+++ b/test/ELF/mips-pc-relocs.s
@@ -0,0 +1,38 @@
+# Check R_MIPS_PCxxx relocations calculation.
+
+# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
+# RUN: -mcpu=mips32r6 %s -o %t1.o
+# 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
+
+# REQUIRES: mips
+
+ .text
+ .globl __start
+__start:
+ lwpc $6, _foo # R_MIPS_PC19_S2
+ beqc $5, $6, _foo # R_MIPS_PC16
+ beqzc $9, _foo # R_MIPS_PC21_S2
+ bc _foo # R_MIPS_PC26_S2
+ aluipc $2, %pcrel_hi(_foo) # R_MIPS_PCHI16
+ addiu $2, $2, %pcrel_lo(_foo) # R_MIPS_PCLO16
+
+# 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
+# ^-- (0x20020-4-0x20004)>>2
+# CHECK-NEXT: 20008: d9 20 00 05 beqzc $9, 20
+# ^-- (0x20020-4-0x20008)>>2
+# CHECK-NEXT: 2000c: c8 00 00 04 bc 16
+# ^-- (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: 00020000 .text 00000000 __start
+# CHECK: 00020020 .text 00000000 _foo
diff --git a/test/ELF/mips-reginfo.s b/test/ELF/mips-reginfo.s
new file mode 100644
index 000000000000..dd4771c98b8d
--- /dev/null
+++ b/test/ELF/mips-reginfo.s
@@ -0,0 +1,26 @@
+# Check MIPS .reginfo section generation.
+
+# 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 %t1.o %t2.o -shared -o %t.so
+# RUN: llvm-readobj -symbols -mips-reginfo %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 RegInfo {
+# CHECK-NEXT: GP: 0x[[GP]]
+# CHECK-NEXT: General Mask: 0x10000101
+# 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: }
diff --git a/test/ELF/mips-relocs.s b/test/ELF/mips-relocs.s
new file mode 100644
index 000000000000..c05b8fd3bdd1
--- /dev/null
+++ b/test/ELF/mips-relocs.s
@@ -0,0 +1,42 @@
+# 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/new-dtags.test b/test/ELF/new-dtags.test
new file mode 100644
index 000000000000..334d477622a7
--- /dev/null
+++ b/test/ELF/new-dtags.test
@@ -0,0 +1,15 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -rpath=/somepath -shared --disable-new-dtags -o %t
+// RUN: ld.lld %t.o -rpath=/somepath -shared --enable-new-dtags -o %t2
+// RUN: llvm-readobj --dynamic-table %t | FileCheck --check-prefix=DISABLE %s
+// RUN: llvm-readobj --dynamic-table %t2 | FileCheck --check-prefix=ENABLE %s
+
+// DISABLE: DynamicSection [
+// DISABLE: 0x000000000000000F RPATH /somepath
+// DISABLE-NOT: RUNPATH
+// DISABLE: ]
+
+// ENABLE: DynamicSection [
+// ENABLE: 0x000000000000001D RUNPATH /somepath
+// ENABLE-NOT: RPATH
+// ENABLE: ]
diff --git a/test/ELF/no-inhibit-exec.s b/test/ELF/no-inhibit-exec.s
new file mode 100644
index 000000000000..fe2240b731fe
--- /dev/null
+++ b/test/ELF/no-inhibit-exec.s
@@ -0,0 +1,15 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: not ld.lld %t -o %t2
+# RUN: ld.lld %t --noinhibit-exec -o %t2
+# RUN: llvm-objdump -d %t2 | FileCheck %s
+# REQUIRES: x86
+
+# CHECK: Disassembly of section .text:
+# CHECK-NEXT: _start
+# 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;
+_start:
+ call _bar
diff --git a/test/ELF/no-obj.s b/test/ELF/no-obj.s
new file mode 100644
index 000000000000..68e9979e3ede
--- /dev/null
+++ b/test/ELF/no-obj.s
@@ -0,0 +1,8 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: llvm-ar rcs %t.a %t.o
+// RUN: not ld.lld -o %t2 -u _start %t.a 2>&1 | FileCheck %s
+
+// CHECK: -m or at least a .o file required
+
+.global _start
+_start:
diff --git a/test/ELF/no-symtab.s b/test/ELF/no-symtab.s
new file mode 100644
index 000000000000..158bd727f251
--- /dev/null
+++ b/test/ELF/no-symtab.s
@@ -0,0 +1,4 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o %p/Inputs/no-symtab.o -o %t
+.global _start
+_start:
diff --git a/test/ELF/no-undefined.s b/test/ELF/no-undefined.s
new file mode 100644
index 000000000000..94378bde40a2
--- /dev/null
+++ b/test/ELF/no-undefined.s
@@ -0,0 +1,7 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: not ld.lld --no-undefined -shared %t -o %t.so
+# RUN: ld.lld -shared %t -o %t1.so
+
+.globl _shared
+_shared:
+ call _unresolved
diff --git a/test/ELF/output-section.s b/test/ELF/output-section.s
new file mode 100644
index 000000000000..68505254686c
--- /dev/null
+++ b/test/ELF/output-section.s
@@ -0,0 +1,34 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: ld.lld %t -o %t2
+// RUN: llvm-readobj -t %t2 | FileCheck %s
+// REQUIRES: x86
+
+// CHECK: Symbol {
+// CHECK: Name: bar_sym
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Binding:
+// CHECK-NEXT: Type:
+// CHECK-NEXT: Other:
+// CHECK-NEXT: Section: bar
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: foo_sym
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Binding:
+// CHECK-NEXT: Type:
+// CHECK-NEXT: Other:
+// CHECK-NEXT: Section: foo
+// CHECK-NEXT: }
+
+.section foo
+.global foo_sym
+foo_sym:
+
+.section bar, "a"
+.global bar_sym
+bar_sym:
+
+.global _start
+_start:
diff --git a/test/ELF/plt-aarch64.s b/test/ELF/plt-aarch64.s
new file mode 100644
index 000000000000..6ea732ec7c68
--- /dev/null
+++ b/test/ELF/plt-aarch64.s
@@ -0,0 +1,205 @@
+// 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: 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
+// RUN: llvm-readobj -s -r %t.so | FileCheck --check-prefix=CHECKDSO %s
+// RUN: llvm-objdump -s -section=.got.plt %t.so | FileCheck --check-prefix=DUMPDSO %s
+// RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASMDSO %s
+// RUN: llvm-readobj -s -r %t.exe | FileCheck --check-prefix=CHECKEXE %s
+// RUN: llvm-objdump -s -section=.got.plt %t.exe | FileCheck --check-prefix=DUMPEXE %s
+// RUN: llvm-objdump -d %t.exe | FileCheck --check-prefix=DISASMEXE %s
+
+// REQUIRES: aarch64
+
+// CHECKDSO: Name: .plt
+// CHECKDSO-NEXT: Type: SHT_PROGBITS
+// CHECKDSO-NEXT: Flags [
+// CHECKDSO-NEXT: SHF_ALLOC
+// CHECKDSO-NEXT: SHF_EXECINSTR
+// CHECKDSO-NEXT: ]
+// CHECKDSO-NEXT: Address: 0x1010
+// CHECKDSO-NEXT: Offset:
+// CHECKDSO-NEXT: Size: 80
+// CHECKDSO-NEXT: Link:
+// CHECKDSO-NEXT: Info:
+// CHECKDSO-NEXT: AddressAlignment: 16
+
+// CHECKDSO: Name: .got.plt
+// CHECKDSO-NEXT: Type: SHT_PROGBITS
+// CHECKDSO-NEXT: Flags [
+// CHECKDSO-NEXT: SHF_ALLOC
+// CHECKDSO-NEXT: SHF_WRITE
+// CHECKDSO-NEXT: ]
+// CHECKDSO-NEXT: Address: 0x3000
+// CHECKDSO-NEXT: Offset:
+// CHECKDSO-NEXT: Size: 48
+// CHECKDSO-NEXT: Link:
+// CHECKDSO-NEXT: Info:
+// CHECKDSO-NEXT: AddressAlignment: 8
+
+// CHECKDSO: Relocations [
+// CHECKDSO-NEXT: Section ({{.*}}) .rela.plt {
+
+// &(.got.plt[3]) = 0x3000 + 3 * 8 = 0x3018
+// CHECKDSO-NEXT: 0x3018 R_AARCH64_JUMP_SLOT foo
+
+// &(.got.plt[4]) = 0x3000 + 4 * 8 = 0x3020
+// CHECKDSO-NEXT: 0x3020 R_AARCH64_JUMP_SLOT bar
+
+// &(.got.plt[5]) = 0x3000 + 5 * 8 = 0x3028
+// CHECKDSO-NEXT: 0x3028 R_AARCH64_JUMP_SLOT weak
+// CHECKDSO-NEXT: }
+// CHECKDSO-NEXT: ]
+
+// DUMPDSO: Contents of section .got.plt:
+// .got.plt[0..2] = 0 (reserved)
+// .got.plt[3..5] = .plt = 0x1010
+// DUMPDSO-NEXT: 3000 00000000 00000000 00000000 00000000 ................
+// DUMPDSO-NEXT: 3010 00000000 00000000 10100000 00000000 ................
+// DUMPDSO-NEXT: 3020 10100000 00000000 10100000 00000000 ................
+
+// DISASMDSO: _start:
+// 0x1030 - 0x1000 = 0x30 = 48
+// DISASMDSO-NEXT: 1000: 0c 00 00 14 b #48
+// 0x1040 - 0x1004 = 0x3c = 60
+// DISASMDSO-NEXT: 1004: 0f 00 00 14 b #60
+// 0x1050 - 0x1008 = 0x48 = 72
+// DISASMDSO-NEXT: 1008: 12 00 00 14 b #72
+
+// DISASMDSO: foo:
+// DISASMDSO-NEXT: 100c: 1f 20 03 d5 nop
+
+// DISASMDSO: Disassembly of section .plt:
+// DISASMDSO-NEXT: .plt:
+// DISASMDSO-NEXT: 1010: f0 7b bf a9 stp x16, x30, [sp, #-16]!
+// &(.got.plt[2]) = 0x3000 + 2 * 8 = 0x3010
+// Page(0x3010) - Page(0x1014) = 0x3000 - 0x1000 = 0x2000 = 8192
+// DISASMDSO-NEXT: 1014: 10 00 00 d0 adrp x16, #8192
+// 0x3010 & 0xFFF = 0x10 = 16
+// DISASMDSO-NEXT: 1018: 11 0a 40 f9 ldr x17, [x16, #16]
+// DISASMDSO-NEXT: 101c: 10 42 00 91 add x16, x16, #16
+// DISASMDSO-NEXT: 1020: 20 02 1f d6 br x17
+// DISASMDSO-NEXT: 1024: 1f 20 03 d5 nop
+// DISASMDSO-NEXT: 1028: 1f 20 03 d5 nop
+// DISASMDSO-NEXT: 102c: 1f 20 03 d5 nop
+
+// foo@plt
+// Page(0x3018) - Page(0x1030) = 0x3000 - 0x1000 = 0x2000 = 8192
+// DISASMDSO-NEXT: 1030: 10 00 00 d0 adrp x16, #8192
+// 0x3018 & 0xFFF = 0x18 = 24
+// DISASMDSO-NEXT: 1034: 11 0e 40 f9 ldr x17, [x16, #24]
+// DISASMDSO-NEXT: 1038: 10 62 00 91 add x16, x16, #24
+// DISASMDSO-NEXT: 103c: 20 02 1f d6 br x17
+
+// bar@plt
+// Page(0x3020) - Page(0x1040) = 0x3000 - 0x1000 = 0x2000 = 8192
+// DISASMDSO-NEXT: 1040: 10 00 00 d0 adrp x16, #8192
+// 0x3020 & 0xFFF = 0x20 = 32
+// DISASMDSO-NEXT: 1044: 11 12 40 f9 ldr x17, [x16, #32]
+// DISASMDSO-NEXT: 1048: 10 82 00 91 add x16, x16, #32
+// DISASMDSO-NEXT: 104c: 20 02 1f d6 br x17
+
+// weak@plt
+// Page(0x3028) - Page(0x1050) = 0x3000 - 0x1000 = 0x2000 = 8192
+// DISASMDSO-NEXT: 1050: 10 00 00 d0 adrp x16, #8192
+// 0x3028 & 0xFFF = 0x28 = 40
+// DISASMDSO-NEXT: 1054: 11 16 40 f9 ldr x17, [x16, #40]
+// DISASMDSO-NEXT: 1058: 10 a2 00 91 add x16, x16, #40
+// DISASMDSO-NEXT: 105c: 20 02 1f d6 br x17
+
+// CHECKEXE: Name: .plt
+// CHECKEXE-NEXT: Type: SHT_PROGBITS
+// CHECKEXE-NEXT: Flags [
+// CHECKEXE-NEXT: SHF_ALLOC
+// CHECKEXE-NEXT: SHF_EXECINSTR
+// CHECKEXE-NEXT: ]
+// CHECKEXE-NEXT: Address: 0x11010
+// CHECKEXE-NEXT: Offset:
+// CHECKEXE-NEXT: Size: 64
+// CHECKEXE-NEXT: Link:
+// CHECKEXE-NEXT: Info:
+// CHECKEXE-NEXT: AddressAlignment: 16
+
+// CHECKEXE: Name: .got.plt
+// CHECKEXE-NEXT: Type: SHT_PROGBITS
+// CHECKEXE-NEXT: Flags [
+// CHECKEXE-NEXT: SHF_ALLOC
+// CHECKEXE-NEXT: SHF_WRITE
+// CHECKEXE-NEXT: ]
+// CHECKEXE-NEXT: Address: 0x13000
+// CHECKEXE-NEXT: Offset:
+// CHECKEXE-NEXT: Size: 40
+// CHECKEXE-NEXT: Link:
+// CHECKEXE-NEXT: Info:
+// CHECKEXE-NEXT: AddressAlignment: 8
+
+// CHECKEXE: Relocations [
+// CHECKEXE-NEXT: Section ({{.*}}) .rela.plt {
+
+// &(.got.plt[3]) = 0x13000 + 3 * 8 = 0x13018
+// CHECKEXE-NEXT: 0x13018 R_AARCH64_JUMP_SLOT bar 0x0
+
+// &(.got.plt[4]) = 0x13000 + 4 * 8 = 0x13020
+// CHECKEXE-NEXT: 0x13020 R_AARCH64_JUMP_SLOT weak 0x0
+// CHECKEXE-NEXT: }
+// CHECKEXE-NEXT: ]
+
+// DUMPEXE: Contents of section .got.plt:
+// .got.plt[0..2] = 0 (reserved)
+// .got.plt[3..4] = .plt = 0x11010
+// DUMPEXE-NEXT: 13000 00000000 00000000 00000000 00000000 ................
+// DUMPEXE-NEXT: 13010 00000000 00000000 10100100 00000000 ................
+// DUMPEXE-NEXT: 13020 10100100 00000000 ........
+
+// DISASMEXE: _start:
+// 0x1100c - 0x11000 = 0xc = 12
+// DISASMEXE-NEXT: 11000: 03 00 00 14 b #12
+// 0x11030 - 0x11004 = 0x2c = 44
+// DISASMEXE-NEXT: 11004: 0b 00 00 14 b #44
+// 0x11040 - 0x11008 = 0x38 = 56
+// DISASMEXE-NEXT: 11008: 0e 00 00 14 b #56
+
+// DISASMEXE: foo:
+// DISASMEXE-NEXT: 1100c: 1f 20 03 d5 nop
+
+// DISASMEXE: Disassembly of section .plt:
+// DISASMEXE-NEXT: .plt:
+// DISASMEXE-NEXT: 11010: f0 7b bf a9 stp x16, x30, [sp, #-16]!
+// &(.got.plt[2]) = 0x120B0 + 2 * 8 = 0x120C0
+// Page(0x13010) - Page(0x11014) = 0x13000 - 0x11000 = 0x1000 = 8192
+// DISASMEXE-NEXT: 11014: 10 00 00 d0 adrp x16, #8192
+// 0x120c0 & 0xFFF = 0xC0 = 192
+// DISASMEXE-NEXT: 11018: 11 0a 40 f9 ldr x17, [x16, #16]
+// DISASMEXE-NEXT: 1101c: 10 42 00 91 add x16, x16, #16
+// DISASMEXE-NEXT: 11020: 20 02 1f d6 br x17
+// DISASMEXE-NEXT: 11024: 1f 20 03 d5 nop
+// DISASMEXE-NEXT: 11028: 1f 20 03 d5 nop
+// DISASMEXE-NEXT: 1102c: 1f 20 03 d5 nop
+
+// bar@plt
+// Page(0x13018) - Page(0x11030) = 0x12000 - 0x11000 = 0x1000 = 8192
+// DISASMEXE-NEXT: 11030: 10 00 00 d0 adrp x16, #8192
+// 0x120C8 & 0xFFF = 0xC8 = 200
+// DISASMEXE-NEXT: 11034: 11 0e 40 f9 ldr x17, [x16, #24]
+// DISASMEXE-NEXT: 11038: 10 62 00 91 add x16, x16, #24
+// DISASMEXE-NEXT: 1103c: 20 02 1f d6 br x17
+
+// weak@plt
+// Page(0x13020) - Page(0x11040) = 0x12000 - 0x11000 = 0x1000 = 8192
+// DISASMEXE-NEXT: 11040: 10 00 00 d0 adrp x16, #8192
+// 0x120D0 & 0xFFF = 0xD0 = 208
+// DISASMEXE-NEXT: 11044: 11 12 40 f9 ldr x17, [x16, #32]
+// DISASMEXE-NEXT: 11048: 10 82 00 91 add x16, x16, #32
+// DISASMEXE-NEXT: 1104c: 20 02 1f d6 br x17
+
+.global _start,foo,bar
+.weak weak
+_start:
+ b foo
+ b bar
+ b weak
+
+.section .text2,"ax",@progbits
+foo:
+ nop
diff --git a/test/ELF/plt-i686.s b/test/ELF/plt-i686.s
new file mode 100644
index 000000000000..4947e0e734fd
--- /dev/null
+++ b/test/ELF/plt-i686.s
@@ -0,0 +1,158 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
+// 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-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
+
+// REQUIRES: x86
+
+// CHECK: Name: .plt
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_EXECINSTR
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x11020
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 48
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 16
+
+// 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: 0x13000
+// CHECK-NEXT: Offset: 0x3000
+// CHECK-NEXT: Size: 20
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 4
+// CHECK-NEXT: EntrySize: 0
+
+// 0x13000 + got.plt.reserved(12) = 0x1300C
+// 0x13000 + got.plt.reserved(12) + 4 = 0x13010
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rel.plt {
+// CHECK-NEXT: 0x1300C R_386_JUMP_SLOT bar 0x0
+// CHECK-NEXT: 0x13010 R_386_JUMP_SLOT zed 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+// Unfortunately FileCheck can't do math, so we have to check for explicit
+// values:
+
+// 16 is the size of PLT[0]
+// (0x11010 + 16) - (0x11000 + 1) - 4 = 27
+// (0x11010 + 16) - (0x11005 + 1) - 4 = 22
+// (0x11020 + 16) - (0x1100a + 1) - 4 = 33
+
+// DISASM: local:
+// DISASM-NEXT: 11000: {{.*}}
+// DISASM-NEXT: 11002: {{.*}}
+// DISASM: _start:
+// 0x11013 + 5 - 24 = 0x11000
+// DISASM-NEXT: 11004: e9 27 00 00 00 jmp 39
+// DISASM-NEXT: 11009: e9 22 00 00 00 jmp 34
+// DISASM-NEXT: 1100e: e9 2d 00 00 00 jmp 45
+// DISASM-NEXT: 11013: e9 e8 ff ff ff jmp -24
+
+// 0x11010 - 0x1102b - 5 = -32
+// 0x11010 - 0x1103b - 5 = -48
+// 77828 = 0x13004 = .got.plt (0x13000) + 4
+// 77832 = 0x13008 = .got.plt (0x13000) + 8
+// 77836 = 0x1300C = .got.plt (0x13000) + got.plt.reserved(12)
+// 77840 = 0x13010 = .got.plt (0x13000) + got.plt.reserved(12) + 4
+// DISASM: Disassembly of section .plt:
+// DISASM-NEXT: .plt:
+// DISASM-NEXT: 11020: ff 35 04 30 01 00 pushl 77828
+// DISASM-NEXT: 11026: ff 25 08 30 01 00 jmpl *77832
+// DISASM-NEXT: 1102c: 90 nop
+// DISASM-NEXT: 1102d: 90 nop
+// DISASM-NEXT: 1102e: 90 nop
+// DISASM-NEXT: 1102f: 90 nop
+// DISASM-NEXT: 11030: ff 25 0c 30 01 00 jmpl *77836
+// DISASM-NEXT: 11036: 68 00 00 00 00 pushl $0
+// DISASM-NEXT: 1103b: e9 e0 ff ff ff jmp -32 <.plt>
+// DISASM-NEXT: 11040: ff 25 10 30 01 00 jmpl *77840
+// DISASM-NEXT: 11046: 68 08 00 00 00 pushl $8
+// DISASM-NEXT: 1104b: e9 d0 ff ff ff jmp -48 <.plt>
+
+// CHECKSHARED: Name: .plt
+// CHECKSHARED-NEXT: Type: SHT_PROGBITS
+// CHECKSHARED-NEXT: Flags [
+// CHECKSHARED-NEXT: SHF_ALLOC
+// CHECKSHARED-NEXT: SHF_EXECINSTR
+// CHECKSHARED-NEXT: ]
+// CHECKSHARED-NEXT: Address: 0x1020
+// CHECKSHARED-NEXT: Offset: 0x1020
+// CHECKSHARED-NEXT: Size: 48
+// CHECKSHARED-NEXT: Link: 0
+// CHECKSHARED-NEXT: Info: 0
+// CHECKSHARED-NEXT: AddressAlignment: 16
+// CHECKSHARED-NEXT: EntrySize: 0
+// CHECKSHARED-NEXT: }
+// CHECKSHARED: Name: .got.plt
+// CHECKSHARED-NEXT: Type: SHT_PROGBITS
+// CHECKSHARED-NEXT: Flags [
+// CHECKSHARED-NEXT: SHF_ALLOC
+// CHECKSHARED-NEXT: SHF_WRITE
+// CHECKSHARED-NEXT: ]
+// CHECKSHARED-NEXT: Address: 0x3000
+// CHECKSHARED-NEXT: Offset: 0x3000
+// CHECKSHARED-NEXT: Size: 20
+// CHECKSHARED-NEXT: Link: 0
+// CHECKSHARED-NEXT: Info: 0
+// CHECKSHARED-NEXT: AddressAlignment: 4
+// CHECKSHARED-NEXT: EntrySize: 0
+// CHECKSHARED-NEXT: }
+
+// 0x3000 + got.plt.reserved(12) = 0x300C
+// 0x3000 + got.plt.reserved(12) + 4 = 0x3010
+// CHECKSHARED: Relocations [
+// CHECKSHARED-NEXT: Section ({{.*}}) .rel.plt {
+// CHECKSHARED-NEXT: 0x300C R_386_JUMP_SLOT bar 0x0
+// CHECKSHARED-NEXT: 0x3010 R_386_JUMP_SLOT zed 0x0
+// CHECKSHARED-NEXT: }
+// CHECKSHARED-NEXT: ]
+
+// DISASMSHARED: local:
+// DISASMSHARED-NEXT: 1000: {{.*}}
+// DISASMSHARED-NEXT: 1002: {{.*}}
+// DISASMSHARED: _start:
+// 0x1013 + 5 - 24 = 0x1000
+// DISASMSHARED-NEXT: 1004: e9 27 00 00 00 jmp 39
+// DISASMSHARED-NEXT: 1009: e9 22 00 00 00 jmp 34
+// DISASMSHARED-NEXT: 100e: e9 2d 00 00 00 jmp 45
+// DISASMSHARED-NEXT: 1013: e9 e8 ff ff ff jmp -24
+// DISASMSHARED-NEXT: Disassembly of section .plt:
+// DISASMSHARED-NEXT: .plt:
+// DISASMSHARED-NEXT: 1020: ff b3 04 00 00 00 pushl 4(%ebx)
+// DISASMSHARED-NEXT: 1026: ff a3 08 00 00 00 jmpl *8(%ebx)
+// DISASMSHARED-NEXT: 102c: 90 nop
+// DISASMSHARED-NEXT: 102d: 90 nop
+// DISASMSHARED-NEXT: 102e: 90 nop
+// DISASMSHARED-NEXT: 102f: 90 nop
+// DISASMSHARED-NEXT: 1030: ff a3 0c 00 00 00 jmpl *12(%ebx)
+// DISASMSHARED-NEXT: 1036: 68 00 00 00 00 pushl $0
+// DISASMSHARED-NEXT: 103b: e9 e0 ff ff ff jmp -32 <.plt>
+// DISASMSHARED-NEXT: 1040: ff a3 10 00 00 00 jmpl *16(%ebx)
+// DISASMSHARED-NEXT: 1046: 68 08 00 00 00 pushl $8
+// DISASMSHARED-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt>
+
+local:
+.long 0
+
+.global _start
+_start:
+ jmp bar@PLT
+ jmp bar@PLT
+ jmp zed@PLT
+ jmp local@plt
diff --git a/test/ELF/plt.s b/test/ELF/plt.s
new file mode 100644
index 000000000000..1183d32c3ccc
--- /dev/null
+++ b/test/ELF/plt.s
@@ -0,0 +1,119 @@
+// 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: ld.lld -shared %t2.o -o %t2.so
+// RUN: ld.lld -shared %t.o %t2.so -o %t
+// RUN: ld.lld %t.o %t2.so -o %t3
+// RUN: llvm-readobj -s -r %t | FileCheck %s
+// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
+// RUN: llvm-readobj -s -r %t3 | FileCheck --check-prefix=CHECK2 %s
+// RUN: llvm-objdump -d %t3 | FileCheck --check-prefix=DISASM2 %s
+
+// REQUIRES: x86
+
+// CHECK: Name: .plt
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_EXECINSTR
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x1020
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 64
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 16
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.plt {
+// CHECK-NEXT: 0x3018 R_X86_64_JUMP_SLOT bar 0x0
+// CHECK-NEXT: 0x3020 R_X86_64_JUMP_SLOT zed 0x0
+// CHECK-NEXT: 0x3028 R_X86_64_JUMP_SLOT _start 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+// CHECK2: Name: .plt
+// CHECK2-NEXT: Type: SHT_PROGBITS
+// CHECK2-NEXT: Flags [
+// CHECK2-NEXT: SHF_ALLOC
+// CHECK2-NEXT: SHF_EXECINSTR
+// CHECK2-NEXT: ]
+// CHECK2-NEXT: Address: 0x11020
+// CHECK2-NEXT: Offset:
+// CHECK2-NEXT: Size: 48
+// CHECK2-NEXT: Link: 0
+// CHECK2-NEXT: Info: 0
+// CHECK2-NEXT: AddressAlignment: 16
+
+// CHECK2: Relocations [
+// CHECK2-NEXT: Section ({{.*}}) .rela.plt {
+// CHECK2-NEXT: 0x13018 R_X86_64_JUMP_SLOT bar 0x0
+// CHECK2-NEXT: 0x13020 R_X86_64_JUMP_SLOT zed 0x0
+// CHECK2-NEXT: }
+// CHECK2-NEXT: ]
+
+// Unfortunately FileCheck can't do math, so we have to check for explicit
+// values:
+
+// 0x1030 - (0x1000 + 5) = 43
+// 0x1030 - (0x1005 + 5) = 38
+// 0x1040 - (0x100a + 5) = 49
+// 0x1048 - (0x100a + 5) = 60
+
+// DISASM: _start:
+// DISASM-NEXT: 1000: e9 {{.*}} jmp 43
+// DISASM-NEXT: 1005: e9 {{.*}} jmp 38
+// DISASM-NEXT: 100a: e9 {{.*}} jmp 49
+// DISASM-NEXT: 100f: e9 {{.*}} jmp 60
+
+// 0x3018 - 0x1036 = 8162
+// 0x3020 - 0x1046 = 4234
+// 0x3028 - 0x1056 = 4226
+
+// DISASM: Disassembly of section .plt:
+// DISASM-NEXT: .plt:
+// DISASM-NEXT: 1020: ff 35 e2 1f 00 00 pushq 8162(%rip)
+// DISASM-NEXT: 1026: ff 25 e4 1f 00 00 jmpq *8164(%rip)
+// DISASM-NEXT: 102c: 0f 1f 40 00 nopl (%rax)
+// DISASM-NEXT: 1030: ff 25 e2 1f 00 00 jmpq *8162(%rip)
+// DISASM-NEXT: 1036: 68 00 00 00 00 pushq $0
+// DISASM-NEXT: 103b: e9 e0 ff ff ff jmp -32 <.plt>
+// DISASM-NEXT: 1040: ff 25 da 1f 00 00 jmpq *8154(%rip)
+// DISASM-NEXT: 1046: 68 01 00 00 00 pushq $1
+// DISASM-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt>
+// DISASM-NEXT: 1050: ff 25 d2 1f 00 00 jmpq *8146(%rip)
+// DISASM-NEXT: 1056: 68 02 00 00 00 pushq $2
+// DISASM-NEXT: 105b: e9 c0 ff ff ff jmp -64 <.plt>
+
+// 0x11030 - (0x11000 + 1) - 4 = 43
+// 0x11030 - (0x11005 + 1) - 4 = 38
+// 0x11040 - (0x1100a + 1) - 4 = 49
+// 0x11000 - (0x1100f + 1) - 4 = -20
+
+// DISASM2: _start:
+// DISASM2-NEXT: 11000: e9 {{.*}} jmp 43
+// DISASM2-NEXT: 11005: e9 {{.*}} jmp 38
+// DISASM2-NEXT: 1100a: e9 {{.*}} jmp 49
+// DISASM2-NEXT: 1100f: e9 {{.*}} jmp -20
+
+// 0x13018 - 0x11036 = 4242
+// 0x13020 - 0x11046 = 4234
+
+// DISASM2: Disassembly of section .plt:
+// DISASM2-NEXT: .plt:
+// DISASM2-NEXT: 11020: ff 35 e2 1f 00 00 pushq 8162(%rip)
+// DISASM2-NEXT: 11026: ff 25 e4 1f 00 00 jmpq *8164(%rip)
+// DISASM2-NEXT: 1102c: 0f 1f 40 00 nopl (%rax)
+// DISASM2-NEXT: 11030: ff 25 e2 1f 00 00 jmpq *8162(%rip)
+// DISASM2-NEXT: 11036: 68 00 00 00 00 pushq $0
+// DISASM2-NEXT: 1103b: e9 e0 ff ff ff jmp -32 <.plt>
+// 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
+
+.global _start
+_start:
+ jmp bar@PLT
+ jmp bar@PLT
+ jmp zed@PLT
+ jmp _start@plt
diff --git a/test/ELF/ppc64-addr16-error.s b/test/ELF/ppc64-addr16-error.s
new file mode 100644
index 000000000000..57a919a9b338
--- /dev/null
+++ b/test/ELF/ppc64-addr16-error.s
@@ -0,0 +1,7 @@
+// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t
+// RUN: not ld.lld -shared %t -o %t2 2>&1 | FileCheck %s
+// REQUIRES: ppc
+
+.short sym+65539
+
+// CHECK: Relocation R_PPC64_ADDR16 out of range
diff --git a/test/ELF/ppc64-rel-calls.s b/test/ELF/ppc64-rel-calls.s
new file mode 100644
index 000000000000..f3b309f33dfb
--- /dev/null
+++ b/test/ELF/ppc64-rel-calls.s
@@ -0,0 +1,42 @@
+# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t2
+# RUN: llvm-objdump -d %t2 | FileCheck %s
+# REQUIRES: ppc
+
+# CHECK: Disassembly of section .text:
+
+.section ".opd","aw"
+.global _start
+_start:
+.quad .Lfoo,.TOC.@tocbase,0
+
+.text
+.Lfoo:
+ li 0,1
+ li 3,42
+ sc
+
+# CHECK: 10010000: 38 00 00 01 li 0, 1
+# CHECK: 10010004: 38 60 00 2a li 3, 42
+# CHECK: 10010008: 44 00 00 02 sc
+
+.section ".opd","aw"
+.global bar
+bar:
+.quad .Lbar,.TOC.@tocbase,0
+
+.text
+.Lbar:
+ bl _start
+ nop
+ bl .Lfoo
+ nop
+ blr
+
+# FIXME: The printing here is misleading, the branch offset here is negative.
+# CHECK: 1001000c: 4b ff ff f5 bl .+67108852
+# CHECK: 10010010: 60 00 00 00 nop
+# CHECK: 10010014: 4b ff ff ed bl .+67108844
+# CHECK: 10010018: 60 00 00 00 nop
+# CHECK: 1001001c: 4e 80 00 20 blr
+
diff --git a/test/ELF/ppc64-relocs.s b/test/ELF/ppc64-relocs.s
new file mode 100644
index 000000000000..61f9a1eb3ce3
--- /dev/null
+++ b/test/ELF/ppc64-relocs.s
@@ -0,0 +1,130 @@
+# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t2
+# RUN: llvm-objdump -d %t2 | FileCheck %s
+# REQUIRES: ppc
+
+.section ".opd","aw"
+.global _start
+_start:
+.quad .Lfoo,.TOC.@tocbase,0
+
+.text
+.Lfoo:
+ li 0,1
+ li 3,42
+ sc
+
+.section ".toc","aw"
+.L1:
+.quad 22, 37, 89, 47
+
+.section .R_PPC64_TOC16_LO_DS,"ax",@progbits
+.globl .FR_PPC64_TOC16_LO_DS
+.FR_PPC64_TOC16_LO_DS:
+ ld 1, .L1@toc@l(2)
+
+# CHECK: Disassembly of section .R_PPC64_TOC16_LO_DS:
+# CHECK: .FR_PPC64_TOC16_LO_DS:
+# CHECK: 1001000c: e8 22 80 00 ld 1, -32768(2)
+
+.section .R_PPC64_TOC16_LO,"ax",@progbits
+.globl .FR_PPC64_TOC16_LO
+.FR_PPC64_TOC16_LO:
+ addi 1, 2, .L1@toc@l
+
+# CHECK: Disassembly of section .R_PPC64_TOC16_LO:
+# CHECK: .FR_PPC64_TOC16_LO:
+# CHECK: 10010010: 38 22 80 00 addi 1, 2, -32768
+
+.section .R_PPC64_TOC16_HI,"ax",@progbits
+.globl .FR_PPC64_TOC16_HI
+.FR_PPC64_TOC16_HI:
+ addis 1, 2, .L1@toc@h
+
+# CHECK: Disassembly of section .R_PPC64_TOC16_HI:
+# CHECK: .FR_PPC64_TOC16_HI:
+# CHECK: 10010014: 3c 22 10 01 addis 1, 2, 4097
+
+.section .R_PPC64_TOC16_HA,"ax",@progbits
+.globl .FR_PPC64_TOC16_HA
+.FR_PPC64_TOC16_HA:
+ addis 1, 2, .L1@toc@ha
+
+# CHECK: Disassembly of section .R_PPC64_TOC16_HA:
+# CHECK: .FR_PPC64_TOC16_HA:
+# CHECK: 10010018: 3c 22 10 02 addis 1, 2, 4098
+
+.section .R_PPC64_REL24,"ax",@progbits
+.globl .FR_PPC64_REL24
+.FR_PPC64_REL24:
+ b .Lfoox
+.section .R_PPC64_REL24_2,"ax",@progbits
+.Lfoox:
+
+# CHECK: Disassembly of section .R_PPC64_REL24:
+# CHECK: .FR_PPC64_REL24:
+# CHECK: 1001001c: 48 00 00 04 b .+4
+
+.section .R_PPC64_ADDR16_LO,"ax",@progbits
+.globl .FR_PPC64_ADDR16_LO
+.FR_PPC64_ADDR16_LO:
+ li 1, .Lfoo@l
+
+# CHECK: Disassembly of section .R_PPC64_ADDR16_LO:
+# CHECK: .FR_PPC64_ADDR16_LO:
+# CHECK: 10010020: 38 20 00 00 li 1, 0
+
+.section .R_PPC64_ADDR16_HI,"ax",@progbits
+.globl .FR_PPC64_ADDR16_HI
+.FR_PPC64_ADDR16_HI:
+ li 1, .Lfoo@h
+
+# CHECK: Disassembly of section .R_PPC64_ADDR16_HI:
+# CHECK: .FR_PPC64_ADDR16_HI:
+# CHECK: 10010024: 38 20 10 01 li 1, 4097
+
+.section .R_PPC64_ADDR16_HA,"ax",@progbits
+.globl .FR_PPC64_ADDR16_HA
+.FR_PPC64_ADDR16_HA:
+ li 1, .Lfoo@ha
+
+# CHECK: Disassembly of section .R_PPC64_ADDR16_HA:
+# CHECK: .FR_PPC64_ADDR16_HA:
+# CHECK: 10010028: 38 20 10 01 li 1, 4097
+
+.section .R_PPC64_ADDR16_HIGHER,"ax",@progbits
+.globl .FR_PPC64_ADDR16_HIGHER
+.FR_PPC64_ADDR16_HIGHER:
+ li 1, .Lfoo@higher
+
+# CHECK: Disassembly of section .R_PPC64_ADDR16_HIGHER:
+# CHECK: .FR_PPC64_ADDR16_HIGHER:
+# CHECK: 1001002c: 38 20 00 00 li 1, 0
+
+.section .R_PPC64_ADDR16_HIGHERA,"ax",@progbits
+.globl .FR_PPC64_ADDR16_HIGHERA
+.FR_PPC64_ADDR16_HIGHERA:
+ li 1, .Lfoo@highera
+
+# CHECK: Disassembly of section .R_PPC64_ADDR16_HIGHERA:
+# CHECK: .FR_PPC64_ADDR16_HIGHERA:
+# CHECK: 10010030: 38 20 00 00 li 1, 0
+
+.section .R_PPC64_ADDR16_HIGHEST,"ax",@progbits
+.globl .FR_PPC64_ADDR16_HIGHEST
+.FR_PPC64_ADDR16_HIGHEST:
+ li 1, .Lfoo@highest
+
+# CHECK: Disassembly of section .R_PPC64_ADDR16_HIGHEST:
+# CHECK: .FR_PPC64_ADDR16_HIGHEST:
+# CHECK: 10010034: 38 20 00 00 li 1, 0
+
+.section .R_PPC64_ADDR16_HIGHESTA,"ax",@progbits
+.globl .FR_PPC64_ADDR16_HIGHESTA
+.FR_PPC64_ADDR16_HIGHESTA:
+ li 1, .Lfoo@highesta
+
+# CHECK: Disassembly of section .R_PPC64_ADDR16_HIGHESTA:
+# CHECK: .FR_PPC64_ADDR16_HIGHESTA:
+# CHECK: 10010038: 38 20 00 00 li 1, 0
+
diff --git a/test/ELF/ppc64-shared-rel-toc.s b/test/ELF/ppc64-shared-rel-toc.s
new file mode 100644
index 000000000000..f5cd45936683
--- /dev/null
+++ b/test/ELF/ppc64-shared-rel-toc.s
@@ -0,0 +1,27 @@
+// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
+// RUN: ld.lld -shared %t.o -o %t.so
+// RUN: llvm-readobj -t -r -dyn-symbols %t.so | FileCheck %s
+// REQUIRES: ppc
+
+// When we create the TOC reference in the shared library, make sure that the
+// R_PPC64_RELATIVE relocation uses the correct (non-zero) offset.
+
+ .globl foo
+ .align 2
+ .type foo,@function
+ .section .opd,"aw",@progbits
+foo: # @foo
+ .align 3
+ .quad .Lfunc_begin0
+ .quad .TOC.@tocbase
+ .quad 0
+ .text
+.Lfunc_begin0:
+ blr
+
+// CHECK: 0x30000 R_PPC64_RELATIVE - 0x10000
+// CHECK: 0x30008 R_PPC64_RELATIVE - 0x8000
+
+// CHECK: Name: foo
+// CHECK-NEXT: Value: 0x30000
+
diff --git a/test/ELF/ppc64-toc-restore.s b/test/ELF/ppc64-toc-restore.s
new file mode 100644
index 000000000000..cee105b35e64
--- /dev/null
+++ b/test/ELF/ppc64-toc-restore.s
@@ -0,0 +1,62 @@
+// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o
+// RUN: ld.lld -shared %t2.o -o %t2.so
+// RUN: ld.lld %t.o %t2.so -o %t
+// RUN: llvm-objdump -d %t | FileCheck %s
+// REQUIRES: ppc
+
+// CHECK: Disassembly of section .text:
+
+.global _start
+_start:
+ bl bar
+ nop
+
+// CHECK: _start:
+// CHECK: 10010000: 48 00 00 21 bl .+32
+// CHECK-NOT: 10010004: 60 00 00 00 nop
+// CHECK: 10010004: e8 41 00 28 ld 2, 40(1)
+
+.global noret
+noret:
+ bl bar
+ li 5, 7
+
+// CHECK: noret:
+// CHECK: 10010008: 48 00 00 19 bl .+24
+// CHECK: 1001000c: 38 a0 00 07 li 5, 7
+
+.global noretend
+noretend:
+ bl bar
+
+// CHECK: noretend:
+// CHECK: 10010010: 48 00 00 11 bl .+16
+
+.global noretb
+noretb:
+ b bar
+
+// CHECK: noretb:
+// CHECK: 10010014: 48 00 00 0c b .+12
+
+// This should come last to check the end-of-buffer condition.
+.global last
+last:
+ bl bar
+ nop
+
+// CHECK: last:
+// CHECK: 10010018: 48 00 00 09 bl .+8
+// CHECK: 1001001c: e8 41 00 28 ld 2, 40(1)
+
+// 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: 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)
+// CHECK: 10010038: e9 6c 00 10 ld 11, 16(12)
+// CHECK: 1001003c: 4e 80 04 20 bctr
diff --git a/test/ELF/ppc64-weak-undef-call-shared.s b/test/ELF/ppc64-weak-undef-call-shared.s
new file mode 100644
index 000000000000..2c27a27c5a10
--- /dev/null
+++ b/test/ELF/ppc64-weak-undef-call-shared.s
@@ -0,0 +1,16 @@
+# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
+# RUN: ld.lld -shared %t.o -o %t.so
+# RUN: llvm-readobj -t -r -dyn-symbols %t.so | FileCheck %s
+# REQUIRES: ppc
+
+.section ".toc","aw"
+.quad weakfunc
+// CHECK-NOT: R_PPC64_RELATIVE
+
+.text
+.Lfoo:
+ bl weakfunc
+// CHECK-NOT: R_PPC64_REL24
+
+.weak weakfunc
+
diff --git a/test/ELF/ppc64-weak-undef-call.s b/test/ELF/ppc64-weak-undef-call.s
new file mode 100644
index 000000000000..55443cb55b99
--- /dev/null
+++ b/test/ELF/ppc64-weak-undef-call.s
@@ -0,0 +1,27 @@
+# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t2
+# RUN: llvm-objdump -d %t2 | FileCheck %s
+# REQUIRES: ppc
+
+# CHECK: Disassembly of section .text:
+
+.section ".opd","aw"
+.global _start
+_start:
+.quad .Lfoo,.TOC.@tocbase,0
+
+.text
+.Lfoo:
+ bl weakfunc
+ nop
+ blr
+
+.weak weakfunc
+
+# It does not really matter how we fixup the bl, if at all, because it needs to
+# be unreachable. But, we should link successfully. We should not, however,
+# generate a .plt entry (this would be wasted space). For now, we do nothing
+# (leaving the zero relative offset present in the input).
+# CHECK: 10010000: 48 00 00 01 bl .+0
+# CHECK: 10010004: 60 00 00 00 nop
+# CHECK: 10010008: 4e 80 00 20 blr
diff --git a/test/ELF/pre_init_fini_array.s b/test/ELF/pre_init_fini_array.s
new file mode 100644
index 000000000000..bf32283d2579
--- /dev/null
+++ b/test/ELF/pre_init_fini_array.s
@@ -0,0 +1,140 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2
+// RUN: ld.lld %t2 -o %t2.so -shared
+// RUN: ld.lld %t %t2.so -o %t2
+// RUN: llvm-readobj -r -symbols -sections -dynamic-table %t2 | FileCheck %s
+// RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=DISASM %s
+// REQUIRES: x86
+
+.globl _start
+_start:
+ 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 .init_array,"aw",@init_array
+ .quad 0
+
+.section .preinit_array,"aw",@preinit_array
+ .quad 0
+ .byte 0
+
+.section .fini_array,"aw",@fini_array
+ .quad 0
+ .short 0
+
+// CHECK: Name: .init_array
+// CHECK-NEXT: Type: SHT_INIT_ARRAY
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: [[INIT_ADDR:.*]]
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: [[INIT_SIZE:.*]]
+
+
+// CHECK: Name: .preinit_array
+// CHECK-NEXT: Type: SHT_PREINIT_ARRAY
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: [[PREINIT_ADDR:.*]]
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: [[PREINIT_SIZE:.*]]
+
+
+// CHECK: Name: .fini_array
+// CHECK-NEXT: Type: SHT_FINI_ARRAY
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: [[FINI_ADDR:.*]]
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: [[FINI_SIZE:.*]]
+
+// CHECK: Relocations [
+// CHECK-NEXT: ]
+
+// CHECK: Name: __fini_array_end
+// CHECK-NEXT: Value: 0x1201B
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .fini_array
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: __fini_array_start
+// CHECK-NEXT: Value: [[FINI_ADDR]]
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .fini_array
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: __init_array_end
+// CHECK-NEXT: Value: 0x12008
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .init_array
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: __init_array_start
+// CHECK-NEXT: Value: [[INIT_ADDR]]
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .init_array
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: __preinit_array_end
+// CHECK-NEXT: Value: 0x12011
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .preinit_array
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: __preinit_array_start
+// CHECK-NEXT: Value: [[PREINIT_ADDR]]
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .preinit_array
+// CHECK-NEXT: }
+
+// CHECK: DynamicSection
+// CHECK: PREINIT_ARRAY [[PREINIT_ADDR]]
+// CHECK: PREINIT_ARRAYSZ [[PREINIT_SIZE]] (bytes)
+// CHECK: INIT_ARRAY [[INIT_ADDR]]
+// CHECK: INIT_ARRAYSZ [[INIT_SIZE]] (bytes)
+// CHECK: FINI_ARRAY [[FINI_ADDR]]
+// CHECK: FINI_ARRAYSZ [[FINI_SIZE]] (bytes)
+
+
+// 0x12008 - (0x11000 + 5) = 4099
+// 0x12011 - (0x11005 + 5) = 4103
+// 0x12000 - (0x1100a + 5) = 4081
+// 0x12008 - (0x1100f + 5) = 4084
+// 0x12011 - (0x11014 + 5) = 4088
+// 0x1201B - (0x11019 + 5) = 4093
+// DISASM: _start:
+// DISASM-NEXT: 11000: e8 {{.*}} callq 4099
+// DISASM-NEXT: 11005: e8 {{.*}} callq 4103
+// DISASM-NEXT: 1100a: e8 {{.*}} callq 4081
+// DISASM-NEXT: 1100f: e8 {{.*}} callq 4084
+// DISASM-NEXT: 11014: e8 {{.*}} callq 4088
+// DISASM-NEXT: 11019: e8 {{.*}} callq 4093
diff --git a/test/ELF/pre_init_fini_array_missing.s b/test/ELF/pre_init_fini_array_missing.s
new file mode 100644
index 000000000000..02b83240193e
--- /dev/null
+++ b/test/ELF/pre_init_fini_array_missing.s
@@ -0,0 +1,30 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: ld.lld %t -o %t2
+// RUN: llvm-objdump -d %t2 | FileCheck %s
+// REQUIRES: x86
+
+.globl _start
+_start:
+ call __preinit_array_start
+ call __preinit_array_end
+ call __init_array_start
+ call __init_array_end
+ call __fini_array_start
+ call __fini_array_end
+
+// With no .init_array section the symbols resolve to 0
+// 0 - (0x11000 + 5) = -69637
+// 0 - (0x11005 + 5) = -69642
+// 0 - (0x1100a + 5) = -69647
+// 0 - (0x1100f + 5) = -69652
+// 0 - (0x11014 + 5) = -69657
+// 0 - (0x11019 + 5) = -69662
+
+// CHECK: Disassembly of section .text:
+// CHECK-NEXT: _start:
+// CHECK-NEXT: 11000: e8 fb ef fe ff callq -69637
+// CHECK-NEXT: 11005: e8 f6 ef fe ff callq -69642
+// CHECK-NEXT: 1100a: e8 f1 ef fe ff callq -69647
+// CHECK-NEXT: 1100f: e8 ec ef fe ff callq -69652
+// CHECK-NEXT: 11014: e8 e7 ef fe ff callq -69657
+// CHECK-NEXT: 11019: e8 e2 ef fe ff callq -69662
diff --git a/test/ELF/progname.s b/test/ELF/progname.s
new file mode 100644
index 000000000000..5712b95d276d
--- /dev/null
+++ b/test/ELF/progname.s
@@ -0,0 +1,20 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
+// 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
+
+// CHECK: Name: __progname@
+// 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
+// CHECK-NEXT: }
+
+.global _start, __progname
+_start:
+__progname:
+ nop
diff --git a/test/ELF/program-header-layout.s b/test/ELF/program-header-layout.s
new file mode 100644
index 000000000000..8e32227ac741
--- /dev/null
+++ b/test/ELF/program-header-layout.s
@@ -0,0 +1,98 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %t2
+# RUN: llvm-readobj -sections -program-headers %t2 | FileCheck %s
+# REQUIRES: x86
+
+# Check that different output sections with the same flags are merged into a
+# single Read/Write PT_LOAD.
+
+.section .r,"a"
+.globl _start
+_start:
+.quad 0
+
+.section .a,"aw"
+.quad 1
+
+.section .b,"aw"
+.quad 2
+
+# CHECK: Name: .r
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC
+# CHECK-NEXT: ]
+# CHECK-NEXT: Address:
+# CHECK-NEXT: Offset: 0x158
+# CHECK-NEXT: Size:
+# CHECK-NEXT: Link:
+# CHECK-NEXT: Info:
+# CHECK-NEXT: AddressAlignment:
+# CHECK-NEXT: EntrySize:
+# CHECK-NEXT: }
+
+# 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
+# CHECK-NEXT: Offset: 0x0
+# CHECK-NEXT: VirtualAddress:
+# CHECK-NEXT: PhysicalAddress:
+# CHECK-NEXT: FileSize: 352
+# CHECK-NEXT: MemSize: 352
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment:
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: VirtualAddress:
+# CHECK-NEXT: PhysicalAddress:
+# CHECK-NEXT: FileSize: 0
+# CHECK-NEXT: MemSize: 0
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: PF_X
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment:
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_LOAD
+# CHECK-NEXT: Offset:
+# CHECK-NEXT: VirtualAddress:
+# CHECK-NEXT: PhysicalAddress:
+# CHECK-NEXT: FileSize: 16
+# CHECK-NEXT: MemSize: 16
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: PF_W
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment:
+# CHECK-NEXT: }
+# CHECK-NEXT: ProgramHeader {
+# CHECK-NEXT: Type: PT_GNU_STACK
+# CHECK-NEXT: Offset: 0x0
+# CHECK-NEXT: VirtualAddress: 0x0
+# CHECK-NEXT: PhysicalAddress: 0x0
+# CHECK-NEXT: FileSize: 0
+# CHECK-NEXT: MemSize: 0
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: PF_R
+# CHECK-NEXT: PF_W
+# CHECK-NEXT: ]
+# CHECK-NEXT: Alignment: 0
+# CHECK-NEXT: }
+# CHECK-NEXT: ]
diff --git a/test/ELF/relative-dynamic-reloc-ppc64.s b/test/ELF/relative-dynamic-reloc-ppc64.s
new file mode 100644
index 000000000000..b22b33f9f469
--- /dev/null
+++ b/test/ELF/relative-dynamic-reloc-ppc64.s
@@ -0,0 +1,66 @@
+// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
+// RUN: ld.lld -shared %t.o -o %t.so
+// RUN: llvm-readobj -t -r -dyn-symbols %t.so | FileCheck %s
+// REQUIRES: ppc
+
+// Test that we create R_PPC64_RELATIVE relocations but don't put any
+// symbols in the dynamic symbol table.
+
+// CHECK: Relocations [
+// 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: 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: }
+// CHECK-NEXT: ]
+
+// CHECK: Symbols [
+// CHECK: Name: foo
+// CHECK-NEXT: Value: 0x[[FOO_ADDR]]
+// CHECK: Name: bar
+// CHECK-NEXT: Value: 0x[[BAR_ADDR]]
+// CHECK: Name: zed
+// CHECK-NEXT: Value: 0x[[ZED_ADDR]]
+// CHECK: ]
+
+// 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: external@
+// 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: ]
+
+foo:
+ .quad foo
+
+ .hidden bar
+ .global bar
+bar:
+ .quad bar
+ .quad bar + 1
+
+ .hidden zed
+ .comm zed,1
+ .quad zed
+
+ .section abc,"a"
+ .quad foo
+
+ .quad external
diff --git a/test/ELF/relative-dynamic-reloc.s b/test/ELF/relative-dynamic-reloc.s
new file mode 100644
index 000000000000..41fcd8a6a556
--- /dev/null
+++ b/test/ELF/relative-dynamic-reloc.s
@@ -0,0 +1,69 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: ld.lld -shared %t.o -o %t.so
+// RUN: llvm-readobj -t -r -dyn-symbols %t.so | FileCheck %s
+
+// Test that we create R_X86_64_RELATIVE relocations but don't put any
+// symbols in the dynamic symbol table.
+
+// CHECK: Relocations [
+// 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: 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: }
+// CHECK-NEXT: ]
+
+// CHECK: Symbols [
+// CHECK: Name: foo
+// CHECK-NEXT: Value: 0x[[FOO_ADDR]]
+// CHECK: Name: bar
+// CHECK-NEXT: Value: 0x[[BAR_ADDR]]
+// CHECK: Name: zed
+// CHECK-NEXT: Value: 0x[[ZED_ADDR]]
+// CHECK: ]
+
+// 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: external@
+// 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: ]
+
+foo:
+ .quad foo
+
+ .hidden bar
+ .global bar
+bar:
+ .quad bar
+ .quad bar + 1
+
+ .hidden zed
+ .comm zed,1
+ .quad zed
+
+ .section abc,"a"
+ .quad foo
+
+ .quad external
+
+// This doesn't need a relocation.
+ callq localfunc@PLT
+localfunc:
diff --git a/test/ELF/relocatable.s b/test/ELF/relocatable.s
new file mode 100644
index 000000000000..9fb171d4ed50
--- /dev/null
+++ b/test/ELF/relocatable.s
@@ -0,0 +1,9 @@
+# REQUIRES: x86
+
+# 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
+
+# CHECK: -r option is not supported. Use 'ar' command instead.
+
+.globl _start;
+_start:
diff --git a/test/ELF/relocation-absolute.s b/test/ELF/relocation-absolute.s
new file mode 100644
index 000000000000..20d54eca9205
--- /dev/null
+++ b/test/ELF/relocation-absolute.s
@@ -0,0 +1,12 @@
+// 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: ld.lld %tabs %t -o %tout
+// RUN: llvm-objdump -d %tout | FileCheck %s
+// REQUIRES: x86
+
+.global _start
+_start:
+ movl $abs, %edx
+
+//CHECK: start:
+//CHECK-NEXT: movl $66, %edx
diff --git a/test/ELF/relocation-common.s b/test/ELF/relocation-common.s
new file mode 100644
index 000000000000..d5d379a355aa
--- /dev/null
+++ b/test/ELF/relocation-common.s
@@ -0,0 +1,14 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: ld.lld %t -o %tout
+// RUN: llvm-objdump -t -d %tout | FileCheck %s
+// REQUIRES: x86
+
+.global _start
+_start:
+ movl $1, sym1(%rip)
+
+.global sym1
+.comm sym1,4,4
+
+// CHECK: 11000: {{.*}} movl $1, 4086(%rip)
+// CHECK: 0000000000012000 g .bss 00000004 sym1
diff --git a/test/ELF/relocation-copy-align.s b/test/ELF/relocation-copy-align.s
new file mode 100644
index 000000000000..07ae6636e149
--- /dev/null
+++ b/test/ELF/relocation-copy-align.s
@@ -0,0 +1,31 @@
+// 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-align.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 -s -r --expand-relocs %t3 | FileCheck %s
+
+.global _start
+_start:
+movl $5, x
+
+// 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: 4
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment: 4
+// CHECK-NEXT: EntrySize:
+
+// CHECK: Relocation {
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Type: R_X86_64_COPY
+// CHECK-NEXT: Symbol: x
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
diff --git a/test/ELF/relocation-copy-i686.s b/test/ELF/relocation-copy-i686.s
new file mode 100644
index 000000000000..d61f84783cb6
--- /dev/null
+++ b/test/ELF/relocation-copy-i686.s
@@ -0,0 +1,63 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/relocation-copy.s -o %t2.o
+// RUN: ld.lld -shared %t2.o -o %t.so
+// RUN: ld.lld -e main %t.o %t.so -o %t3
+// RUN: llvm-readobj -s -r --expand-relocs %t3 | FileCheck %s
+// RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=CODE %s
+
+.text
+.globl main
+.align 16, 0x90
+.type main,@function
+main:
+movl $5, x
+movl $7, y
+movl $9, 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: 0x3000
+// CHECK-NEXT: Size: 24
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 16
+// CHECK-NEXT: EntrySize: 0
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rel.dyn {
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Type: R_386_COPY
+// CHECK-NEXT: Symbol: x
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Type: R_386_COPY
+// CHECK-NEXT: Symbol: y
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Type: R_386_COPY
+// CHECK-NEXT: Symbol: z
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+// 77824 = 0x13000
+// 16 is alignment here
+// 77840 = 0x13000 + 16
+// 77844 = 0x13000 + 16 + 4
+// CODE: Disassembly of section .text:
+// CODE-NEXT: main:
+// CODE-NEXT: 11000: c7 05 00 30 01 00 05 00 00 00 movl $5, 77824
+// CODE-NEXT: 1100a: c7 05 10 30 01 00 07 00 00 00 movl $7, 77840
+// CODE-NEXT: 11014: c7 05 14 30 01 00 09 00 00 00 movl $9, 77844
diff --git a/test/ELF/relocation-copy.s b/test/ELF/relocation-copy.s
new file mode 100644
index 000000000000..85cbf673910a
--- /dev/null
+++ b/test/ELF/relocation-copy.s
@@ -0,0 +1,63 @@
+// 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 -shared %t2.o -o %t.so
+// RUN: ld.lld -e main %t.o %t.so -o %t3
+// RUN: llvm-readobj -s -r --expand-relocs %t3 | FileCheck %s
+// RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=CODE %s
+
+.text
+.globl main
+.align 16, 0x90
+.type main,@function
+main:
+movl $5, x
+movl $7, y
+movl $9, z
+
+// CHECK: 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: 0x13000
+// CHECK-NEXT: Offset: 0x3000
+// CHECK-NEXT: Size: 24
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 16
+// CHECK-NEXT: EntrySize: 0
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Type: R_X86_64_COPY
+// CHECK-NEXT: Symbol: x
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Type: R_X86_64_COPY
+// CHECK-NEXT: Symbol: y
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: Relocation {
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Type: R_X86_64_COPY
+// CHECK-NEXT: Symbol: z
+// CHECK-NEXT: Addend: 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+// 77824 = 0x13000
+// 16 is alignment here
+// 77840 = 0x13000 + 16
+// 77844 = 0x13000 + 16 + 4
+// CODE: Disassembly of section .text:
+// CODE-NEXT: main:
+// CODE-NEXT: 11000: c7 04 25 00 30 01 00 05 00 00 00 movl $5, 77824
+// CODE-NEXT: 1100b: c7 04 25 10 30 01 00 07 00 00 00 movl $7, 77840
+// CODE-NEXT: 11016: c7 04 25 14 30 01 00 09 00 00 00 movl $9, 77844
diff --git a/test/ELF/relocation-i686.s b/test/ELF/relocation-i686.s
new file mode 100644
index 000000000000..f66cad20a074
--- /dev/null
+++ b/test/ELF/relocation-i686.s
@@ -0,0 +1,84 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t
+// 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 %t2.so -o %t2
+// RUN: llvm-readobj -s %t2 | FileCheck --check-prefix=ADDR %s
+// RUN: llvm-objdump -d %t2 | FileCheck %s
+// REQUIRES: x86
+
+.global _start
+_start:
+
+.section .R_386_32,"ax",@progbits
+.global R_386_32
+R_386_32:
+ movl $R_386_32 + 1, %edx
+
+
+.section .R_386_PC32,"ax",@progbits,unique,1
+.global R_386_PC32
+R_386_PC32:
+ call R_386_PC32_2
+
+.section .R_386_PC32,"ax",@progbits,unique,2
+.zero 4
+R_386_PC32_2:
+ nop
+
+// CHECK: Disassembly of section .R_386_32:
+// CHECK-NEXT: R_386_32:
+// CHECK-NEXT: 11000: {{.*}} movl $69633, %edx
+
+// CHECK: Disassembly of section .R_386_PC32:
+// CHECK-NEXT: R_386_PC32:
+// CHECK-NEXT: 11005: e8 04 00 00 00 calll 4
+
+// CHECK: R_386_PC32_2:
+// CHECK-NEXT: 1100e: 90 nop
+
+// Create a .got
+movl bar@GOT, %eax
+
+// ADDR: Name: .plt
+// ADDR-NEXT: Type: SHT_PROGBITS
+// ADDR-NEXT: Flags [
+// ADDR-NEXT: SHF_ALLOC
+// ADDR-NEXT: SHF_EXECINSTR
+// ADDR-NEXT: ]
+// ADDR-NEXT: Address: 0x11030
+// ADDR-NEXT: Offset: 0x1030
+// ADDR-NEXT: Size: 32
+
+// ADDR: Name: .got
+// ADDR-NEXT: Type: SHT_PROGBITS
+// ADDR-NEXT: Flags [
+// ADDR-NEXT: SHF_ALLOC
+// ADDR-NEXT: SHF_WRITE
+// ADDR-NEXT: ]
+// ADDR-NEXT: Address: 0x12070
+
+.section .R_386_GOTPC,"ax",@progbits
+R_386_GOTPC:
+ movl $_GLOBAL_OFFSET_TABLE_, %eax
+
+// 0x12050 - 0x11014 = 4156
+
+// CHECK: Disassembly of section .R_386_GOTPC:
+// CHECK-NEXT: R_386_GOTPC:
+// CHECK-NEXT: 11014: {{.*}} movl $4188, %eax
+
+.section .dynamic_reloc, "ax",@progbits
+ call bar
+// 0x11030 - (0x11019 + 5) = 18
+// CHECK: Disassembly of section .dynamic_reloc:
+// CHECK-NEXT: .dynamic_reloc:
+// CHECK-NEXT: 11019: e8 22 00 00 00 calll 34
+
+.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.
+// CHECK: Disassembly of section .R_386_GOT32:
+// CHECK-NEXT: R_386_GOT32:
+// CHECK-NEXT: 1101e: {{.*}} movl 4, %eax
diff --git a/test/ELF/relocation-in-merge.s b/test/ELF/relocation-in-merge.s
new file mode 100644
index 000000000000..820208a2cafe
--- /dev/null
+++ b/test/ELF/relocation-in-merge.s
@@ -0,0 +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
+
+ .section .foo,"aM",@progbits,4
+ .long bar
diff --git a/test/ELF/relocation-local.s b/test/ELF/relocation-local.s
new file mode 100644
index 000000000000..26e89fc12f8d
--- /dev/null
+++ b/test/ELF/relocation-local.s
@@ -0,0 +1,38 @@
+// Test that relocation of local symbols is working.
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: ld.lld %t -o %t2
+// RUN: llvm-objdump -s -d %t2 | FileCheck %s
+// REQUIRES: x86
+
+
+.global _start
+_start:
+ call lulz
+
+.zero 4
+lulz:
+
+.section .text2,"ax",@progbits
+R_X86_64_32:
+ movl $R_X86_64_32, %edx
+
+// FIXME: this would be far more self evident if llvm-objdump printed
+// constants in hex.
+// CHECK: Disassembly of section .text2:
+// CHECK-NEXT: R_X86_64_32:
+// CHECK-NEXT: 11009: {{.*}} movl $69641, %edx
+
+.section .R_X86_64_32S,"ax",@progbits
+R_X86_64_32S:
+ movq lulz - 0x100000, %rdx
+
+// CHECK: Disassembly of section .R_X86_64_32S:
+// CHECK-NEXT: R_X86_64_32S:
+// CHECK-NEXT: {{.*}}: {{.*}} movq -978935, %rdx
+
+.section .R_X86_64_64,"a",@progbits
+R_X86_64_64:
+ .quad R_X86_64_64
+
+// CHECK: Contents of section .R_X86_64_64:
+// CHECK-NEXT: 10120 20010100 00000000
diff --git a/test/ELF/relocation-past-merge-end.s b/test/ELF/relocation-past-merge-end.s
new file mode 100644
index 000000000000..4dadea1e7acd
--- /dev/null
+++ b/test/ELF/relocation-past-merge-end.s
@@ -0,0 +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.so -shared 2>&1 | FileCheck %s
+// CHECK: Entry is past the end of the section
+
+ .long .foo + 1
+ .section .foo,"aM",@progbits,4
diff --git a/test/ELF/relocation-size-shared.s b/test/ELF/relocation-size-shared.s
new file mode 100644
index 000000000000..1b52e77b7d5f
--- /dev/null
+++ b/test/ELF/relocation-size-shared.s
@@ -0,0 +1,78 @@
+// 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/relocation-size-shared.s -o %tso.o
+// RUN: ld.lld -shared %tso.o -o %tso
+// RUN: ld.lld %t.o %tso -o %t1
+// RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=RELOCSHARED %s
+// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
+
+// 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: }
+// RELOCSHARED-NEXT:]
+
+// DISASM: Disassembly of section .text:
+// 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: _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
+
+.data
+.global foo
+.type foo,%object
+.size foo,26
+foo:
+.zero 26
+
+.text
+_data:
+ // R_X86_64_SIZE64:
+ .quad foo@SIZE-1
+ .quad foo@SIZE
+ .quad foo@SIZE+1
+ .quad fooshared@SIZE-1
+ .quad fooshared@SIZE
+ .quad fooshared@SIZE+1
+
+.globl _start
+_start:
+ // R_X86_64_SIZE32:
+ movl foo@SIZE-1,%eax
+ movl foo@SIZE,%eax
+ movl foo@SIZE+1,%eax
+ movl fooshared@SIZE-1,%eax
+ movl fooshared@SIZE,%eax
+ movl fooshared@SIZE+1,%eax
diff --git a/test/ELF/relocation-size.s b/test/ELF/relocation-size.s
new file mode 100644
index 000000000000..aea3dafea071
--- /dev/null
+++ b/test/ELF/relocation-size.s
@@ -0,0 +1,123 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t1
+// RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=NORELOC %s
+// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
+// RUN: ld.lld -shared %t.o -o %t1
+// RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=RELOCSHARED %s
+// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASMSHARED %s
+
+// NORELOC: Relocations [
+// NORELOC-NEXT: ]
+
+// DISASM: Disassembly of section .text:
+// 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: _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
+
+// 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: }
+// RELOCSHARED-NEXT: ]
+
+// DISASMSHARED: Disassembly of section .text:
+// 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: _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
+
+.data
+.global foo
+.type foo,%object
+.size foo,26
+foo:
+.zero 26
+
+.data
+.global foohidden
+.hidden foohidden
+.type foohidden,%object
+.size foohidden,26
+foohidden:
+.zero 26
+
+.text
+_data:
+ // R_X86_64_SIZE64:
+ .quad foo@SIZE-1
+ .quad foo@SIZE
+ .quad foo@SIZE+1
+ .quad foohidden@SIZE-1
+ .quad foohidden@SIZE
+ .quad foohidden@SIZE+1
+.globl _start
+_start:
+ // R_X86_64_SIZE32:
+ movl foo@SIZE-1,%eax
+ movl foo@SIZE,%eax
+ movl foo@SIZE+1,%eax
+ movl foohidden@SIZE-1,%eax
+ movl foohidden@SIZE,%eax
+ movl foohidden@SIZE+1,%eax
diff --git a/test/ELF/relocation-undefined-weak.s b/test/ELF/relocation-undefined-weak.s
new file mode 100644
index 000000000000..f1cb706329a4
--- /dev/null
+++ b/test/ELF/relocation-undefined-weak.s
@@ -0,0 +1,27 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: ld.lld %t -o %tout
+// RUN: llvm-readobj -sections %tout | FileCheck %s
+// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix DISASM
+// REQUIRES: x86
+
+// Check that undefined weak symbols are treated as having a VA of 0.
+
+.global _start
+_start:
+ movl $1, sym1(%rip)
+
+.weak sym1
+
+// 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
+
+// Unfortunately FileCheck can't do math, so we have to check for explicit
+// values:
+// R_86_64_PC32 = 0 + (-8 - (0x11000 + 2)) = -69642
+
+// DISASM: movl $1, -69642(%rip)
diff --git a/test/ELF/relocation.s b/test/ELF/relocation.s
new file mode 100644
index 000000000000..a6dd1d1ef5d6
--- /dev/null
+++ b/test/ELF/relocation.s
@@ -0,0 +1,117 @@
+// 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/shared.s -o %t2
+// RUN: ld.lld %t2 -o %t2.so -shared
+// RUN: ld.lld %t %t2.so -o %t3
+// RUN: llvm-readobj -s %t3 | FileCheck --check-prefix=SEC %s
+// RUN: llvm-objdump -s -d %t3 | FileCheck %s
+// REQUIRES: x86
+
+// SEC: Name: .plt
+// SEC-NEXT: Type: SHT_PROGBITS
+// SEC-NEXT: Flags [
+// SEC-NEXT: SHF_ALLOC
+// SEC-NEXT: SHF_EXECINSTR
+// SEC-NEXT: ]
+// SEC-NEXT: Address: 0x11030
+// SEC-NEXT: Offset: 0x1030
+// SEC-NEXT: Size: 32
+
+// SEC: Name: .got
+// SEC-NEXT: Type: SHT_PROGBITS
+// SEC-NEXT: Flags [
+// SEC-NEXT: SHF_ALLOC
+// SEC-NEXT: SHF_WRITE
+// SEC-NEXT: ]
+// SEC-NEXT: Address: 0x120E0
+// SEC-NEXT: Offset:
+// SEC-NEXT: Size: 8
+// SEC-NEXT: Link: 0
+// SEC-NEXT: Info: 0
+// SEC-NEXT: AddressAlignment: 8
+// SEC-NEXT: EntrySize: 0
+// SEC-NEXT: }
+
+// SEC: Name: .got.plt
+// SEC-NEXT: Type: SHT_PROGBITS
+// SEC-NEXT: Flags [
+// SEC-NEXT: SHF_ALLOC
+// SEC-NEXT: SHF_WRITE
+// SEC-NEXT: ]
+// SEC-NEXT: Address: 0x13000
+// SEC-NEXT: Offset: 0x3000
+// SEC-NEXT: Size: 32
+// SEC-NEXT: Link: 0
+// SEC-NEXT: Info: 0
+// SEC-NEXT: AddressAlignment: 8
+// SEC-NEXT: EntrySize: 0
+// SEC-NEXT: }
+
+.section .text,"ax",@progbits,unique,1
+.global _start
+_start:
+ call lulz
+
+.section .text,"ax",@progbits,unique,2
+.zero 4
+.global lulz
+lulz:
+ nop
+
+// CHECK: Disassembly of section .text:
+// CHECK-NEXT: _start:
+// CHECK-NEXT: 11000: e8 04 00 00 00 callq 4
+// CHECK-NEXT: 11005:
+
+// CHECK: lulz:
+// CHECK-NEXT: 11009: 90 nop
+
+
+.section .text2,"ax",@progbits
+.global R_X86_64_32
+R_X86_64_32:
+ movl $R_X86_64_32, %edx
+
+// FIXME: this would be far more self evident if llvm-objdump printed
+// constants in hex.
+// CHECK: Disassembly of section .text2:
+// CHECK-NEXT: R_X86_64_32:
+// CHECK-NEXT: 1100a: {{.*}} movl $69642, %edx
+
+.section .R_X86_64_32S,"ax",@progbits
+.global R_X86_64_32S
+R_X86_64_32S:
+ movq lulz - 0x100000, %rdx
+
+// CHECK: Disassembly of section .R_X86_64_32S:
+// CHECK-NEXT: R_X86_64_32S:
+// CHECK-NEXT: {{.*}}: {{.*}} movq -978935, %rdx
+
+.section .R_X86_64_PC32,"ax",@progbits
+.global R_X86_64_PC32
+R_X86_64_PC32:
+ call bar
+ movl $bar, %eax
+//16 is a size of PLT[0]
+// 0x11030 + 16 - (0x11017 + 5) = 20
+// CHECK: Disassembly of section .R_X86_64_PC32:
+// CHECK-NEXT: R_X86_64_PC32:
+// CHECK-NEXT: 11017: {{.*}} callq 36
+// CHECK-NEXT: 1101c: {{.*}} movl $69696, %eax
+
+.section .R_X86_64_64,"a",@progbits
+.global R_X86_64_64
+R_X86_64_64:
+ .quad R_X86_64_64
+
+// CHECK: Contents of section .R_X86_64_64:
+// CHECK-NEXT: 101c8 c8010100 00000000
+
+.section .R_X86_64_GOTPCREL,"a",@progbits
+.global R_X86_64_GOTPCREL
+R_X86_64_GOTPCREL:
+ .long zed@gotpcrel
+
+// 0x120E8 - 0x101D8 = 7952
+// 7952 = 0x101f0000 in little endian
+// CHECK: Contents of section .R_X86_64_GOTPCREL
+// CHECK-NEXT: 101d0 101f0000
diff --git a/test/ELF/relro.s b/test/ELF/relro.s
new file mode 100644
index 000000000000..7a225a269075
--- /dev/null
+++ b/test/ELF/relro.s
@@ -0,0 +1,242 @@
+// 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: ld.lld -shared %t2.o -o %t2.so
+// RUN: ld.lld %t.o %t2.so -z now -z relro -o %t
+// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data %t | FileCheck --check-prefix=FULLRELRO %s
+// RUN: ld.lld %t.o %t2.so -z relro -o %t
+// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data %t | FileCheck --check-prefix=PARTRELRO %s
+// RUN: ld.lld %t.o %t2.so -z norelro -o %t
+// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data %t | FileCheck --check-prefix=NORELRO %s
+// REQUIRES: x86
+
+// FULLRELRO: Section {
+// FULLRELRO: Index: 9
+// FULLRELRO-NEXT: Name: .got
+// FULLRELRO-NEXT: Type: SHT_PROGBITS
+// FULLRELRO-NEXT: Flags [
+// FULLRELRO-NEXT: SHF_ALLOC
+// FULLRELRO-NEXT: SHF_WRITE
+// FULLRELRO-NEXT: ]
+// FULLRELRO-NEXT: Address: 0x12100
+// FULLRELRO-NEXT: Offset: 0x2100
+// FULLRELRO-NEXT: Size: 8
+// FULLRELRO-NEXT: Link: 0
+// FULLRELRO-NEXT: Info: 0
+// FULLRELRO-NEXT: AddressAlignment: 8
+// FULLRELRO-NEXT: EntrySize: 0
+// FULLRELRO-NEXT: SectionData (
+// FULLRELRO-NEXT: 0000: 00000000 00000000
+// FULLRELRO-NEXT: )
+// FULLRELRO-NEXT: }
+// FULLRELRO-NEXT: Section {
+// FULLRELRO-NEXT: Index: 10
+// FULLRELRO-NEXT: Name: .got.plt
+// FULLRELRO-NEXT: Type: SHT_PROGBITS
+// FULLRELRO-NEXT: Flags [
+// FULLRELRO-NEXT: SHF_ALLOC
+// FULLRELRO-NEXT: SHF_WRITE
+// FULLRELRO-NEXT: ]
+// FULLRELRO-NEXT: Address: 0x12108
+// FULLRELRO-NEXT: Offset: 0x2108
+// FULLRELRO-NEXT: Size: 32
+// FULLRELRO-NEXT: Link: 0
+// FULLRELRO-NEXT: Info: 0
+// FULLRELRO-NEXT: AddressAlignment: 8
+// FULLRELRO-NEXT: EntrySize: 0
+// FULLRELRO-NEXT: SectionData (
+// FULLRELRO-NEXT: 0000:
+// FULLRELRO-NEXT: 0010:
+// FULLRELRO-NEXT: )
+// FULLRELRO-NEXT: }
+// FULLRELRO-NEXT: Section {
+// FULLRELRO-NEXT: Index: 11
+// FULLRELRO-NEXT: Name: .data
+// FULLRELRO-NEXT: Type: SHT_PROGBITS
+// FULLRELRO-NEXT: Flags [
+// FULLRELRO-NEXT: SHF_ALLOC
+// FULLRELRO-NEXT: SHF_WRITE
+// FULLRELRO-NEXT: ]
+// FULLRELRO-NEXT: Address: 0x13000
+// FULLRELRO-NEXT: Offset: 0x3000
+// FULLRELRO-NEXT: Size: 12
+// FULLRELRO-NEXT: Link: 0
+// FULLRELRO-NEXT: Info: 0
+// FULLRELRO-NEXT: AddressAlignment:
+// FULLRELRO-NEXT: EntrySize: 0
+// FULLRELRO-NEXT: SectionData (
+// FULLRELRO-NEXT: 0000:
+// FULLRELRO-NEXT: )
+// FULLRELRO-NEXT: }
+// FULLRELRO-NEXT: Section {
+// FULLRELRO-NEXT: Index: 12
+// FULLRELRO-NEXT: Name: .foo
+// FULLRELRO-NEXT: Type: SHT_PROGBITS
+// FULLRELRO-NEXT: Flags [
+// FULLRELRO-NEXT: SHF_ALLOC
+// FULLRELRO-NEXT: SHF_WRITE
+// FULLRELRO-NEXT: ]
+// FULLRELRO-NEXT: Address: 0x1300C
+// FULLRELRO-NEXT: Offset: 0x300C
+// FULLRELRO-NEXT: Size: 0
+// FULLRELRO-NEXT: Link: 0
+// FULLRELRO-NEXT: Info: 0
+// FULLRELRO-NEXT: AddressAlignment:
+// FULLRELRO-NEXT: EntrySize: 0
+// FULLRELRO-NEXT: SectionData (
+// FULLRELRO-NEXT: )
+// FULLRELRO-NEXT: }
+// 308 - sizeof(.data)(12) = 296
+// FULLRELRO: ProgramHeaders [
+// FULLRELRO: Type: PT_LOAD
+// FULLRELRO: Offset: 0x2000
+// FULLRELRO-NEXT: VirtualAddress: [[RWADDR:.*]]
+// FULLRELRO-NEXT: PhysicalAddress:
+// FULLRELRO-NEXT: FileSize: 4108
+// FULLRELRO-NEXT: MemSize: 4108
+// FULLRELRO-NEXT: Flags [
+// FULLRELRO-NEXT: PF_R
+// FULLRELRO-NEXT: PF_W
+// FULLRELRO-NEXT: ]
+// FULLRELRO-NEXT: Alignment: 4096
+// FULLRELRO-NEXT:}
+// FULLRELRO: Type: PT_GNU_RELRO
+// FULLRELRO-NEXT: Offset: 0x
+// FULLRELRO-NEXT: VirtualAddress: [[RWADDR]]
+// FULLRELRO-NEXT: PhysicalAddress:
+// FULLRELRO-NEXT: FileSize: 296
+// FULLRELRO-NEXT: MemSize: 296
+// FULLRELRO-NEXT: Flags [
+// FULLRELRO-NEXT: PF_R
+// FULLRELRO-NEXT: ]
+// FULLRELRO-NEXT: Alignment: 1
+// FULLRELRO-NEXT:}
+
+// PARTRELRO: Section {
+// PARTRELRO: Index: 9
+// PARTRELRO-NEXT: Name: .got
+// PARTRELRO-NEXT: Type: SHT_PROGBITS
+// PARTRELRO-NEXT: Flags [
+// PARTRELRO-NEXT: SHF_ALLOC
+// PARTRELRO-NEXT: SHF_WRITE
+// PARTRELRO-NEXT: ]
+// PARTRELRO-NEXT: Address: 0x120E0
+// PARTRELRO-NEXT: Offset: 0x20E0
+// PARTRELRO-NEXT: Size: 8
+// PARTRELRO-NEXT: Link: 0
+// PARTRELRO-NEXT: Info: 0
+// PARTRELRO-NEXT: AddressAlignment: 8
+// PARTRELRO-NEXT: EntrySize: 0
+// PARTRELRO-NEXT: SectionData (
+// PARTRELRO-NEXT: 0000:
+// PARTRELRO-NEXT: )
+// PARTRELRO-NEXT: }
+// PARTRELRO-NEXT: Section {
+// PARTRELRO-NEXT: Index: 10
+// PARTRELRO-NEXT: Name: .data
+// PARTRELRO-NEXT: Type: SHT_PROGBITS
+// PARTRELRO-NEXT: Flags [
+// PARTRELRO-NEXT: SHF_ALLOC
+// PARTRELRO-NEXT: SHF_WRITE
+// PARTRELRO-NEXT: ]
+// PARTRELRO-NEXT: Address: 0x13000
+// PARTRELRO-NEXT: Offset: 0x3000
+// PARTRELRO-NEXT: Size: 12
+// PARTRELRO-NEXT: Link: 0
+// PARTRELRO-NEXT: Info: 0
+// PARTRELRO-NEXT: AddressAlignment: 1
+// PARTRELRO-NEXT: EntrySize: 0
+// PARTRELRO-NEXT: SectionData (
+// PARTRELRO-NEXT: 0000:
+// PARTRELRO-NEXT: )
+// PARTRELRO-NEXT: }
+// PARTRELRO-NEXT: Section {
+// PARTRELRO-NEXT: Index: 11
+// PARTRELRO-NEXT: Name: .foo
+// PARTRELRO-NEXT: Type: SHT_PROGBITS
+// PARTRELRO-NEXT: Flags [
+// PARTRELRO-NEXT: SHF_ALLOC
+// PARTRELRO-NEXT: SHF_WRITE
+// PARTRELRO-NEXT: ]
+// PARTRELRO-NEXT: Address: 0x1300C
+// PARTRELRO-NEXT: Offset: 0x300C
+// PARTRELRO-NEXT: Size: 0
+// PARTRELRO-NEXT: Link: 0
+// PARTRELRO-NEXT: Info: 0
+// PARTRELRO-NEXT: AddressAlignment: 1
+// PARTRELRO-NEXT: EntrySize: 0
+// PARTRELRO-NEXT: SectionData (
+// PARTRELRO-NEXT: )
+// PARTRELRO-NEXT: }
+// PARTRELRO-NEXT: Section {
+// PARTRELRO-NEXT: Index: 12
+// PARTRELRO-NEXT: Name: .got.plt
+// PARTRELRO-NEXT: Type: SHT_PROGBITS
+// PARTRELRO-NEXT: Flags [
+// PARTRELRO-NEXT: SHF_ALLOC
+// PARTRELRO-NEXT: SHF_WRITE
+// PARTRELRO-NEXT: ]
+// PARTRELRO-NEXT: Address: 0x13010
+// PARTRELRO-NEXT: Offset: 0x3010
+// PARTRELRO-NEXT: Size: 32
+// PARTRELRO-NEXT: Link: 0
+// PARTRELRO-NEXT: Info: 0
+// PARTRELRO-NEXT: AddressAlignment: 8
+// PARTRELRO-NEXT: EntrySize: 0
+// PARTRELRO-NEXT: SectionData (
+// PARTRELRO-NEXT: 0000:
+// PARTRELRO-NEXT: 0010:
+// PARTRELRO-NEXT: )
+// PARTRELRO-NEXT: }
+// PARTRELRO-NEXT: Section {
+// PARTRELRO-NEXT: Index: 13
+// PARTRELRO-NEXT: Name: .bss
+// PARTRELRO-NEXT: Type: SHT_NOBITS
+// PARTRELRO-NEXT: Flags [
+// PARTRELRO-NEXT: SHF_ALLOC
+// PARTRELRO-NEXT: SHF_WRITE
+// PARTRELRO-NEXT: ]
+// PARTRELRO-NEXT: Address: 0x13030
+// PARTRELRO-NEXT: Offset: 0x3030
+// PARTRELRO-NEXT: Size: 0
+// PARTRELRO-NEXT: Link: 0
+// PARTRELRO-NEXT: Info: 0
+// PARTRELRO-NEXT: AddressAlignment: 1
+// PARTRELRO-NEXT: EntrySize: 0
+// PARTRELRO-NEXT: }
+// PARTRELRO: ProgramHeader {
+// PARTRELRO: Type: PT_LOAD
+// PARTRELRO: Offset: 0x2000
+// PARTRELRO-NEXT: VirtualAddress: [[RWADDR:.*]]
+// PARTRELRO-NEXT: PhysicalAddress:
+// PARTRELRO-NEXT: FileSize: 4144
+// PARTRELRO-NEXT: MemSize: 4144
+// PARTRELRO-NEXT: Flags [
+// PARTRELRO-NEXT: PF_R (0x4)
+// PARTRELRO-NEXT: PF_W (0x2)
+// PARTRELRO-NEXT: ]
+// PARTRELRO-NEXT: Alignment: 4096
+// PARTRELRO: Type: PT_GNU_RELRO
+// PARTRELRO-NEXT: Offset: 0x2000
+// PARTRELRO-NEXT: VirtualAddress: [[RWADDR]]
+// PARTRELRO-NEXT: PhysicalAddress:
+// PARTRELRO-NEXT: FileSize: 232
+// PARTRELRO-NEXT: MemSize: 232
+// PARTRELRO-NEXT: Flags [
+// PARTRELRO-NEXT: PF_R
+// PARTRELRO-NEXT: ]
+// PARTRELRO-NEXT: Alignment: 1
+
+// NORELRO: ProgramHeaders [
+// NORELRO-NOT: PT_GNU_RELRO
+
+.global _start
+_start:
+ .long bar
+ jmp *bar@GOTPCREL(%rip)
+
+.section .data,"aw"
+.quad 0
+
+.zero 4
+.section .foo,"aw"
+.section .bss,"",@nobits
diff --git a/test/ELF/resolution.s b/test/ELF/resolution.s
new file mode 100644
index 000000000000..ce275c2934a4
--- /dev/null
+++ b/test/ELF/resolution.s
@@ -0,0 +1,430 @@
+// 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/resolution.s -o %t2
+// RUN: ld.lld -discard-all %t %t2 -o %t3
+// RUN: llvm-readobj -t %t3 | FileCheck %s
+// REQUIRES: x86
+
+// This is an exhaustive test for checking which symbol is kept when two
+// have the same name. Each symbol has a different size which is used
+// to see which one was chosen.
+
+// 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: _start
+// 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: Symbol {
+// CHECK-NEXT: Name: CommonStrong_with_CommonStrong
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 63
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section:
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: CommonStrong_with_CommonWeak
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 30
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section:
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: CommonStrong_with_RegularStrong
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 55
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: CommonStrong_with_RegularWeak
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 22
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section:
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: CommonStrong_with_UndefStrong
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 27
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section:
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: CommonStrong_with_UndefWeak
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 26
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section:
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: CommonWeak_with_CommonStrong
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 61
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section:
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: CommonWeak_with_CommonWeak
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 28
+// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section:
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: CommonWeak_with_RegularStrong
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 53
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: CommonWeak_with_RegularWeak
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 20
+// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section:
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: CommonWeak_with_UndefStrong
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 25
+// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section:
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: CommonWeak_with_UndefWeak
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 24
+// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section:
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: RegularStrong_with_CommonStrong
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 10
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: RegularStrong_with_CommonWeak
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 9
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: RegularStrong_with_RegularWeak
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 2
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: RegularStrong_with_UndefStrong
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 6
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: RegularStrong_with_UndefWeak
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 5
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: RegularWeak_with_CommonStrong
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 40
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section:
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: RegularWeak_with_CommonWeak
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 7
+// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: RegularWeak_with_RegularStrong
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 33
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: RegularWeak_with_RegularWeak
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: RegularWeak_with_UndefStrong
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: RegularWeak_with_UndefWeak
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 3
+// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: UndefStrong_with_CommonStrong
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 51
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section:
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: UndefStrong_with_CommonWeak
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 50
+// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section:
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: UndefStrong_with_RegularStrong
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 46
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: UndefStrong_with_RegularWeak
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 45
+// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: UndefWeak_with_CommonStrong
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 49
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section:
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: UndefWeak_with_CommonWeak
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 48
+// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section:
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: UndefWeak_with_RegularStrong
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 44
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: UndefWeak_with_RegularWeak
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 43
+// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: UndefWeak_with_UndefWeak
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 15
+// CHECK-NEXT: Binding: Weak
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+.globl _start
+_start:
+ nop
+
+local:
+
+.weak RegularWeak_with_RegularWeak
+.size RegularWeak_with_RegularWeak, 0
+RegularWeak_with_RegularWeak:
+
+.weak RegularWeak_with_RegularStrong
+.size RegularWeak_with_RegularStrong, 1
+RegularWeak_with_RegularStrong:
+
+.global RegularStrong_with_RegularWeak
+.size RegularStrong_with_RegularWeak, 2
+RegularStrong_with_RegularWeak:
+
+.weak RegularWeak_with_UndefWeak
+.size RegularWeak_with_UndefWeak, 3
+RegularWeak_with_UndefWeak:
+
+.weak RegularWeak_with_UndefStrong
+.size RegularWeak_with_UndefStrong, 4
+RegularWeak_with_UndefStrong:
+
+.global RegularStrong_with_UndefWeak
+.size RegularStrong_with_UndefWeak, 5
+RegularStrong_with_UndefWeak:
+
+.global RegularStrong_with_UndefStrong
+.size RegularStrong_with_UndefStrong, 6
+RegularStrong_with_UndefStrong:
+
+.weak RegularWeak_with_CommonWeak
+.size RegularWeak_with_CommonWeak, 7
+RegularWeak_with_CommonWeak:
+
+.weak RegularWeak_with_CommonStrong
+.size RegularWeak_with_CommonStrong, 8
+RegularWeak_with_CommonStrong:
+
+.global RegularStrong_with_CommonWeak
+.size RegularStrong_with_CommonWeak, 9
+RegularStrong_with_CommonWeak:
+
+.global RegularStrong_with_CommonStrong
+.size RegularStrong_with_CommonStrong, 10
+RegularStrong_with_CommonStrong:
+
+.weak UndefWeak_with_RegularWeak
+.size UndefWeak_with_RegularWeak, 11
+.quad UndefWeak_with_RegularWeak
+
+.weak UndefWeak_with_RegularStrong
+.size UndefWeak_with_RegularStrong, 12
+.quad UndefWeak_with_RegularStrong
+
+.size UndefStrong_with_RegularWeak, 13
+.quad UndefStrong_with_RegularWeak
+
+.size UndefStrong_with_RegularStrong, 14
+.quad UndefStrong_with_RegularStrong
+
+.weak UndefWeak_with_UndefWeak
+.size UndefWeak_with_UndefWeak, 15
+.quad UndefWeak_with_UndefWeak
+
+.weak UndefWeak_with_CommonWeak
+.size UndefWeak_with_CommonWeak, 16
+.quad UndefWeak_with_CommonWeak
+
+.weak UndefWeak_with_CommonStrong
+.size UndefWeak_with_CommonStrong, 17
+.quad UndefWeak_with_CommonStrong
+
+.size UndefStrong_with_CommonWeak, 18
+.quad UndefStrong_with_CommonWeak
+
+.size UndefStrong_with_CommonStrong, 19
+.quad UndefStrong_with_CommonStrong
+
+.weak CommonWeak_with_RegularWeak
+.comm CommonWeak_with_RegularWeak,20,4
+
+.weak CommonWeak_with_RegularStrong
+.comm CommonWeak_with_RegularStrong,21,4
+
+.comm CommonStrong_with_RegularWeak,22,4
+
+.comm CommonStrong_with_RegularStrong,23,4
+
+.weak CommonWeak_with_UndefWeak
+.comm CommonWeak_with_UndefWeak,24,4
+
+.weak CommonWeak_with_UndefStrong
+.comm CommonWeak_with_UndefStrong,25,4
+
+.comm CommonStrong_with_UndefWeak,26,4
+
+.comm CommonStrong_with_UndefStrong,27,4
+
+.weak CommonWeak_with_CommonWeak
+.comm CommonWeak_with_CommonWeak,28,4
+
+.weak CommonWeak_with_CommonStrong
+.comm CommonWeak_with_CommonStrong,29,4
+
+.comm CommonStrong_with_CommonWeak,30,4
+
+.comm CommonStrong_with_CommonStrong,31,4
diff --git a/test/ELF/section-align-0.test b/test/ELF/section-align-0.test
new file mode 100644
index 000000000000..fc27ee95fd4b
--- /dev/null
+++ b/test/ELF/section-align-0.test
@@ -0,0 +1,19 @@
+# RUN: yaml2obj -format elf %s -o %t
+# RUN: ld.lld %t -o %tout
+
+# Verify that lld can handle sections with an alignment of zero.
+
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .text
+ Type: SHT_PROGBITS
+ AddressAlign: 0
+
+Symbols:
+ Global:
+ - Name: _start
+ Section: .text
diff --git a/test/ELF/section-layout.s b/test/ELF/section-layout.s
new file mode 100644
index 000000000000..20480919956c
--- /dev/null
+++ b/test/ELF/section-layout.s
@@ -0,0 +1,54 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %tout
+# RUN: llvm-readobj -sections %tout | FileCheck %s
+# REQUIRES: x86
+
+# Check that sections are laid out in the correct order.
+
+.global _start
+.text
+_start:
+
+.section t,"x",@nobits
+.section s,"x"
+.section r,"w",@nobits
+.section q,"w"
+.section p,"wx",@nobits
+.section o,"wx"
+.section n,"",@nobits
+.section m,""
+
+.section l,"awx",@nobits
+.section k,"awx"
+.section j,"aw",@nobits
+.section i,"aw"
+.section g,"awT",@nobits
+.section e,"awT"
+.section d,"ax",@nobits
+.section c,"ax"
+.section b,"a",@nobits
+.section a,"a"
+
+// CHECK: Name: a
+// CHECK: Name: b
+// CHECK: Name: c
+// CHECK: Name: d
+
+// TLS sections are only sorted on NOBITS.
+// CHECK: Name: e
+// CHECK: Name: g
+
+// CHECK: Name: i
+// CHECK: Name: j
+// CHECK: Name: k
+// CHECK: Name: l
+
+// Non allocated sections are in input order.
+// CHECK: Name: t
+// CHECK: Name: s
+// CHECK: Name: r
+// CHECK: Name: q
+// CHECK: Name: p
+// CHECK: Name: o
+// CHECK: Name: n
+// CHECK: Name: m
diff --git a/test/ELF/section-name.s b/test/ELF/section-name.s
new file mode 100644
index 000000000000..2d7ed4e63717
--- /dev/null
+++ b/test/ELF/section-name.s
@@ -0,0 +1,37 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+# RUN: ld.lld %t -o %tout
+# RUN: llvm-readobj -sections %tout | FileCheck %s
+# REQUIRES: x86
+
+.global _start
+.text
+_start:
+
+.section .text.a,"ax"
+.section .text.,"ax"
+.section .rodata.a,"a"
+.section .rodata,"a"
+.section .data.a,"aw"
+.section .data,"aw"
+.section .bss.a,"",@nobits
+.section .bss,"",@nobits
+.section .foo.a,"aw"
+.section .foo,"aw"
+.section .data.rel.ro,"aw",%progbits
+.section .data.rel.ro.a,"aw",%progbits
+.section .data.rel.ro.local,"aw",%progbits
+.section .data.rel.ro.local.a,"aw",%progbits
+
+// CHECK-NOT: Name: .rodata.a
+// CHECK: Name: .rodata
+// CHECK-NOT: Name: .text.a
+// CHECK: Name: .text
+// CHECK-NOT: Name: .data.rel.ro.a
+// CHECK-NOT: Name: .data.rel.ro.local.a
+// CHECK: Name: .data.rel.ro
+// CHECK-NOT: Name: .data.a
+// CHECK: Name: .data
+// CHECK: Name: .foo.a
+// CHECK: Name: .foo
+// CHECK-NOT: Name: .bss.a
+// CHECK: Name: .bss
diff --git a/test/ELF/section-symbol.s b/test/ELF/section-symbol.s
new file mode 100644
index 000000000000..5f04606914fb
--- /dev/null
+++ b/test/ELF/section-symbol.s
@@ -0,0 +1,29 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: ld.lld %t -o %t.so -shared -discard-none
+// RUN: llvm-readobj -t %t.so | FileCheck %s
+
+// Test that we don't include the section symbols from the .o in the .so
+
+// 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: foo
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+foo:
+ .quad foo
diff --git a/test/ELF/shared-be.s b/test/ELF/shared-be.s
new file mode 100644
index 000000000000..1524d48b2ed6
--- /dev/null
+++ b/test/ELF/shared-be.s
@@ -0,0 +1,35 @@
+// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
+// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared.s -o %t2.o
+// RUN: ld.lld -shared %t2.o -o %t2.so
+// RUN: ld.lld -dynamic-linker /lib64/ld64.so.1 -rpath foo -rpath bar --export-dynamic %t.o %t2.so -o %t
+// RUN: llvm-readobj --dynamic-table -s %t | FileCheck %s
+// REQUIRES: ppc
+
+// CHECK: Name: .rela.dyn
+// CHECK-NEXT: Type: SHT_REL
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: [[RELADDR:.*]]
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: [[RELSIZE:.*]]
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment:
+// CHECK-NEXT: EntrySize: [[RELENT:.*]]
+
+// CHECK: DynamicSection [
+// CHECK-NEXT: Tag Type Name/Value
+// 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: 0x0000000000000000 NULL 0x0
+// CHECK-NEXT: ]
+
+.global _start
+_start:
+.long bar
+.long zed
+
diff --git a/test/ELF/shared.s b/test/ELF/shared.s
new file mode 100644
index 000000000000..f76495d960af
--- /dev/null
+++ b/test/ELF/shared.s
@@ -0,0 +1,294 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
+// 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: llvm-readobj -s %t2.so | FileCheck --check-prefix=SO %s
+// RUN: ld.lld -dynamic-linker /lib64/ld-linux-x86-64.so.2 -rpath foo -rpath bar --export-dynamic %t.o %t2.so -o %t
+// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data -hash-table %t | FileCheck %s
+// RUN: ld.lld %t.o %t2.so %t2.so -o %t2
+// RUN: llvm-readobj -dyn-symbols %t2 | FileCheck --check-prefix=DONT_EXPORT %s
+// REQUIRES: x86
+
+// Make sure .symtab is properly aligned.
+// SO: Name: .symtab
+// SO-NEXT: Type: SHT_SYMTAB
+// SO-NEXT: Flags [
+// SO-NEXT: ]
+// SO-NEXT: Address:
+// SO-NEXT: Offset: 0x1030
+// SO-NEXT: Size:
+// SO-NEXT: Link:
+// SO-NEXT: Info:
+// SO-NEXT: AddressAlignment: 4
+
+// CHECK: Name: .interp
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: [[INTERPADDR:.*]]
+// CHECK-NEXT: Offset: [[INTERPOFFSET:.*]]
+// CHECK-NEXT: Size: [[INTERPSIZE:.*]]
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 2F6C6962 36342F6C 642D6C69 6E75782D |/lib64/ld-linux-|
+// CHECK-NEXT: 0010: 7838362D 36342E73 6F2E3200 |x86-64.so.2.|
+// CHECK-NEXT: )
+// CHECK-NEXT: }
+
+// test that .hash is linked to .dynsym
+// CHECK: Index: 2
+// CHECK-NEXT: Name: .dynsym
+// CHECK-NEXT: Type: SHT_DYNSYM
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: [[DYNSYMADDR:.*]]
+// CHECK-NEXT: Offset: 0x150
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Link: [[DYNSTR:.*]]
+// CHECK-NEXT: Info: 1
+// CHECK-NEXT: AddressAlignment: 4
+// CHECK-NEXT: EntrySize: 16
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000:
+// CHECK-NEXT: 0010:
+// CHECK-NEXT: 0020:
+// CHECK-NEXT: 0030:
+// CHECK-NEXT: )
+// CHECK-NEXT: }
+// CHECK-NEXT: Section {
+// CHECK-NEXT: Index: 3
+// CHECK-NEXT: Name: .hash
+// CHECK-NEXT: Type: SHT_HASH
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: [[HASHADDR:.*]]
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Link: 2
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 4
+// CHECK-NEXT: EntrySize: 4
+
+// CHECK: Index: [[DYNSTR]]
+// CHECK-NEXT: Name: .dynstr
+// CHECK-NEXT: Type: SHT_STRTAB
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: [[DYNSTRADDR:.*]]
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK: )
+// CHECK-NEXT: }
+
+// CHECK: Name: .rel.dyn
+// CHECK-NEXT: Type: SHT_REL
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: [[RELADDR:.*]]
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: [[RELSIZE:.*]]
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment:
+// CHECK-NEXT: EntrySize: [[RELENT:.*]]
+
+// CHECK: Name: .dynamic
+// CHECK-NEXT: Type: SHT_DYNAMIC
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: [[ADDR:.*]]
+// CHECK-NEXT: Offset: [[OFFSET:.*]]
+// CHECK-NEXT: Size: [[SIZE:.*]]
+// CHECK-NEXT: Link: [[DYNSTR]]
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: [[ALIGN:.*]]
+// CHECK-NEXT: EntrySize: 8
+// CHECK-NEXT: SectionData (
+// CHECK: )
+// CHECK-NEXT: }
+
+// CHECK: Name: .symtab
+// CHECK-NEXT: Type: SHT_SYMTAB
+// 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: [[SYMENT:.*]]
+
+// 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: 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-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: zed
+// 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: 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: _start@
+// CHECK-NEXT: Value: 0x11000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Non
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: 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-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: zed@
+// 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: ]
+
+// DONT_EXPORT: DynamicSymbols [
+// DONT_EXPORT-NEXT: Symbol {
+// DONT_EXPORT-NEXT: Name: @ (0)
+// DONT_EXPORT-NEXT: Value: 0x0
+// DONT_EXPORT-NEXT: Size: 0
+// DONT_EXPORT-NEXT: Binding: Local (0x0)
+// DONT_EXPORT-NEXT: Type: None (0x0)
+// DONT_EXPORT-NEXT: Other: 0
+// DONT_EXPORT-NEXT: Section: Undefined (0x0)
+// DONT_EXPORT-NEXT: }
+// DONT_EXPORT-NEXT: Symbol {
+// DONT_EXPORT-NEXT: Name: bar@
+// DONT_EXPORT-NEXT: Value: 0x0
+// DONT_EXPORT-NEXT: Size: 0
+// DONT_EXPORT-NEXT: Binding: Global
+// DONT_EXPORT-NEXT: Type: Function
+// DONT_EXPORT-NEXT: Other: 0
+// DONT_EXPORT-NEXT: Section: Undefined
+// DONT_EXPORT-NEXT: }
+// DONT_EXPORT-NEXT: Symbol {
+// DONT_EXPORT-NEXT: Name: zed@
+// DONT_EXPORT-NEXT: Value: 0x0
+// DONT_EXPORT-NEXT: Size: 0
+// DONT_EXPORT-NEXT: Binding: Global
+// DONT_EXPORT-NEXT: Type: None
+// DONT_EXPORT-NEXT: Other: 0
+// DONT_EXPORT-NEXT: Section: Undefined
+// DONT_EXPORT-NEXT: }
+// DONT_EXPORT-NEXT: ]
+
+// CHECK: DynamicSection [
+// CHECK-NEXT: Tag Type Name/Value
+// CHECK-NEXT: 0x00000011 REL [[RELADDR]]
+// CHECK-NEXT: 0x00000012 RELSZ [[RELSIZE]] (bytes)
+// CHECK-NEXT: 0x00000013 RELENT [[RELENT]] (bytes)
+// CHECK-NEXT: 0x00000006 SYMTAB [[DYNSYMADDR]]
+// CHECK-NEXT: 0x0000000B SYMENT [[SYMENT]] (bytes)
+// 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: 0x00000000 NULL 0x0
+// CHECK-NEXT: ]
+
+// CHECK: ProgramHeaders [
+// CHECK: Type: PT_INTERP
+// CHECK-NEXT: Offset: [[INTERPOFFSET]]
+// CHECK-NEXT: VirtualAddress: [[INTERPADDR]]
+// CHECK-NEXT: PhysicalAddress: [[INTERPADDR]]
+// CHECK-NEXT: FileSize: [[INTERPSIZE]]
+// CHECK-NEXT: MemSize: [[INTERPSIZE]]
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: PF_R
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment: 1
+// CHECK-NEXT: }
+// CHECK: Type: PT_DYNAMIC
+// CHECK-NEXT: Offset: [[OFFSET]]
+// CHECK-NEXT: VirtualAddress: [[ADDR]]
+// CHECK-NEXT: PhysicalAddress: [[ADDR]]
+// CHECK-NEXT: FileSize: [[SIZE]]
+// CHECK-NEXT: MemSize: [[SIZE]]
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: PF_R
+// CHECK-NEXT: PF_W
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment: [[ALIGN]]
+// CHECK-NEXT: }
+
+// CHECK: HashTable {
+// CHECK-NEXT: Num Buckets: 4
+// CHECK-NEXT: Num Chains: 4
+// CHECK-NEXT: Buckets: [3, 0, 2, 0]
+// CHECK-NEXT: Chains: [0, 0, 0, 1]
+// CHECK-NEXT: }
+
+.global _start
+_start:
+.long bar
+.long zed
diff --git a/test/ELF/soname.s b/test/ELF/soname.s
new file mode 100644
index 000000000000..9d6fe7681dac
--- /dev/null
+++ b/test/ELF/soname.s
@@ -0,0 +1,11 @@
+// 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 %t.so %t2.so -o %t
+// RUN: llvm-readobj --dynamic-table %t | FileCheck %s
+
+// CHECK: 0x0000000000000001 NEEDED SharedLibrary (bar)
+// CHECK-NOT: NEEDED
+
+.global _start
+_start:
diff --git a/test/ELF/soname2.s b/test/ELF/soname2.s
new file mode 100644
index 000000000000..d446766a799d
--- /dev/null
+++ b/test/ELF/soname2.s
@@ -0,0 +1,8 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -shared -soname=foo.so -o %t
+// RUN: llvm-readobj --dynamic-table %t | FileCheck %s
+
+// CHECK: 0x000000000000000E SONAME LibrarySoname (foo.so)
+
+.global _start
+_start:
diff --git a/test/ELF/startstop-shared.s b/test/ELF/startstop-shared.s
new file mode 100644
index 000000000000..108184648f97
--- /dev/null
+++ b/test/ELF/startstop-shared.s
@@ -0,0 +1,18 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t.so -shared
+// RUN: llvm-readobj -r -t %t.so | FileCheck %s
+
+ .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
+
+ .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:.*]]
+
+// CHECK: Name: __start_bar
+// CHECK-NEXT: Value: 0x[[ADDR]]
diff --git a/test/ELF/startstop.s b/test/ELF/startstop.s
new file mode 100644
index 000000000000..d0e88df4e7eb
--- /dev/null
+++ b/test/ELF/startstop.s
@@ -0,0 +1,61 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: ld.lld %t -o %tout -shared
+// RUN: llvm-objdump -d %tout | FileCheck -check-prefix=DISASM %s
+// RUN: llvm-readobj -symbols -r %tout | FileCheck -check-prefix=SYMBOL %s
+
+// DISASM: _start:
+// DISASM: 1000: {{.*}} callq 10
+// DISASM: 1005: {{.*}} callq 8
+// DISASM: 100a: {{.*}} callq 3
+// DISASM: Disassembly of section foo:
+// DISASM: __start_foo:
+// DISASM: 100f: 90 nop
+// DISASM: 1010: 90 nop
+// DISASM: 1011: 90 nop
+// DISASM: Disassembly of section bar:
+// DISASM: __start_bar:
+// DISASM: 1012: 90 nop
+// DISASM: 1013: 90 nop
+// DISASM: 1014: 90 nop
+
+
+// SYMBOL: Relocations [
+// SYMBOL-NEXT: ]
+
+// SYMBOL: Symbol {
+// SYMBOL: Name: __start_bar
+// SYMBOL: Value: 0x1012
+// SYMBOL: Section: bar
+// SYMBOL: }
+// SYMBOL-NOT: Section: __stop_bar
+// SYMBOL: Symbol {
+// SYMBOL: Name: __start_foo
+// SYMBOL: Value: 0x100F
+// SYMBOL: Section: foo
+// SYMBOL: }
+// SYMBOL: Symbol {
+// SYMBOL: Name: __stop_foo
+// SYMBOL: Value: 0x1012
+// SYMBOL: Section: foo
+// SYMBOL: }
+
+.hidden __start_foo
+.hidden __stop_foo
+.hidden __start_bar
+.global _start
+.text
+_start:
+ call __start_foo
+ call __stop_foo
+ call __start_bar
+
+.section foo,"ax"
+ nop
+ nop
+ nop
+
+.section bar,"ax"
+ nop
+ nop
+ nop
diff --git a/test/ELF/string-table.s b/test/ELF/string-table.s
new file mode 100644
index 000000000000..52a40d790d8f
--- /dev/null
+++ b/test/ELF/string-table.s
@@ -0,0 +1,80 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: ld.lld %t -o %t2
+// RUN: llvm-readobj -sections -section-data %t2 | FileCheck %s
+// REQUIRES: x86
+
+.global _start
+_start:
+
+.section foobar,"",@progbits,unique,1
+.section foobar,"T",@progbits,unique,2
+.section foobar,"",@nobits,unique,3
+.section foobar,"",@nobits,unique,4
+
+.section bar, "a"
+
+// Both sections are in the output and that the alloc section is first:
+// CHECK: Name: bar
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x10120
+
+// CHECK: Name: foobar
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x0
+
+// CHECK: Name: foobar
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_TLS
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x0
+
+// CHECK: Name: foobar
+// CHECK-NEXT: Type: SHT_NOBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x0
+
+// CHECK-NOT: Name: foobar
+
+// Test that the string "bar" is merged into "foobar".
+
+// CHECK: Section {
+// CHECK: Index:
+// CHECK: Name: .shstrtab
+// CHECK-NEXT: Type: SHT_STRTAB
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x0
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 002E7465 78740066 6F6F6261 72002E73 |..text.foobar..s|
+// CHECK-NEXT: 0010: 68737472 74616200 2E737472 74616200 |hstrtab..strtab.|
+// CHECK-NEXT: 0020: 2E73796D 74616200 |.symtab.|
+// CHECK-NEXT: )
+// CHECK-NEXT:}
+// CHECK: Name: .strtab
+// CHECK-NEXT: Type: SHT_STRTAB (0x3)
+// CHECK-NEXT: Flags [ (0x0)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x0
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 15
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 1
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: SectionData (
+// CHECK-NEXT: 0000: 005F7374 61727400 666F6F62 617200 |._start.foobar.|
+// CHECK-NEXT: )
+// CHECK-NEXT: }
diff --git a/test/ELF/strip-all.s b/test/ELF/strip-all.s
new file mode 100644
index 000000000000..6d18431668ae
--- /dev/null
+++ b/test/ELF/strip-all.s
@@ -0,0 +1,25 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: ld.lld %t.o -o %t1
+#RUN: llvm-objdump -section-headers %t1 | FileCheck %s -check-prefix BEFORE
+#BEFORE: .symtab
+#BEFORE-NEXT: .shstrtab
+#BEFORE-NEXT: .strtab
+
+#RUN: ld.lld %t.o --strip-all -o %t1
+#RUN: llvm-objdump -section-headers %t1 | FileCheck %s -check-prefix AFTER
+#AFTER-NOT: .symtab
+#AFTER: .shstrtab
+#AFTER-NOT: .strtab
+
+# 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;
+_start:
+ mov $60, %rax
+ mov $42, %rdi
+ syscall
diff --git a/test/ELF/symbols.s b/test/ELF/symbols.s
new file mode 100644
index 000000000000..ccf83afdf567
--- /dev/null
+++ b/test/ELF/symbols.s
@@ -0,0 +1,182 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: ld.lld %t -o %t2
+// RUN: llvm-readobj -symbols -sections %t2 | FileCheck %s
+// REQUIRES: x86
+
+.type _start, @function
+.globl _start
+_start:
+
+.type foo, @object
+.weak foo
+foo:
+
+.type bar, @object
+.weak bar
+.long bar
+
+.section foobar,"a",@nobits,unique,1
+.globl zed
+zed:
+ .long 0
+.globl zed2
+zed2:
+.long 0
+
+.section foobar,"a",@nobits,unique,2
+.globl zed3
+.size zed3, 4
+zed3:
+
+.globl abs
+abs = 0x123
+
+.comm common,4,4
+
+.global protected
+.protected protected
+protected:
+
+.global hidden
+.hidden hidden
+hidden:
+
+.global internal
+.internal internal
+internal:
+
+// CHECK: Name: foobar
+// CHECK-NEXT: Type: SHT_NOBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x10158
+
+// CHECK: Name: .text
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_EXECINSTR
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x1100
+
+// 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: 0x2000
+// CHECK-NEXT: Size: 4
+
+// 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: hidden
+// CHECK-NEXT: Value: 0x10160
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 2
+// CHECK-NEXT: Section: foobar
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: internal
+// CHECK-NEXT: Value: 0x10160
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 1
+// CHECK-NEXT: Section: foobar
+// 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
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: abs
+// CHECK-NEXT: Value: 0x123
+// 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: bar
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Weak (0x2)
+// CHECK-NEXT: Type: Object (0x1)
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined (0x0)
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: common
+// CHECK-NEXT: Value: 0x12000
+// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .bss
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: foo
+// CHECK-NEXT: Value: 0x11000
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Weak (0x2)
+// CHECK-NEXT: Type: Object
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: protected
+// CHECK-NEXT: Value: 0x10160
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 3
+// CHECK-NEXT: Section: foobar
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: zed
+// CHECK-NEXT: Value: 0x10158
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global (0x1)
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: foobar
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: zed2
+// CHECK-NEXT: Value: 0x1015C
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: foobar
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: zed3
+// CHECK-NEXT: Value: 0x10160
+// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: foobar
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
diff --git a/test/ELF/sysroot.s b/test/ELF/sysroot.s
new file mode 100644
index 000000000000..35154be125a3
--- /dev/null
+++ b/test/ELF/sysroot.s
@@ -0,0 +1,36 @@
+// RUN: mkdir -p %t/lib
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t/m.o
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+// RUN: %p/Inputs/libsearch-st.s -o %t/st.o
+// RUN: rm -f %t/lib/libls.a
+// RUN: llvm-ar rcs %t/lib/libls.a %t/st.o
+// REQUIRES: x86
+
+// Should not link because of undefined symbol _bar
+// RUN: not ld.lld -o %t/r %t/m.o 2>&1 \
+// RUN: | FileCheck --check-prefix=UNDEFINED %s
+// UNDEFINED: undefined symbol: _bar
+
+// 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
+
+// Should just remove the '=' symbol if --sysroot is not specified.
+// Case 1: relative path
+// RUN: cd %t && ld.lld -o %t/r %t/m.o -L=lib -l:libls.a
+// Case 2: absolute path
+// RUN: cd %p && ld.lld -o %t/r %t/m.o -L=%t/lib -l:libls.a
+
+// RUN: cd %p
+
+// Should substitute SysRoot if specified
+// RUN: ld.lld -o %t/r %t/m.o --sysroot=%t -L=lib -l:libls.a
+// RUN: ld.lld -o %t/r %t/m.o --sysroot=%t -L=/lib -l:libls.a
+
+// Should not substitute SysRoot if the directory name does not start with '='
+// 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;
+_start:
diff --git a/test/ELF/tls-align.s b/test/ELF/tls-align.s
new file mode 100644
index 000000000000..56b404e0851c
--- /dev/null
+++ b/test/ELF/tls-align.s
@@ -0,0 +1,21 @@
+// 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 -program-headers %tout | FileCheck %s
+
+ .section .tbss,"awT",@nobits
+ .align 8
+ .long 0
+
+// CHECK: ProgramHeader {
+// CHECK: Type: PT_TLS
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: VirtualAddress:
+// CHECK-NEXT: PhysicalAddress:
+// CHECK-NEXT: FileSize: 0
+// CHECK-NEXT: MemSize: 8
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: PF_R (0x4)
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment: 8
+// CHECK-NEXT: }
diff --git a/test/ELF/tls-dynamic-i686.s b/test/ELF/tls-dynamic-i686.s
new file mode 100644
index 000000000000..b2620d048864
--- /dev/null
+++ b/test/ELF/tls-dynamic-i686.s
@@ -0,0 +1,92 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t
+// RUN: ld.lld -shared %t -o %tout
+// RUN: llvm-readobj -sections -relocations %tout | FileCheck %s
+// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS
+
+.type tls0,@object
+.section .tbss,"awT",@nobits
+.globl tls0
+.align 4
+tls0:
+ .long 0
+ .size tls0, 4
+
+.type tls1,@object
+.globl tls1
+.align 4
+tls1:
+ .long 0
+ .size tls1, 4
+
+.section .text
+.globl _start
+_start:
+leal tls0@tlsgd(,%ebx,1),%eax
+call __tls_get_addr@plt
+
+leal tls1@tlsgd(,%ebx,1),%eax
+call __tls_get_addr@plt
+
+leal tls0@tlsldm(%ebx),%eax
+call __tls_get_addr@plt
+leal tls0@dtpoff(%eax),%edx
+
+leal tls1@tlsldm(%ebx),%eax
+call __tls_get_addr@plt
+leal tls1@dtpoff(%eax),%edx
+
+movl %gs:0,%eax
+addl tls0@gotntpoff(%ebx),%eax
+
+movl %gs:0,%eax
+addl tls1@gotntpoff(%ebx),%eax
+
+// CHECK: Index: 10
+// 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: 0x2068
+// CHECK-NEXT: Offset: 0x2068
+// CHECK-NEXT: Size: 32
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 4
+// CHECK-NEXT: EntrySize: 0
+
+// CHECK: Relocations [
+// CHECK: Section ({{.+}}) .rel.dyn {
+// CHECK-NEXT: 0x2068 R_386_TLS_DTPMOD32 tls0 0x0
+// CHECK-NEXT: 0x206C R_386_TLS_DTPOFF32 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: }
+
+// DIS: Disassembly of section .text:
+// DIS-NEXT: _start:
+// General dynamic model:
+// -32 and -24 are first and second GOT entries offsets.
+// Each one is a pair of records.
+// DIS-NEXT: 1000: 8d 04 1d e0 ff ff ff leal -32(,%ebx), %eax
+// DIS-NEXT: 1007: e8 64 00 00 00 calll 100
+// DIS-NEXT: 100c: 8d 04 1d e8 ff ff ff leal -24(,%ebx), %eax
+// DIS-NEXT: 1013: e8 58 00 00 00 calll 88
+// Local dynamic model:
+// -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: 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
+// 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
+// DIS-NEXT: 1046: 65 a1 00 00 00 00 movl %gs:0, %eax
+// DIS-NEXT: 104c: 03 83 fc ff ff ff addl -4(%ebx), %eax
diff --git a/test/ELF/tls-dynamic.s b/test/ELF/tls-dynamic.s
new file mode 100644
index 000000000000..b6ae6da61bb2
--- /dev/null
+++ b/test/ELF/tls-dynamic.s
@@ -0,0 +1,81 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: ld.lld -shared %t -o %tout
+// RUN: llvm-readobj -sections -relocations %tout | FileCheck %s
+// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS
+
+ leaq a@tlsld(%rip), %rdi
+ callq __tls_get_addr@PLT
+ leaq b@tlsld(%rip), %rdi
+ callq __tls_get_addr@PLT
+ leaq a@dtpoff(%rax), %rcx
+ leaq b@dtpoff(%rax), %rcx
+ .long b@dtpoff, 0
+ leaq c@tlsgd(%rip), %rdi
+ rex64
+ callq __tls_get_addr@PLT
+ leaq c@dtpoff(%rax), %rcx
+ // Initial Exec Model Code Sequence, II
+ movq c@gottpoff(%rip),%rax
+ movq %fs:(%rax),%rax
+
+ .global a
+ .hidden a
+ .section .tbss,"awT",@nobits
+ .align 4
+a:
+ .long 0
+
+ .section .tbss,"awT",@nobits
+ .align 4
+b:
+ .long 0
+ .global c
+ .section .tbss,"awT",@nobits
+ .align 4
+c:
+ .long 0
+
+// Get the address of the got, and check that it has 4 entries.
+
+// CHECK: Sections [
+// CHECK: Name: .got
+// CHECK-NEXT: Type: SHT_PROGBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+// CHECK-NEXT: Address: 0x20D0
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 40
+
+// CHECK: Relocations [
+// CHECK: Section ({{.+}}) .rela.dyn {
+// CHECK-NEXT: 0x20D0 R_X86_64_DTPMOD64 - 0x0
+// CHECK-NEXT: 0x20E0 R_X86_64_DTPMOD64 c 0x0
+// CHECK-NEXT: 0x20E8 R_X86_64_DTPOFF64 c 0x0
+// CHECK-NEXT: 0x20F0 R_X86_64_TPOFF64 c 0x0
+// CHECK-NEXT: }
+
+// 4297 = (0x20D0 + -4) - (0x1000 + 3) // PC relative offset to got entry.
+// 4285 = (0x20D0 + -4) - (0x100c + 3) // PC relative offset to got entry.
+// 4267 = (0x20E0 + -4) - (0x102e + 3) // PC relative offset to got entry.
+// 4263 = (0x20F0 + -4) - (0x1042 + 3) // PC relative offset to got entry.
+
+// DIS: Disassembly of section .text:
+// DIS-NEXT: .text:
+// DIS-NEXT: 1000: {{.+}} leaq 4297(%rip), %rdi
+// DIS-NEXT: 1007: {{.+}} callq
+// DIS-NEXT: 100c: {{.+}} leaq 4285(%rip), %rdi
+// DIS-NEXT: 1013: {{.+}} callq
+// DIS-NEXT: 1018: {{.+}} leaq (%rax), %rcx
+// DIS-NEXT: 101f: {{.+}} leaq 4(%rax), %rcx
+// DIS-NEXT: 1026: 04 00
+// DIS-NEXT: 1028: 00 00
+// DIS-NEXT: 102a: 00 00
+// 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: 1042: {{.+}} movq 4263(%rip), %rax
+// DIS-NEXT: 1049: {{.+}} movq %fs:(%rax), %rax
diff --git a/test/ELF/tls-error.s b/test/ELF/tls-error.s
new file mode 100644
index 000000000000..b61789901049
--- /dev/null
+++ b/test/ELF/tls-error.s
@@ -0,0 +1,12 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: not ld.lld %t -o %tout 2>&1 | FileCheck %s
+// CHECK: R_X86_64_TPOFF32 out of range
+
+.global _start
+_start:
+ movl %fs:a@tpoff, %eax
+.global a
+.section .tbss,"awT",@nobits
+a:
+.zero 0x80000001
diff --git a/test/ELF/tls-got.s b/test/ELF/tls-got.s
new file mode 100644
index 000000000000..10b9cf994579
--- /dev/null
+++ b/test/ELF/tls-got.s
@@ -0,0 +1,58 @@
+// 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/tls-got.s -o %t2.o
+// RUN: ld.lld -shared %t2.o -o %t2.so
+// RUN: ld.lld -e main %t1.o %t2.so -o %t3
+// RUN: llvm-readobj -s -r %t3 | FileCheck %s
+// RUN: llvm-objdump -d %t3 | FileCheck --check-prefix=DISASM %s
+
+// CHECK: Section {
+// CHECK: Index: 8
+// 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: [[ADDR:.*]]
+// CHECK-NEXT: Offset: 0x20A0
+// CHECK-NEXT: Size: 16
+// CHECK-NEXT: Link: 0
+// CHECK-NEXT: Info: 0
+// CHECK-NEXT: AddressAlignment: 8
+// CHECK-NEXT: EntrySize: 0
+// CHECK-NEXT: }
+
+// CHECK: Relocations [
+// CHECK-NEXT: Section (4) .rela.dyn {
+// CHECK-NEXT: [[ADDR]] R_X86_64_TPOFF64 tls1 0x0
+// CHECK-NEXT: 0x120A8 R_X86_64_TPOFF64 tls0 0x0
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+//0x11000 + 4249 + 7 = 0x120A0
+//0x1100A + 4247 + 7 = 0x120A8
+//0x11014 + 4237 + 7 = 0x120A8
+//DISASM: Disassembly of section .text:
+//DISASM-NEXT: main:
+//DISASM-NEXT: 11000: 48 8b 05 99 10 00 00 movq 4249(%rip), %rax
+//DISASM-NEXT: 11007: 64 8b 00 movl %fs:(%rax), %eax
+//DISASM-NEXT: 1100a: 48 8b 05 97 10 00 00 movq 4247(%rip), %rax
+//DISASM-NEXT: 11011: 64 8b 00 movl %fs:(%rax), %eax
+//DISASM-NEXT: 11014: 48 8b 05 8d 10 00 00 movq 4237(%rip), %rax
+//DISASM-NEXT: 1101b: 64 8b 00 movl %fs:(%rax), %eax
+//DISASM-NEXT: 1101e: c3 retq
+
+.section .tdata,"awT",@progbits
+
+.text
+ .globl main
+ .align 16, 0x90
+ .type main,@function
+main:
+ movq tls1@GOTTPOFF(%rip), %rax
+ movl %fs:0(%rax), %eax
+ movq tls0@GOTTPOFF(%rip), %rax
+ movl %fs:0(%rax), %eax
+ movq tls0@GOTTPOFF(%rip), %rax
+ movl %fs:0(%rax), %eax
+ ret
diff --git a/test/ELF/tls-i686.s b/test/ELF/tls-i686.s
new file mode 100644
index 000000000000..62940d6cd164
--- /dev/null
+++ b/test/ELF/tls-i686.s
@@ -0,0 +1,69 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t
+// RUN: ld.lld %t -o %tout
+// RUN: ld.lld %t -shared -o %tsharedout
+// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS
+// RUN: llvm-readobj -r %tout | FileCheck %s --check-prefix=RELOC
+// RUN: llvm-objdump -d %tsharedout | FileCheck %s --check-prefix=DISSHARED
+// RUN: llvm-readobj -r %tsharedout | FileCheck %s --check-prefix=RELOCSHARED
+
+.section ".tdata", "awT", @progbits
+.globl var
+.globl var1
+var:
+.long 0
+var1:
+.long 1
+
+.text
+.global _start
+_start:
+ movl $var@tpoff, %edx
+ movl %gs:0, %ecx
+ subl %edx, %eax
+ movl $var1@tpoff, %edx
+ movl %gs:0, %ecx
+ subl %edx, %eax
+
+ movl %gs:0, %ecx
+ leal var@ntpoff(%ecx), %eax
+ movl %gs:0, %ecx
+ leal var1@ntpoff(%ecx), %eax
+
+// DIS: Disassembly of section .text:
+// 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
+
+// RELOC: Relocations [
+// RELOC-NEXT: ]
+
+// DISSHARED: Disassembly of section .text:
+// 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
+
+// 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: }
+// RELOCSHARED-NEXT: ]
diff --git a/test/ELF/tls-mismatch.s b/test/ELF/tls-mismatch.s
new file mode 100644
index 000000000000..fb70229e1a52
--- /dev/null
+++ b/test/ELF/tls-mismatch.s
@@ -0,0 +1,9 @@
+// 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: not ld.lld %t %t2 -o %t3 2>&1 | FileCheck %s
+// CHECK: TLS attribute mismatch for symbol: tlsvar
+
+.globl _start,tlsvar
+_start:
+ movl tlsvar,%edx
diff --git a/test/ELF/tls-opt-gdie.s b/test/ELF/tls-opt-gdie.s
new file mode 100644
index 000000000000..a6c68686c57b
--- /dev/null
+++ b/test/ELF/tls-opt-gdie.s
@@ -0,0 +1,55 @@
+// 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-opt-gdie.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 -s -r %t1 | FileCheck --check-prefix=RELOC %s
+// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
+
+//RELOC: Section {
+//RELOC: Index: 9
+//RELOC-NEXT: Name: .got
+//RELOC-NEXT: Type: SHT_PROGBITS
+//RELOC-NEXT: Flags [
+//RELOC-NEXT: SHF_ALLOC
+//RELOC-NEXT: SHF_WRITE
+//RELOC-NEXT: ]
+//RELOC-NEXT: Address: 0x120E0
+//RELOC-NEXT: Offset: 0x20E0
+//RELOC-NEXT: Size: 16
+//RELOC-NEXT: Link: 0
+//RELOC-NEXT: Info: 0
+//RELOC-NEXT: AddressAlignment: 8
+//RELOC-NEXT: EntrySize: 0
+//RELOC-NEXT: }
+//RELOC: Relocations [
+//RELOC-NEXT: Section (4) .rela.dyn {
+//RELOC-NEXT: 0x120E0 R_X86_64_TPOFF64 tlsshared0 0x0
+//RELOC-NEXT: 0x120E8 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: }
+//RELOC-NEXT: ]
+
+//0x11009 + (4304 + 7) = 0x120E0
+//0x11019 + (4296 + 7) = 0x120E8
+// 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 d0 10 00 00 addq 4304(%rip), %rax
+// DISASM-NEXT: 11010: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax
+// DISASM-NEXT: 11019: 48 03 05 c8 10 00 00 addq 4296(%rip), %rax
+
+.section .text
+.globl _start
+_start:
+ .byte 0x66
+ leaq tlsshared0@tlsgd(%rip),%rdi
+ .word 0x6666
+ rex64
+ call __tls_get_addr@plt
+ .byte 0x66
+ leaq tlsshared1@tlsgd(%rip),%rdi
+ .word 0x6666
+ rex64
+ call __tls_get_addr@plt
diff --git a/test/ELF/tls-opt-gdiele-i686.s b/test/ELF/tls-opt-gdiele-i686.s
new file mode 100644
index 000000000000..94630bbc0df2
--- /dev/null
+++ b/test/ELF/tls-opt-gdiele-i686.s
@@ -0,0 +1,59 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/tls-opt-gdiele-i686.s -o %tso.o
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
+// RUN: ld.lld -shared %tso.o -o %tso
+// RUN: ld.lld %t.o %tso -o %tout
+// RUN: llvm-readobj -r %tout | FileCheck --check-prefix=NORELOC %s
+// RUN: llvm-objdump -d %tout | FileCheck --check-prefix=DISASM %s
+
+// NORELOC: Relocations [
+// NORELOC-NEXT: Section ({{.*}}) .rel.dyn {
+// NORELOC-NEXT: 0x12050 R_386_TLS_TPOFF tlsshared0 0x0
+// NORELOC-NEXT: 0x12054 R_386_TLS_TPOFF tlsshared1 0x0
+// NORELOC-NEXT: }
+// NORELOC-NEXT: ]
+
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: _start:
+// DISASM-NEXT: 11000: 65 a1 00 00 00 00 movl %gs:0, %eax
+// DISASM-NEXT: 11006: 03 83 f8 ff ff ff addl -8(%ebx), %eax
+// DISASM-NEXT: 1100c: 65 a1 00 00 00 00 movl %gs:0, %eax
+// DISASM-NEXT: 11012: 03 83 fc ff ff ff addl -4(%ebx), %eax
+// DISASM-NEXT: 11018: 65 a1 00 00 00 00 movl %gs:0, %eax
+// DISASM-NEXT: 1101e: 81 e8 08 00 00 00 subl $8, %eax
+// DISASM-NEXT: 11024: 65 a1 00 00 00 00 movl %gs:0, %eax
+// DISASM-NEXT: 1102a: 81 e8 04 00 00 00 subl $4, %eax
+
+.type tlsexe1,@object
+.section .tbss,"awT",@nobits
+.globl tlsexe1
+.align 4
+tlsexe1:
+ .long 0
+ .size tlsexe1, 4
+
+.type tlsexe2,@object
+.section .tbss,"awT",@nobits
+.globl tlsexe2
+.align 4
+tlsexe2:
+ .long 0
+ .size tlsexe2, 4
+
+.section .text
+.globl ___tls_get_addr
+.type ___tls_get_addr,@function
+___tls_get_addr:
+
+.section .text
+.globl _start
+_start:
+//GD->IE
+leal tlsshared0@tlsgd(,%ebx,1),%eax
+call ___tls_get_addr@plt
+leal tlsshared1@tlsgd(,%ebx,1),%eax
+call ___tls_get_addr@plt
+//GD->IE
+leal tlsexe1@tlsgd(,%ebx,1),%eax
+call ___tls_get_addr@plt
+leal tlsexe2@tlsgd(,%ebx,1),%eax
+call ___tls_get_addr@plt
diff --git a/test/ELF/tls-opt-i686.s b/test/ELF/tls-opt-i686.s
new file mode 100644
index 000000000000..dec45b4e5c41
--- /dev/null
+++ b/test/ELF/tls-opt-i686.s
@@ -0,0 +1,69 @@
+// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t1
+// RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=NORELOC %s
+// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
+
+// NORELOC: Relocations [
+// NORELOC-NEXT: ]
+
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: _start:
+// LD -> LE:
+// DISASM-NEXT: 11000: 65 a1 00 00 00 00 movl %gs:0, %eax
+// DISASM-NEXT: 11006: 90 nop
+// DISASM-NEXT: 11007: 8d 74 26 00 leal (%esi), %esi
+// DISASM-NEXT: 1100b: 8d 90 f8 ff ff ff leal -8(%eax), %edx
+// DISASM-NEXT: 11011: 65 a1 00 00 00 00 movl %gs:0, %eax
+// DISASM-NEXT: 11017: 90 nop
+// DISASM-NEXT: 11018: 8d 74 26 00 leal (%esi), %esi
+// DISASM-NEXT: 1101c: 8d 90 fc ff ff ff leal -4(%eax), %edx
+// IE -> LE:
+// 4294967288 == 0xFFFFFFF8
+// 4294967292 == 0xFFFFFFFC
+// DISASM-NEXT: 11022: 65 a1 00 00 00 00 movl %gs:0, %eax
+// DISASM-NEXT: 11028: c7 c0 f8 ff ff ff movl $4294967288, %eax
+// DISASM-NEXT: 1102e: 65 a1 00 00 00 00 movl %gs:0, %eax
+// DISASM-NEXT: 11034: c7 c0 fc ff ff ff movl $4294967292, %eax
+// DISASM-NEXT: 1103a: 65 a1 00 00 00 00 movl %gs:0, %eax
+// DISASM-NEXT: 11040: 8d 80 f8 ff ff ff leal -8(%eax), %eax
+// DISASM-NEXT: 11046: 65 a1 00 00 00 00 movl %gs:0, %eax
+// DISASM-NEXT: 1104c: 8d 80 fc ff ff ff leal -4(%eax), %eax
+.type tls0,@object
+.section .tbss,"awT",@nobits
+.globl tls0
+.align 4
+tls0:
+ .long 0
+ .size tls0, 4
+
+.type tls1,@object
+.globl tls1
+.align 4
+tls1:
+ .long 0
+ .size tls1, 4
+
+.section .text
+.globl ___tls_get_addr
+.type ___tls_get_addr,@function
+___tls_get_addr:
+
+.section .text
+.globl _start
+_start:
+//LD -> LE:
+leal tls0@tlsldm(%ebx),%eax
+call ___tls_get_addr@plt
+leal tls0@dtpoff(%eax),%edx
+leal tls1@tlsldm(%ebx),%eax
+call ___tls_get_addr@plt
+leal tls1@dtpoff(%eax),%edx
+//IE -> LE:
+movl %gs:0,%eax
+movl tls0@gotntpoff(%ebx),%eax
+movl %gs:0,%eax
+movl tls1@gotntpoff(%ebx),%eax
+movl %gs:0,%eax
+addl tls0@gotntpoff(%ebx),%eax
+movl %gs:0,%eax
+addl tls1@gotntpoff(%ebx),%eax
diff --git a/test/ELF/tls-opt-iele-i686-nopic.s b/test/ELF/tls-opt-iele-i686-nopic.s
new file mode 100644
index 000000000000..bc6c6bed7b44
--- /dev/null
+++ b/test/ELF/tls-opt-iele-i686-nopic.s
@@ -0,0 +1,159 @@
+// 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 %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:
+// GOTREL: Name: .got
+// GOTREL-NEXT: Type: SHT_PROGBITS
+// GOTREL-NEXT: Flags [
+// GOTREL-NEXT: SHF_ALLOC
+// GOTREL-NEXT: SHF_WRITE
+// GOTREL-NEXT: ]
+// GOTREL-NEXT: Address: 0x12050
+// GOTREL-NEXT: Offset: 0x2050
+// GOTREL-NEXT: Size: 8
+// GOTREL-NEXT: Link: 0
+// GOTREL-NEXT: Info: 0
+// GOTREL-NEXT: AddressAlignment: 4
+// GOTREL-NEXT: EntrySize: 0
+// GOTREL-NEXT: }
+// GOTREL: Relocations [
+// GOTREL-NEXT: Section ({{.*}}) .rel.dyn {
+// GOTREL-NEXT: 0x12050 R_386_TLS_TPOFF tlsshared0 0x0
+// GOTREL-NEXT: 0x12054 R_386_TLS_TPOFF tlsshared1 0x0
+// GOTREL-NEXT: }
+// GOTREL-NEXT: ]
+
+// DISASM: Disassembly of section .text:
+// DISASM-NEXT: _start:
+// 4294967288 = 0xFFFFFFF8
+// 4294967292 = 0xFFFFFFFC
+// 73808 = (.got)[0] = 0x12050
+// 73812 = (.got)[1] = 0x12054
+// DISASM-NEXT: 11000: c7 c1 f8 ff ff ff movl $4294967288, %ecx
+// DISASM-NEXT: 11006: 65 8b 01 movl %gs:(%ecx), %eax
+// DISASM-NEXT: 11009: b8 f8 ff ff ff movl $4294967288, %eax
+// DISASM-NEXT: 1100e: 65 8b 00 movl %gs:(%eax), %eax
+// DISASM-NEXT: 11011: 81 c1 f8 ff ff ff addl $4294967288, %ecx
+// DISASM-NEXT: 11017: 65 8b 01 movl %gs:(%ecx), %eax
+// DISASM-NEXT: 1101a: c7 c1 fc ff ff ff movl $4294967292, %ecx
+// DISASM-NEXT: 11020: 65 8b 01 movl %gs:(%ecx), %eax
+// DISASM-NEXT: 11023: b8 fc ff ff ff movl $4294967292, %eax
+// DISASM-NEXT: 11028: 65 8b 00 movl %gs:(%eax), %eax
+// DISASM-NEXT: 1102b: 81 c1 fc ff ff ff addl $4294967292, %ecx
+// DISASM-NEXT: 11031: 65 8b 01 movl %gs:(%ecx), %eax
+// DISASM-NEXT: 11034: 8b 0d 50 20 01 00 movl 73808, %ecx
+// DISASM-NEXT: 1103a: 65 8b 01 movl %gs:(%ecx), %eax
+// DISASM-NEXT: 1103d: 03 0d 54 20 01 00 addl 73812, %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
+.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 .text
+.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/tls-opt-local.s b/test/ELF/tls-opt-local.s
new file mode 100644
index 000000000000..d2904ac6fba0
--- /dev/null
+++ b/test/ELF/tls-opt-local.s
@@ -0,0 +1,52 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t1
+// RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=NORELOC %s
+// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
+
+// 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
+
+.section .tbss,"awT",@nobits
+
+.type tls0,@object
+.align 4
+tls0:
+ .long 0
+ .size tls0, 4
+
+.type tls1,@object
+.align 4
+tls1:
+ .long 0
+ .size tls1, 4
+
+.section .text
+.globl _start
+_start:
+ movq tls0@GOTTPOFF(%rip), %rax
+ movq tls0@GOTTPOFF(%rip), %r15
+ addq tls0@GOTTPOFF(%rip), %rax
+ addq tls0@GOTTPOFF(%rip), %r15
+ addq tls0@GOTTPOFF(%rip), %rsp
+ addq tls0@GOTTPOFF(%rip), %r12
+ movq tls1@GOTTPOFF(%rip), %rax
+ movq tls1@GOTTPOFF(%rip), %r15
+ addq tls1@GOTTPOFF(%rip), %rax
+ addq tls1@GOTTPOFF(%rip), %r15
+ addq tls1@GOTTPOFF(%rip), %rsp
+ addq tls1@GOTTPOFF(%rip), %r12
diff --git a/test/ELF/tls-opt.s b/test/ELF/tls-opt.s
new file mode 100644
index 000000000000..06577d7e1021
--- /dev/null
+++ b/test/ELF/tls-opt.s
@@ -0,0 +1,93 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+// RUN: ld.lld %t.o -o %t1
+// RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=NORELOC %s
+// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
+
+// 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
+// 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
+// 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
+
+.type tls0,@object
+.section .tbss,"awT",@nobits
+.globl tls0
+.align 4
+tls0:
+ .long 0
+ .size tls0, 4
+
+.type tls1,@object
+.globl tls1
+.align 4
+tls1:
+ .long 0
+ .size tls1, 4
+
+.section .text
+.globl _start
+_start:
+ movq tls0@GOTTPOFF(%rip), %rax
+ movq tls0@GOTTPOFF(%rip), %r15
+ addq tls0@GOTTPOFF(%rip), %rax
+ addq tls0@GOTTPOFF(%rip), %r15
+ addq tls0@GOTTPOFF(%rip), %rsp
+ addq tls0@GOTTPOFF(%rip), %r12
+ movq tls1@GOTTPOFF(%rip), %rax
+ movq tls1@GOTTPOFF(%rip), %r15
+ addq tls1@GOTTPOFF(%rip), %rax
+ addq tls1@GOTTPOFF(%rip), %r15
+ 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:
+ leaq tls0@tlsld(%rip), %rdi
+ callq __tls_get_addr@PLT
+ leaq tls0@dtpoff(%rax),%rcx
+ leaq tls1@tlsld(%rip), %rdi
+ callq __tls_get_addr@PLT
+ leaq tls1@dtpoff(%rax),%rcx
+
+ //GD to LE:
+ .byte 0x66
+ leaq tls0@tlsgd(%rip),%rdi
+ .word 0x6666
+ rex64
+ call __tls_get_addr@plt
+ .byte 0x66
+ leaq tls1@tlsgd(%rip),%rdi
+ .word 0x6666
+ rex64
+ call __tls_get_addr@plt
diff --git a/test/ELF/tls-static.s b/test/ELF/tls-static.s
new file mode 100644
index 000000000000..4c515abb1252
--- /dev/null
+++ b/test/ELF/tls-static.s
@@ -0,0 +1,13 @@
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
+// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/shared.s -o %tso
+// RUN: ld.lld -static %t -o %tout
+// RUN: ld.lld %t -o %tout
+// RUN: ld.lld -shared %tso -o %tshared
+// RUN: not ld.lld -static %t %tshared -o %tout 2>&1 | FileCheck %s
+// REQUIRES: x86
+
+.global _start
+_start:
+ call __tls_get_addr
+
+// CHECK: undefined symbol: __tls_get_addr
diff --git a/test/ELF/tls.s b/test/ELF/tls.s
new file mode 100644
index 000000000000..525890b087e2
--- /dev/null
+++ b/test/ELF/tls.s
@@ -0,0 +1,170 @@
+// REQUIRES: x86
+// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
+// RUN: ld.lld %t -o %tout
+// RUN: llvm-readobj -symbols -sections -program-headers %tout | FileCheck %s
+// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS
+
+.global _start
+_start:
+ movl %fs:a@tpoff, %eax
+ movl %fs:b@tpoff, %eax
+ movl %fs:c@tpoff, %eax
+ movl %fs:d@tpoff, %eax
+
+ .global a
+ .section .tbss,"awT",@nobits
+a:
+ .long 0
+
+ .global b
+ .section .tdata,"awT",@progbits
+b:
+ .long 1
+
+ .global c
+ .section .thread_bss,"awT",@nobits
+c:
+ .long 0
+
+ .global d
+ .section .thread_data,"awT",@progbits
+d:
+ .long 2
+
+// 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: [[TDATA_ADDR:0x.*]]
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment:
+// CHECK-NEXT: EntrySize:
+// CHECK-NEXT: }
+// CHECK-NEXT: Section {
+// CHECK-NEXT: Index:
+// CHECK-NEXT: Name: .thread_data
+// 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:
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment:
+// CHECK-NEXT: EntrySize:
+// CHECK-NEXT: }
+// CHECK-NEXT: Section {
+// CHECK-NEXT: Index:
+// CHECK-NEXT: 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: [[TBSS_ADDR:0x.*]]
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment:
+// CHECK-NEXT: EntrySize:
+// CHECK-NEXT: }
+// CHECK-NEXT: Section {
+// CHECK-NEXT: Index:
+// CHECK-NEXT: Name: .thread_bss
+// CHECK-NEXT: Type: SHT_NOBITS
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: SHF_ALLOC
+// CHECK-NEXT: SHF_TLS
+// CHECK-NEXT: SHF_WRITE
+// CHECK-NEXT: ]
+
+// 0x1200C = TBSS_ADDR + 4
+
+// CHECK-NEXT: Address: 0x1200C
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: Size: 4
+// CHECK-NEXT: Link:
+// CHECK-NEXT: Info:
+// CHECK-NEXT: AddressAlignment:
+// CHECK-NEXT: EntrySize:
+// CHECK-NEXT: }
+
+// CHECK: Symbols [
+// CHECK: Name: a
+// CHECK-NEXT: Value: 0x8
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: TLS
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .tbss
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: b
+// CHECK-NEXT: Value: 0x0
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: TLS
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .tdata
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: c
+// CHECK-NEXT: Value: 0xC
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: TLS
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .thread_bss
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: d
+// CHECK-NEXT: Value: 0x4
+// CHECK-NEXT: Size:
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: TLS
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: .thread_data
+// CHECK-NEXT: }
+
+// Check that the TLS NOBITS sections weren't added to the R/W PT_LOAD's size.
+
+// CHECK: ProgramHeaders [
+// CHECK: Type: PT_LOAD
+// CHECK: Type: PT_LOAD
+// CHECK: Type: PT_LOAD
+// CHECK: FileSize: 8
+// CHECK-NEXT: MemSize: 8
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: PF_R
+// CHECK-NEXT: PF_W
+// CHECK-NEXT: ]
+// CHECK: Type: PT_TLS
+// CHECK-NEXT: Offset:
+// CHECK-NEXT: VirtualAddress: [[TDATA_ADDR]]
+// CHECK-NEXT: PhysicalAddress: [[TDATA_ADDR]]
+// CHECK-NEXT: FileSize: 8
+// CHECK-NEXT: MemSize: 16
+// CHECK-NEXT: Flags [
+// CHECK-NEXT: PF_R
+// CHECK-NEXT: ]
+// CHECK-NEXT: Alignment:
+// CHECK-NEXT: }
+
+// DIS: Disassembly of section .text:
+// DIS-NEXT: _start:
+// DIS-NEXT: 11000: {{.+}} movl %fs:-8, %eax
+// DIS-NEXT: 11008: {{.+}} movl %fs:-16, %eax
+// DIS-NEXT: 11010: {{.+}} movl %fs:-4, %eax
+// DIS-NEXT: 11018: {{.+}} movl %fs:-12, %eax
diff --git a/test/ELF/undef-start.s b/test/ELF/undef-start.s
new file mode 100644
index 000000000000..bf1d89853f59
--- /dev/null
+++ b/test/ELF/undef-start.s
@@ -0,0 +1,4 @@
+# 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: _start
+# REQUIRES: x86
diff --git a/test/ELF/undef.s b/test/ELF/undef.s
new file mode 100644
index 000000000000..374c9c884d5f
--- /dev/null
+++ b/test/ELF/undef.s
@@ -0,0 +1,8 @@
+# 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
+
+ .globl _start;
+_start:
+ call foo
diff --git a/test/ELF/undefined-opt.s b/test/ELF/undefined-opt.s
new file mode 100644
index 000000000000..97ab5a63490a
--- /dev/null
+++ b/test/ELF/undefined-opt.s
@@ -0,0 +1,55 @@
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+# RUN: %p/Inputs/abs.s -o %tabs.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
+# RUN: %p/Inputs/shared.s -o %tshared.o
+# RUN: rm -f %tar.a
+# RUN: llvm-ar rcs %tar.a %tabs.o %tshared.o
+# REQUIRES: x86
+
+# Symbols from the archive are not in if not needed
+# RUN: ld.lld -o %t1 %t.o %tar.a
+# RUN: llvm-readobj --symbols %t1 | FileCheck --check-prefix=NO-UNDEFINED %s
+# NO-UNDEFINED: Symbols [
+# NO-UNDEFINED-NOT: Name: abs
+# NO-UNDEFINED-NOT: Name: big
+# NO-UNDEFINED-NOT: Name: bar
+# NO-UNDEFINED-NOT: Name: zed
+# NO-UNDEFINED: ]
+
+# Symbols from the archive are in if needed, but only from the
+# containing object file
+# RUN: ld.lld -o %t2 %t.o %tar.a -u bar
+# RUN: llvm-readobj --symbols %t2 | FileCheck --check-prefix=ONE-UNDEFINED %s
+# ONE-UNDEFINED: Symbols [
+# ONE-UNDEFINED-NOT: Name: abs
+# ONE-UNDEFINED-NOT: Name: big
+# ONE-UNDEFINED: Name: bar
+# ONE-UNDEFINED: Name: zed
+# ONE-UNDEFINED: ]
+
+# Use the option couple of times, both short and long forms
+# RUN: ld.lld -o %t3 %t.o %tar.a -u bar --undefined=abs
+# RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=TWO-UNDEFINED %s
+# TWO-UNDEFINED: Symbols [
+# TWO-UNDEFINED: Name: abs
+# TWO-UNDEFINED: Name: big
+# TWO-UNDEFINED: Name: bar
+# TWO-UNDEFINED: Name: zed
+# TWO-UNDEFINED: ]
+# Now the same logic but linker script is used to set undefines
+# RUN: echo "EXTERN( bar abs )" > %t.script
+# RUN: ld.lld -o %t3 %t.o %tar.a %t.script
+# RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=TWO-UNDEFINED %s
+
+# Added undefined symbol may be left undefined without error, but
+# shouldn't show up in the dynamic table.
+# RUN: ld.lld -shared -o %t4 %t.o %tar.a -u unknown
+# RUN: llvm-readobj --dyn-symbols %t4 | \
+# RUN: FileCheck --check-prefix=UNK-UNDEFINED-SO %s
+# UNK-UNDEFINED-SO: DynamicSymbols [
+# UNK-UNDEFINED-SO-NOT: Name: unknown
+# UNK-UNDEFINED-SO: ]
+
+.globl _start;
+_start:
diff --git a/test/ELF/valid-cie-length-dw64.s b/test/ELF/valid-cie-length-dw64.s
new file mode 100644
index 000000000000..65d6952448a2
--- /dev/null
+++ b/test/ELF/valid-cie-length-dw64.s
@@ -0,0 +1,13 @@
+// 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/visibility.s b/test/ELF/visibility.s
new file mode 100644
index 000000000000..d76ed0793eb1
--- /dev/null
+++ b/test/ELF/visibility.s
@@ -0,0 +1,108 @@
+// 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/visibility.s -o %t2
+// RUN: ld.lld -shared %t %t2 -o %t3
+// RUN: llvm-readobj -t -dyn-symbols %t3 | FileCheck %s
+// REQUIRES: x86
+
+// 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: hidden
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 2
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: internal
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 1
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: protected_with_hidden
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Local
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 2
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: default
+// 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: Symbol {
+// CHECK-NEXT: Name: protected
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 3
+// CHECK-NEXT: Section: .text
+// 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
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 0
+// CHECK-NEXT: Section: Undefined
+// CHECK-NEXT: }
+// CHECK-NEXT: Symbol {
+// CHECK-NEXT: Name: default
+// 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: Symbol {
+// CHECK-NEXT: Name: protected
+// CHECK-NEXT: Value:
+// CHECK-NEXT: Size: 0
+// CHECK-NEXT: Binding: Global
+// CHECK-NEXT: Type: None
+// CHECK-NEXT: Other: 3
+// CHECK-NEXT: Section: .text
+// CHECK-NEXT: }
+// CHECK-NEXT: ]
+
+.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/whole-archive.s b/test/ELF/whole-archive.s
new file mode 100644
index 000000000000..0a6b30fd171e
--- /dev/null
+++ b/test/ELF/whole-archive.s
@@ -0,0 +1,34 @@
+// 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 \
+// RUN: %p/Inputs/whole-archive.s -o %ta.o
+// RUN: rm -f %t.a
+// RUN: llvm-ar rcs %t.a %ta.o
+
+// Should not add symbols from the archive by default as they are not required
+// RUN: ld.lld -o %t3 %t.o %t.a
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=NOTADDED %s
+// NOTADDED: Symbols [
+// NOTADDED-NOT: Name: _bar
+// NOTADDED: ]
+
+// Should add symbols from the archive if --whole-archive is used
+// RUN: ld.lld -o %t3 %t.o --whole-archive %t.a
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=ADDED %s
+// ADDED: Symbols [
+// ADDED: Name: _bar
+// ADDED: ]
+
+// --no-whole-archive should restore default behaviour
+// RUN: ld.lld -o %t3 %t.o --whole-archive --no-whole-archive %t.a
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=NOTADDED %s
+
+// --whole-archive and --no-whole-archive should affect only archives which follow them
+// RUN: ld.lld -o %t3 %t.o %t.a --whole-archive --no-whole-archive
+// RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=NOTADDED %s
+// 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;
+_start:
diff --git a/test/ELF/writable-merge.s b/test/ELF/writable-merge.s
new file mode 100644
index 000000000000..dd7b8538e57a
--- /dev/null
+++ b/test/ELF/writable-merge.s
@@ -0,0 +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
+
+ .section .foo,"awM",@progbits,4
diff --git a/test/ELF/x86-64-reloc-32-error.s b/test/ELF/x86-64-reloc-32-error.s
new file mode 100644
index 000000000000..b5d476bcf082
--- /dev/null
+++ b/test/ELF/x86-64-reloc-32-error.s
@@ -0,0 +1,8 @@
+// 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-32S-error.s b/test/ELF/x86-64-reloc-32S-error.s
new file mode 100644
index 000000000000..aa19c2c32e93
--- /dev/null
+++ b/test/ELF/x86-64-reloc-32S-error.s
@@ -0,0 +1,7 @@
+// 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/LinkerScript/phdrs-sections.test b/test/LinkerScript/phdrs-sections.test
new file mode 100644
index 000000000000..872b7999cb7e
--- /dev/null
+++ b/test/LinkerScript/phdrs-sections.test
@@ -0,0 +1,29 @@
+/*
+ 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
index 8f7d01418044..67f8288badaa 100644
--- a/test/LinkerScript/sections.test
+++ b/test/LinkerScript/sections.test
@@ -26,6 +26,7 @@ SECTIONS
}
.init :
{
+ FILL (0x90909090)
KEEP (*(SORT_NONE(.init)))
} =0x909090909090909090909090
PROVIDE (__etext = .);
@@ -181,6 +182,10 @@ 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: *
@@ -556,6 +561,7 @@ CHECK: PROVIDE_HIDDEN(__rela_iplt_end = .)
CHECK: }
CHECK: .init :
CHECK: {
+CHECK: FILL(0x90909090)
CHECK: KEEP(*(SORT_NONE(.init)))
CHECK: } =0x909090909090909090909090
CHECK: PROVIDE(__etext = .)
diff --git a/test/Makefile b/test/Makefile
deleted file mode 100644
index 2d45e4fae2a7..000000000000
--- a/test/Makefile
+++ /dev/null
@@ -1,71 +0,0 @@
-LLD_LEVEL := ..
-include $(LLD_LEVEL)/Makefile
-
-# Test in all immediate subdirectories if unset.
-ifdef TESTSUITE
-TESTDIRS := $(TESTSUITE:%=$(PROJ_SRC_DIR)/%)
-else
-TESTDIRS ?= $(PROJ_SRC_DIR)
-endif
-
-# 'lit' wants objdir paths, so it will pick up the lit.site.cfg.
-TESTDIRS := $(TESTDIRS:$(PROJ_SRC_DIR)%=$(PROJ_OBJ_DIR)%)
-
-# Allow EXTRA_TESTDIRS to provide additional test directories.
-TESTDIRS += $(EXTRA_TESTDIRS)
-
-ifndef TESTARGS
-ifdef VERBOSE
-TESTARGS = -v
-else
-TESTARGS = -s -v
-endif
-endif
-
-# Make sure any extra test suites can find the main site config.
-LIT_ARGS := --param lld_site_config=$(PROJ_OBJ_DIR)/lit.site.cfg
-
-ifdef VG
- LIT_ARGS += "--vg"
-endif
-
-all:: lit.site.cfg Unit/lit.site.cfg
- @ echo '--- Running lld tests for $(TARGET_TRIPLE) ---'
- @ $(PYTHON) $(LLVM_SRC_ROOT)/utils/lit/lit.py \
- $(LIT_ARGS) $(TESTARGS) $(TESTDIRS)
-
-FORCE:
-
-lit.site.cfg: FORCE
- @echo "Making lld 'lit.site.cfg' file..."
- @$(ECHOPATH) s=@LLVM_SOURCE_DIR@=$(LLVM_SRC_ROOT)=g > lit.tmp
- @$(ECHOPATH) s=@LLVM_BINARY_DIR@=$(LLVM_OBJ_ROOT)=g >> lit.tmp
- @$(ECHOPATH) s=@LLVM_TOOLS_DIR@=$(ToolDir)=g >> lit.tmp
- @$(ECHOPATH) s=@LLVM_LIBS_DIR@=$(LibDir)=g >> lit.tmp
- @$(ECHOPATH) s=@LLD_SOURCE_DIR@=$(PROJ_SRC_DIR)/..=g >> lit.tmp
- @$(ECHOPATH) s=@LLD_BINARY_DIR@=$(PROJ_OBJ_DIR)/..=g >> lit.tmp
- @$(ECHOPATH) s=@TARGET_TRIPLE@=$(TARGET_TRIPLE)=g >> lit.tmp
- @sed -f lit.tmp $(PROJ_SRC_DIR)/lit.site.cfg.in > $@
- @-rm -f lit.tmp
-
-Unit/lit.site.cfg: FORCE
- @echo "Making lld 'Unit/lit.site.cfg' file..."
- @$(MKDIR) $(dir $@)
- @$(ECHOPATH) s=@LLVM_SOURCE_DIR@=$(LLVM_SRC_ROOT)=g > unit.tmp
- @$(ECHOPATH) s=@LLVM_BINARY_DIR@=$(LLVM_OBJ_ROOT)=g >> unit.tmp
- @$(ECHOPATH) s=@LLVM_TOOLS_DIR@=$(ToolDir)=g >> unit.tmp
- @$(ECHOPATH) s=@LLVM_LIBS_DIR@=$(LibDir)=g >> unit.tmp
- @$(ECHOPATH) s=@LLD_SOURCE_DIR@=$(PROJ_SRC_DIR)/..=g >> unit.tmp
- @$(ECHOPATH) s=@LLD_BINARY_DIR@=$(PROJ_OBJ_DIR)/..=g >> unit.tmp
- @$(ECHOPATH) s=@TARGET_TRIPLE@=$(TARGET_TRIPLE)=g >> unit.tmp
- @$(ECHOPATH) s=@LLVM_BUILD_MODE@=$(BuildMode)=g >> unit.tmp
- @$(ECHOPATH) s=@ENABLE_SHARED@=$(ENABLE_SHARED)=g >> unit.tmp
- @$(ECHOPATH) s=@SHLIBDIR@=$(SharedLibDir)=g >> unit.tmp
- @$(ECHOPATH) s=@SHLIBPATH_VAR@=$(SHLIBPATH_VAR)=g >> unit.tmp
- @sed -f unit.tmp $(PROJ_SRC_DIR)/Unit/lit.site.cfg.in > $@
- @-rm -f unit.tmp
-
-clean::
- @ find . -name Output | xargs rm -fr
-
-.PHONY: all report clean
diff --git a/test/core/Inputs/archive-basic.objtxt b/test/core/Inputs/archive-basic.objtxt
new file mode 100644
index 000000000000..ecfdacd0b6dd
--- /dev/null
+++ b/test/core/Inputs/archive-basic.objtxt
@@ -0,0 +1,21 @@
+--- !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
new file mode 100644
index 000000000000..d3cc17137c18
--- /dev/null
+++ b/test/core/Inputs/archive-chain.objtxt
@@ -0,0 +1,24 @@
+--- !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
new file mode 100644
index 000000000000..aed6b1b959e1
--- /dev/null
+++ b/test/core/Inputs/archive-chain2.objtxt
@@ -0,0 +1,21 @@
+--- !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
new file mode 100644
index 000000000000..70219aac7a6d
--- /dev/null
+++ b/test/core/Inputs/archive-tentdef-search.objtxt
@@ -0,0 +1,11 @@
+--- !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
new file mode 100644
index 000000000000..29d028c27edc
--- /dev/null
+++ b/test/core/Inputs/associates.objtxt
@@ -0,0 +1,8 @@
+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
new file mode 100644
index 000000000000..d82d0f41c4f4
--- /dev/null
+++ b/test/core/Inputs/auto-hide-coalesce.objtxt
@@ -0,0 +1,20 @@
+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
new file mode 100644
index 000000000000..7c01a0d57f36
--- /dev/null
+++ b/test/core/Inputs/code-model-attributes.objtxt
@@ -0,0 +1,4 @@
+---
+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
new file mode 100644
index 000000000000..92df88c7b0ea
--- /dev/null
+++ b/test/core/Inputs/code-model-attributes2.objtxt
@@ -0,0 +1,4 @@
+---
+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
new file mode 100644
index 000000000000..8f2ced14f10c
--- /dev/null
+++ b/test/core/Inputs/code-model-attributes3.objtxt
@@ -0,0 +1,4 @@
+---
+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
new file mode 100644
index 000000000000..160c9a00c3da
--- /dev/null
+++ b/test/core/Inputs/code-model-attributes4.objtxt
@@ -0,0 +1,4 @@
+---
+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
new file mode 100644
index 000000000000..99bdb54e09bb
--- /dev/null
+++ b/test/core/Inputs/code-model-attributes5.objtxt
@@ -0,0 +1,4 @@
+---
+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
new file mode 100644
index 000000000000..ea3436f9ee28
--- /dev/null
+++ b/test/core/Inputs/constants-coalesce.objtxt
@@ -0,0 +1,9 @@
+---
+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
new file mode 100644
index 000000000000..c8f10f414f87
--- /dev/null
+++ b/test/core/Inputs/constants-coalesce2.objtxt
@@ -0,0 +1,10 @@
+---
+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
new file mode 100644
index 000000000000..d2e6327cf20c
--- /dev/null
+++ b/test/core/Inputs/cstring-coalesce.objtxt
@@ -0,0 +1,6 @@
+---
+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
new file mode 100644
index 000000000000..76dedf7cf3bd
--- /dev/null
+++ b/test/core/Inputs/cstring-coalesce2.objtxt
@@ -0,0 +1,6 @@
+---
+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
new file mode 100644
index 000000000000..de3efe339aae
--- /dev/null
+++ b/test/core/Inputs/custom-section-coalesce.objtxt
@@ -0,0 +1,15 @@
+---
+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
new file mode 100644
index 000000000000..3e8356f0c7ee
--- /dev/null
+++ b/test/core/Inputs/custom-section-coalesce2.objtxt
@@ -0,0 +1,13 @@
+---
+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
new file mode 100644
index 000000000000..06a71485dcd5
--- /dev/null
+++ b/test/core/Inputs/dead-strip-attributes.objtxt
@@ -0,0 +1,4 @@
+---
+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
new file mode 100644
index 000000000000..3dd55c46cd92
--- /dev/null
+++ b/test/core/Inputs/dead-strip-attributes2.objtxt
@@ -0,0 +1,4 @@
+---
+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
new file mode 100644
index 000000000000..05cb81bbcf94
--- /dev/null
+++ b/test/core/Inputs/dead-strip-basic.objtxt
@@ -0,0 +1,9 @@
+---
+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
new file mode 100644
index 000000000000..6b0b01aef642
--- /dev/null
+++ b/test/core/Inputs/dead-strip-basic2.objtxt
@@ -0,0 +1,8 @@
+---
+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
new file mode 100644
index 000000000000..fbf2ba6d1da3
--- /dev/null
+++ b/test/core/Inputs/dead-strip-globals.objtxt
@@ -0,0 +1,9 @@
+---
+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
new file mode 100644
index 000000000000..a314bbe5ae41
--- /dev/null
+++ b/test/core/Inputs/dead-strip-globals2.objtxt
@@ -0,0 +1,8 @@
+---
+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
new file mode 100644
index 000000000000..2b99aa37848a
--- /dev/null
+++ b/test/core/Inputs/error-duplicate-absolutes.objtxt
@@ -0,0 +1,5 @@
+---
+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
new file mode 100644
index 000000000000..e1fa42a24a52
--- /dev/null
+++ b/test/core/Inputs/gnulinkonce-rearrange-resolve.objtxt
@@ -0,0 +1,26 @@
+---
+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
new file mode 100644
index 000000000000..02903a6b7bc5
--- /dev/null
+++ b/test/core/Inputs/gnulinkonce-remaining-undef.objtxt
@@ -0,0 +1,34 @@
+---
+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
new file mode 100644
index 000000000000..4991476c621c
--- /dev/null
+++ b/test/core/Inputs/gnulinkonce-remaining-undef2.objtxt
@@ -0,0 +1,4 @@
+---
+undefined-atoms:
+ - name: f3
+ can-be-null: never
diff --git a/test/core/Inputs/gnulinkonce-resolve.objtxt b/test/core/Inputs/gnulinkonce-resolve.objtxt
new file mode 100644
index 000000000000..f4beb37fee2a
--- /dev/null
+++ b/test/core/Inputs/gnulinkonce-resolve.objtxt
@@ -0,0 +1,25 @@
+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
new file mode 100644
index 000000000000..807f0d35802b
--- /dev/null
+++ b/test/core/Inputs/gnulinkonce-simple.objtxt
@@ -0,0 +1,4 @@
+---
+undefined-atoms:
+ - name: f1
+ can-be-null: never
diff --git a/test/core/Inputs/inline-coalesce.objtxt b/test/core/Inputs/inline-coalesce.objtxt
new file mode 100644
index 000000000000..2eddee647c14
--- /dev/null
+++ b/test/core/Inputs/inline-coalesce.objtxt
@@ -0,0 +1,6 @@
+---
+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
new file mode 100644
index 000000000000..2eddee647c14
--- /dev/null
+++ b/test/core/Inputs/inline-coalesce2.objtxt
@@ -0,0 +1,6 @@
+---
+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
new file mode 100644
index 000000000000..8a1dcdb9c37f
--- /dev/null
+++ b/test/core/Inputs/multiple-def-error.objtxt
@@ -0,0 +1,5 @@
+---
+defined-atoms:
+ - name: _foo
+ scope: global
+ type: data
diff --git a/test/core/Inputs/sectiongroup-deadstrip.objtxt b/test/core/Inputs/sectiongroup-deadstrip.objtxt
new file mode 100644
index 000000000000..392f7ee96898
--- /dev/null
+++ b/test/core/Inputs/sectiongroup-deadstrip.objtxt
@@ -0,0 +1,3 @@
+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
new file mode 100644
index 000000000000..a365d37b66b5
--- /dev/null
+++ b/test/core/Inputs/sectiongroup-gnulinkonce-error.objtxt
@@ -0,0 +1,26 @@
+---
+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
new file mode 100644
index 000000000000..bcefee646ef4
--- /dev/null
+++ b/test/core/Inputs/sectiongroup-rearrange-resolve.objtxt
@@ -0,0 +1,25 @@
+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
new file mode 100644
index 000000000000..07c7af5dc67c
--- /dev/null
+++ b/test/core/Inputs/sectiongroup-remaining-undef.objtxt
@@ -0,0 +1,34 @@
+---
+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
new file mode 100644
index 000000000000..4991476c621c
--- /dev/null
+++ b/test/core/Inputs/sectiongroup-remaining-undef2.objtxt
@@ -0,0 +1,4 @@
+---
+undefined-atoms:
+ - name: f3
+ can-be-null: never
diff --git a/test/core/Inputs/sectiongroup-resolve.objtxt b/test/core/Inputs/sectiongroup-resolve.objtxt
new file mode 100644
index 000000000000..a047ad33fe9c
--- /dev/null
+++ b/test/core/Inputs/sectiongroup-resolve.objtxt
@@ -0,0 +1,26 @@
+---
+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
new file mode 100644
index 000000000000..807f0d35802b
--- /dev/null
+++ b/test/core/Inputs/sectiongroup-simple.objtxt
@@ -0,0 +1,4 @@
+---
+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
new file mode 100644
index 000000000000..57cdfe662d4c
--- /dev/null
+++ b/test/core/Inputs/shared-library-coalesce.objtxt
@@ -0,0 +1,28 @@
+---
+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
new file mode 100644
index 000000000000..90db8fd1f446
--- /dev/null
+++ b/test/core/Inputs/tent-merge.objtxt
@@ -0,0 +1,6 @@
+---
+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
new file mode 100644
index 000000000000..f493f00bdf1a
--- /dev/null
+++ b/test/core/Inputs/undef-coalesce-error.objtxt
@@ -0,0 +1,8 @@
+---
+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
new file mode 100644
index 000000000000..88d736fc2111
--- /dev/null
+++ b/test/core/Inputs/undef-coalesce-error2.objtxt
@@ -0,0 +1,8 @@
+---
+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
new file mode 100644
index 000000000000..f493f00bdf1a
--- /dev/null
+++ b/test/core/Inputs/undef-coalesce.objtxt
@@ -0,0 +1,8 @@
+---
+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
new file mode 100644
index 000000000000..88d736fc2111
--- /dev/null
+++ b/test/core/Inputs/undef-coalesce2.objtxt
@@ -0,0 +1,8 @@
+---
+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
new file mode 100644
index 000000000000..c392731805cd
--- /dev/null
+++ b/test/core/Inputs/undef-fallback.objtxt
@@ -0,0 +1,7 @@
+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
new file mode 100644
index 000000000000..7a5e20fad097
--- /dev/null
+++ b/test/core/Inputs/undef-weak-coalesce.objtxt
@@ -0,0 +1,20 @@
+---
+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
new file mode 100644
index 000000000000..8a1dcdb9c37f
--- /dev/null
+++ b/test/core/Inputs/weak-coalesce.objtxt
@@ -0,0 +1,5 @@
+---
+defined-atoms:
+ - name: _foo
+ scope: global
+ type: data
diff --git a/test/core/Inputs/weak-coalesce2.objtxt b/test/core/Inputs/weak-coalesce2.objtxt
new file mode 100644
index 000000000000..1039b309f8a4
--- /dev/null
+++ b/test/core/Inputs/weak-coalesce2.objtxt
@@ -0,0 +1,6 @@
+---
+defined-atoms:
+ - name: _foo
+ merge: as-weak
+ scope: global
+ type: data
diff --git a/test/core/archive-basic.objtxt b/test/core/archive-basic.objtxt
index ec825c1a7e52..205e0a5034e5 100644
--- a/test/core/archive-basic.objtxt
+++ b/test/core/archive-basic.objtxt
@@ -1,4 +1,4 @@
-# RUN: lld -core %s | FileCheck %s
+# 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
@@ -13,27 +13,6 @@ defined-atoms:
undefined-atoms:
- name: bar
---- !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
...
# CHECK: name: foo
diff --git a/test/core/archive-chain.objtxt b/test/core/archive-chain.objtxt
index 0f80985ec112..35417f0bdb68 100644
--- a/test/core/archive-chain.objtxt
+++ b/test/core/archive-chain.objtxt
@@ -1,4 +1,4 @@
-# RUN: lld -core %s | FileCheck %s
+# 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.
@@ -11,53 +11,6 @@ defined-atoms:
undefined-atoms:
- name: bar1
-
---- !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
-
---- !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
...
# CHECK: name: foo
diff --git a/test/core/archive-tentdef-search.objtxt b/test/core/archive-tentdef-search.objtxt
index 3d26778e4986..230ab0bfd0de 100644
--- a/test/core/archive-tentdef-search.objtxt
+++ b/test/core/archive-tentdef-search.objtxt
@@ -1,5 +1,5 @@
-# RUN: lld -core %s | FileCheck -check-prefix=CHK1 %s
-# RUN: lld -core --commons-search-archives %s | FileCheck -check-prefix=CHK2 %s
+# 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
@@ -16,18 +16,6 @@ defined-atoms:
scope: global
type: zero-fill
merge: as-tentative
-
---- !archive
-members:
- - name: bar.o
- content: !native
- defined-atoms:
- - name: bar
- scope: global
- type: data
-
- - name: bar2
- type: data
...
# CHK1: name: foo
diff --git a/test/core/associates.objtxt b/test/core/associates.objtxt
index bf780693ab70..5c711c97f9fa 100644
--- a/test/core/associates.objtxt
+++ b/test/core/associates.objtxt
@@ -1,4 +1,4 @@
-# RUN: lld -core %s | FileCheck %s
+# RUN: lld -core %s %p/Inputs/associates.objtxt | FileCheck %s
---
defined-atoms:
@@ -9,15 +9,6 @@ defined-atoms:
- kind: associate
target: f2
- name: f2
----
-defined-atoms:
- - name: f1
- merge: as-weak
- scope: global
- references:
- - kind: associate
- target: f2
- - name: f2
...
# CHECK: defined-atoms:
diff --git a/test/core/auto-hide-coalesce.objtxt b/test/core/auto-hide-coalesce.objtxt
index ad82d5afc573..63c54951150e 100644
--- a/test/core/auto-hide-coalesce.objtxt
+++ b/test/core/auto-hide-coalesce.objtxt
@@ -1,4 +1,4 @@
-# RUN: lld -core %s | FileCheck %s
+# RUN: lld -core %s %p/Inputs/auto-hide-coalesce.objtxt | FileCheck %s
#
# Tests auto-hide bit during coalescing
@@ -25,27 +25,6 @@ defined-atoms:
scope: global
type: code
merge: as-addressed-weak
----
-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/code-model-attributes.objtxt b/test/core/code-model-attributes.objtxt
index 8c30e868567d..9bb4a01bd1a7 100644
--- a/test/core/code-model-attributes.objtxt
+++ b/test/core/code-model-attributes.objtxt
@@ -1,5 +1,8 @@
-# RUN: lld -core %s | FileCheck %s
-
+# 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
#
@@ -7,26 +10,6 @@
---
defined-atoms:
- name: _def
----
-defined-atoms:
- - name: _none
- code-model: none
----
-defined-atoms:
- - name: _mips_pic
- code-model: mips-pic
----
-defined-atoms:
- - name: _mips_micro
- code-model: mips-micro
----
-defined-atoms:
- - name: _mips_micro_pic
- code-model: mips-micro-pic
----
-defined-atoms:
- - name: _mips_16
- code-model: mips-16
...
# CHECK: name: _def
diff --git a/test/core/constants-coalesce.objtxt b/test/core/constants-coalesce.objtxt
index a82f68009087..1a9f1013e6ec 100644
--- a/test/core/constants-coalesce.objtxt
+++ b/test/core/constants-coalesce.objtxt
@@ -1,4 +1,5 @@
-# RUN: lld -core %s | FileCheck %s
+# 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
@@ -20,25 +21,6 @@ defined-atoms:
- ref-name: L1
type: constant
content: [ 01, 02 ]
----
-defined-atoms:
- - ref-name: L1
- type: constant
- content: [ 01, 02 ]
- - ref-name: L2
- type: constant
- merge: by-content
- content: [ 01, 02, 03, 04 ]
----
-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 ]
...
# CHECK-NOT: name:
diff --git a/test/core/cstring-coalesce.objtxt b/test/core/cstring-coalesce.objtxt
index 78986a08c640..4d32c00daf82 100644
--- a/test/core/cstring-coalesce.objtxt
+++ b/test/core/cstring-coalesce.objtxt
@@ -15,18 +15,6 @@ defined-atoms:
type: c-string
merge: by-content
content: [ 74, 68, 65, 72, 65, 00 ]
----
-defined-atoms:
- - ref-name: L2
- type: c-string
- merge: by-content
- content: [ 68, 65, 6c, 6c, 6f, 00 ]
----
-defined-atoms:
- - ref-name: L2
- type: c-string
- merge: by-content
- content: [ 74, 68, 65, 72, 65, 00 ]
...
# CHECK-NOT: name:
diff --git a/test/core/custom-section-coalesce.objtxt b/test/core/custom-section-coalesce.objtxt
index e9bada56938d..fcf04845a7dd 100644
--- a/test/core/custom-section-coalesce.objtxt
+++ b/test/core/custom-section-coalesce.objtxt
@@ -1,4 +1,5 @@
-# RUN: lld -core %s | FileCheck %s
+# 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
@@ -25,35 +26,6 @@ defined-atoms:
type: constant
merge: by-content
content: [ 01, 02, 03, 04 ]
-
----
-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
----
-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/dead-strip-attributes.objtxt b/test/core/dead-strip-attributes.objtxt
index dcb35a21e261..2a1c97627d2b 100644
--- a/test/core/dead-strip-attributes.objtxt
+++ b/test/core/dead-strip-attributes.objtxt
@@ -1,4 +1,5 @@
-# RUN: lld -core %s | FileCheck %s
+# 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
@@ -8,14 +9,6 @@
defined-atoms:
- name: _foo1
dead-strip: normal
----
-defined-atoms:
- - name: _foo2
- dead-strip: never
----
-defined-atoms:
- - name: _foo3
- dead-strip: always
...
diff --git a/test/core/dead-strip-basic.objtxt b/test/core/dead-strip-basic.objtxt
index 64cd2291c76b..1607ea9e5b89 100644
--- a/test/core/dead-strip-basic.objtxt
+++ b/test/core/dead-strip-basic.objtxt
@@ -1,5 +1,5 @@
-# RUN: lld -core --dead-strip %s | FileCheck -check-prefix=CHK1 %s
-# RUN: lld -core %s | FileCheck -check-prefix=CHK2 %s
+# 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
@@ -25,23 +25,6 @@ undefined-atoms:
- name: bar
- name: baz
----
-defined-atoms:
- - name: mydead2
- scope: global
- type: data
-
- - name: bar
- scope: global
- type: data
----
-defined-atoms:
- - name: baz
- scope: global
- type: code
-
- - name: mydead3
- type: code
...
diff --git a/test/core/dead-strip-globals.objtxt b/test/core/dead-strip-globals.objtxt
index 8feb235d07c3..e4b11b16f690 100644
--- a/test/core/dead-strip-globals.objtxt
+++ b/test/core/dead-strip-globals.objtxt
@@ -1,5 +1,5 @@
-# RUN: lld -core --dead-strip --keep-globals %s | FileCheck -check-prefix=CHK1 %s
-# RUN: lld -core --dead-strip %s | FileCheck -check-prefix=CHK2 %s
+# 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.
@@ -23,23 +23,6 @@ defined-atoms:
undefined-atoms:
- name: bar
- name: baz
----
-defined-atoms:
- - name: myglobal2
- scope: global
- type: data
-
- - name: bar
- scope: hidden
- type: data
----
-defined-atoms:
- - name: baz
- scope: hidden
- type: code
-
- - name: mydead
- type: code
...
diff --git a/test/core/error-duplicate-absolutes.objtxt b/test/core/error-duplicate-absolutes.objtxt
index 533297e59dcd..513a2f494485 100644
--- a/test/core/error-duplicate-absolutes.objtxt
+++ b/test/core/error-duplicate-absolutes.objtxt
@@ -1,4 +1,4 @@
-# RUN: not lld -core %s 2> %t.err
+# RUN: not lld -core %s %p/Inputs/error-duplicate-absolutes.objtxt 2> %t.err
# RUN: FileCheck %s < %t.err
#
@@ -12,11 +12,6 @@ absolute-atoms:
scope: global
undefined-atoms:
- name: undefatom
----
-absolute-atoms:
- - name: absatom
- value: 0
- scope: global
...
diff --git a/test/core/gnulinkonce-rearrange-resolve.objtxt b/test/core/gnulinkonce-rearrange-resolve.objtxt
index 2a6386a6935d..b3df078d2314 100644
--- a/test/core/gnulinkonce-rearrange-resolve.objtxt
+++ b/test/core/gnulinkonce-rearrange-resolve.objtxt
@@ -1,4 +1,4 @@
-# RUN: lld -core %s | FileCheck %s
+# 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
@@ -31,32 +31,6 @@ defined-atoms:
- name: d1
scope: global
type: data
----
-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:
diff --git a/test/core/gnulinkonce-remaining-undef.objtxt b/test/core/gnulinkonce-remaining-undef.objtxt
index 490608209ba9..5fe0ab55b5c0 100644
--- a/test/core/gnulinkonce-remaining-undef.objtxt
+++ b/test/core/gnulinkonce-remaining-undef.objtxt
@@ -1,4 +1,5 @@
-# RUN: lld -core %s | FileCheck %s
+# 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
@@ -33,44 +34,6 @@ defined-atoms:
target: g1
- kind: group-child
target: d1
----
-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
----
-undefined-atoms:
- - name: f3
- can-be-null: never
...
#CHECK: - name: anotherfunction
diff --git a/test/core/gnulinkonce-resolve.objtxt b/test/core/gnulinkonce-resolve.objtxt
index 817e9cfdd4e0..e926c39bd0e1 100644
--- a/test/core/gnulinkonce-resolve.objtxt
+++ b/test/core/gnulinkonce-resolve.objtxt
@@ -1,4 +1,4 @@
-# RUN: lld -core %s | FileCheck %s
+# 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
@@ -31,32 +31,6 @@ defined-atoms:
target: g1
- kind: group-child
target: d1
----
-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:
diff --git a/test/core/gnulinkonce-simple.objtxt b/test/core/gnulinkonce-simple.objtxt
index da325d48c366..0576e5f75d7f 100644
--- a/test/core/gnulinkonce-simple.objtxt
+++ b/test/core/gnulinkonce-simple.objtxt
@@ -1,4 +1,4 @@
-# RUN: lld -core %s | FileCheck %s
+# 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
@@ -37,10 +37,6 @@ defined-atoms:
- name: anotherfunction
scope: global
type: data
----
-undefined-atoms:
- - name: f1
- can-be-null: never
...
#CHECK: defined-atoms:
diff --git a/test/core/inline-coalesce.objtxt b/test/core/inline-coalesce.objtxt
index 6df9d0e7a49a..5ddc9b2624b5 100644
--- a/test/core/inline-coalesce.objtxt
+++ b/test/core/inline-coalesce.objtxt
@@ -1,4 +1,4 @@
-# RUN: lld -core %s | FileCheck %s
+# 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
@@ -10,18 +10,6 @@ defined-atoms:
scope: global
type: code
merge: as-weak
----
-defined-atoms:
- - name: _inlineFunc
- scope: global
- type: code
- merge: as-weak
----
-defined-atoms:
- - name: _inlineFunc
- scope: global
- type: code
- merge: as-weak
...
diff --git a/test/core/multiple-def-error.objtxt b/test/core/multiple-def-error.objtxt
index 7c7732c15fd9..5765814e53ee 100644
--- a/test/core/multiple-def-error.objtxt
+++ b/test/core/multiple-def-error.objtxt
@@ -1,4 +1,4 @@
-# RUN: not lld -core %s 2>&1 | FileCheck %s
+# RUN: not lld -core %s %p/Inputs/multiple-def-error.objtxt 2>&1 | FileCheck %s
#
# Test that multiple definitions cause an error
@@ -11,9 +11,4 @@ defined-atoms:
- name: _foo
scope: global
type: data
----
-defined-atoms:
- - name: _foo
- scope: global
- type: data
...
diff --git a/test/core/sectiongroup-deadstrip.objtxt b/test/core/sectiongroup-deadstrip.objtxt
index 8606c52d62e1..5055c6e06b69 100644
--- a/test/core/sectiongroup-deadstrip.objtxt
+++ b/test/core/sectiongroup-deadstrip.objtxt
@@ -1,6 +1,6 @@
# 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 | FileCheck %s
+# 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
@@ -45,10 +45,6 @@ defined-atoms:
- name: anotherfunction
scope: global
type: data
----
-undefined-atoms:
- - name: f1
- can-be-null: never
...
#CHECK: defined-atoms:
diff --git a/test/core/sectiongroup-gnulinkonce-error.objtxt b/test/core/sectiongroup-gnulinkonce-error.objtxt
index 47598957f8df..1b8617067839 100644
--- a/test/core/sectiongroup-gnulinkonce-error.objtxt
+++ b/test/core/sectiongroup-gnulinkonce-error.objtxt
@@ -1,4 +1,4 @@
-# RUN: not lld -core %s 2>&1 | FileCheck %s
+# 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
@@ -31,32 +31,6 @@ defined-atoms:
target: g1
- kind: group-child
target: d1
----
-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: SymbolTable: error while merging g1
diff --git a/test/core/sectiongroup-rearrange-resolve.objtxt b/test/core/sectiongroup-rearrange-resolve.objtxt
index 7f5d2603775b..f191113718df 100644
--- a/test/core/sectiongroup-rearrange-resolve.objtxt
+++ b/test/core/sectiongroup-rearrange-resolve.objtxt
@@ -1,4 +1,4 @@
-# RUN: lld -core %s | FileCheck %s
+# 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
@@ -31,32 +31,6 @@ defined-atoms:
- name: d1
scope: global
type: data
----
-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:
diff --git a/test/core/sectiongroup-remaining-undef.objtxt b/test/core/sectiongroup-remaining-undef.objtxt
index 7d889b8a4931..0a292040a354 100644
--- a/test/core/sectiongroup-remaining-undef.objtxt
+++ b/test/core/sectiongroup-remaining-undef.objtxt
@@ -1,4 +1,4 @@
-# RUN: lld -core %s | FileCheck %s
+# 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
@@ -33,44 +33,6 @@ defined-atoms:
target: g1
- kind: group-child
target: d1
----
-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
----
-undefined-atoms:
- - name: f3
- can-be-null: never
...
#CHECK: - name: anotherfunction
diff --git a/test/core/sectiongroup-resolve.objtxt b/test/core/sectiongroup-resolve.objtxt
index 2d481b1818b2..52197dbb4e91 100644
--- a/test/core/sectiongroup-resolve.objtxt
+++ b/test/core/sectiongroup-resolve.objtxt
@@ -31,32 +31,6 @@ defined-atoms:
target: g1
- kind: group-child
target: d1
----
-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:
diff --git a/test/core/sectiongroup-simple.objtxt b/test/core/sectiongroup-simple.objtxt
index 9f0ff9581c1d..d81b1a1b313c 100644
--- a/test/core/sectiongroup-simple.objtxt
+++ b/test/core/sectiongroup-simple.objtxt
@@ -37,10 +37,6 @@ defined-atoms:
- name: anotherfunction
scope: global
type: data
----
-undefined-atoms:
- - name: f1
- can-be-null: never
...
#CHECK: defined-atoms:
diff --git a/test/core/shared-library-coalesce.objtxt b/test/core/shared-library-coalesce.objtxt
index 51ff93e87a88..1cd25d18f881 100644
--- a/test/core/shared-library-coalesce.objtxt
+++ b/test/core/shared-library-coalesce.objtxt
@@ -1,4 +1,4 @@
-# RUN: lld -core %s | FileCheck %s
+# RUN: lld -core %s %p/Inputs/shared-library-coalesce.objtxt | FileCheck %s
#
# Test that shared library symbols preserve their attributes and merge properly
@@ -33,35 +33,6 @@ shared-library-atoms:
- name: mismatchload2
load-name: libb.so
----
-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
-
...
# CHECK: name: foo1
diff --git a/test/core/tent-merge.objtxt b/test/core/tent-merge.objtxt
index 8ad46d40ae18..8997be2833b1 100644
--- a/test/core/tent-merge.objtxt
+++ b/test/core/tent-merge.objtxt
@@ -1,4 +1,4 @@
-# RUN: lld -core %s | FileCheck %s
+# RUN: lld -core %s %p/Inputs/tent-merge.objtxt | FileCheck %s
#
# Test that a tentative definition and a regular global are merged into
@@ -12,12 +12,6 @@ defined-atoms:
scope: global
type: zero-fill
size: 4
----
-defined-atoms:
- - name: _foo
- scope: global
- type: data
- content: [ 00, 00, 00, 00 ]
...
diff --git a/test/core/undef-coalesce-error.objtxt b/test/core/undef-coalesce-error.objtxt
index a0485befd288..f0ad8d8555ab 100644
--- a/test/core/undef-coalesce-error.objtxt
+++ b/test/core/undef-coalesce-error.objtxt
@@ -1,6 +1,6 @@
-# RUN: not lld -core --undefines-are-errors %s 2> %t.err
+# 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 | FileCheck %s
+# 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
@@ -15,22 +15,6 @@ defined-atoms:
undefined-atoms:
- name: malloc
- name: free
----
-defined-atoms:
- - name: bar
- type: code
-
-undefined-atoms:
- - name: malloc
- - name: myfunc
----
-defined-atoms:
- - name: myfunc
- scope: global
- type: code
-
-undefined-atoms:
- - name: free
...
# CHECKERR: free
diff --git a/test/core/undef-coalesce.objtxt b/test/core/undef-coalesce.objtxt
index 822ed5acf191..b0ea2b928977 100644
--- a/test/core/undef-coalesce.objtxt
+++ b/test/core/undef-coalesce.objtxt
@@ -1,4 +1,4 @@
-# RUN: lld -core %s | FileCheck %s
+# 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
@@ -13,22 +13,6 @@ defined-atoms:
undefined-atoms:
- name: malloc
- name: free
----
-defined-atoms:
- - name: bar
- type: code
-
-undefined-atoms:
- - name: malloc
- - name: myfunc
----
-defined-atoms:
- - name: myfunc
- scope: global
- type: code
-
-undefined-atoms:
- - name: free
...
# CHECK: defined-atoms:
diff --git a/test/core/undef-fallback.objtxt b/test/core/undef-fallback.objtxt
index 8abaa93c8e8d..aef7b6d7c26f 100644
--- a/test/core/undef-fallback.objtxt
+++ b/test/core/undef-fallback.objtxt
@@ -1,4 +1,4 @@
-# RUN: lld -core %s | FileCheck %s
+# 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.
@@ -15,14 +15,6 @@ undefined-atoms:
- name: undef2
fallback:
name: fallback2
----
-defined-atoms:
- - name: fallback1
-
-undefined-atoms:
- - name: def1
- fallback:
- name: fallback3
...
# CHECK: defined-atoms:
diff --git a/test/core/undef-weak-coalesce.objtxt b/test/core/undef-weak-coalesce.objtxt
index 97e0fd28500d..d46a05cb95cf 100644
--- a/test/core/undef-weak-coalesce.objtxt
+++ b/test/core/undef-weak-coalesce.objtxt
@@ -1,4 +1,4 @@
-# RUN: lld -core %s | FileCheck %s
+# RUN: lld -core %s %p/Inputs/undef-weak-coalesce.objtxt| FileCheck %s
#
# Test that undefined symbols preserve their attributes and merge properly
@@ -30,26 +30,6 @@ undefined-atoms:
can-be-null: at-runtime
- name: bar9
can-be-null: at-buildtime
----
-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
...
# CHECK: - name: regular_func
diff --git a/test/core/weak-coalesce.objtxt b/test/core/weak-coalesce.objtxt
index 550c10cfa468..e92aedeb4f15 100644
--- a/test/core/weak-coalesce.objtxt
+++ b/test/core/weak-coalesce.objtxt
@@ -1,20 +1,6 @@
-# RUN: lld -core %s | FileCheck %s
+# RUN: lld -core %s %p/Inputs/weak-coalesce.objtxt \
+# RUN: %p/Inputs/weak-coalesce2.objtxt | FileCheck %s
-#
-# Test that weak definitions are coalesced away in favor of a regular definition
-#
-
----
-defined-atoms:
- - name: _foo
- merge: as-weak
- scope: global
- type: data
----
-defined-atoms:
- - name: _foo
- scope: global
- type: data
---
defined-atoms:
- name: _foo
diff --git a/test/darwin/Inputs/native-and-mach-o.objtxt b/test/darwin/Inputs/native-and-mach-o.objtxt
new file mode 100644
index 000000000000..58124eb83321
--- /dev/null
+++ b/test/darwin/Inputs/native-and-mach-o.objtxt
@@ -0,0 +1,17 @@
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS ]
+ address: 0
+ content: [ 0xC3 ]
+global-symbols:
+ - name: _foo
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ desc: [ ]
+ value: 0
diff --git a/test/darwin/Inputs/native-and-mach-o2.objtxt b/test/darwin/Inputs/native-and-mach-o2.objtxt
new file mode 100644
index 000000000000..344c9bc0b0d2
--- /dev/null
+++ b/test/darwin/Inputs/native-and-mach-o2.objtxt
@@ -0,0 +1,19 @@
+--- !mach-o
+arch: x86_64
+file-type: MH_DYLIB
+flags: [ ]
+install-name: /usr/lib/libSystem.B.dylib
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x55 ]
+
+global-symbols:
+ - name: dyld_stub_binder
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
diff --git a/test/darwin/native-and-mach-o.objtxt b/test/darwin/native-and-mach-o.objtxt
index 20f2d0b96207..1dee76d6d8cd 100644
--- a/test/darwin/native-and-mach-o.objtxt
+++ b/test/darwin/native-and-mach-o.objtxt
@@ -1,4 +1,6 @@
-# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t && \
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s \
+# RUN: %p/Inputs/native-and-mach-o.objtxt \
+# RUN: %p/Inputs/native-and-mach-o2.objtxt -o %t && \
# RUN: llvm-nm %t | FileCheck %s
#
# Test a mix of atoms and mach-o both encoded in yaml
@@ -19,46 +21,6 @@ defined-atoms:
undefined-atoms:
- name: _foo
-
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS ]
- address: 0
- content: [ 0xC3 ]
-global-symbols:
- - name: _foo
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ ]
- value: 0
-
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-flags: [ ]
-install-name: /usr/lib/libSystem.B.dylib
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55 ]
-
-global-symbols:
- - name: dyld_stub_binder
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-
-
...
# CHECK: {{[0-9a-f]+}} T _foo
diff --git a/test/elf/AArch64/defsym.test b/test/elf/AArch64/defsym.test
deleted file mode 100644
index 8bf492d4a38a..000000000000
--- a/test/elf/AArch64/defsym.test
+++ /dev/null
@@ -1,22 +0,0 @@
-RUN: lld -flavor 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/elf/AArch64/dontignorezerosize-sections.test b/test/elf/AArch64/dontignorezerosize-sections.test
deleted file mode 100644
index ac593abcc368..000000000000
--- a/test/elf/AArch64/dontignorezerosize-sections.test
+++ /dev/null
@@ -1,9 +0,0 @@
-# This tests that lld is not ignoring zero sized sections
-RUN: lld -flavor 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/elf/AArch64/dynlib-nointerp-section.test b/test/elf/AArch64/dynlib-nointerp-section.test
deleted file mode 100644
index 9365b4d5b3e9..000000000000
--- a/test/elf/AArch64/dynlib-nointerp-section.test
+++ /dev/null
@@ -1,5 +0,0 @@
-RUN: lld -flavor 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/elf/AArch64/initfini.test b/test/elf/AArch64/initfini.test
deleted file mode 100644
index 887e44ea105b..000000000000
--- a/test/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 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/elf/AArch64/rel-abs32-overflow.test b/test/elf/AArch64/rel-abs32-overflow.test
deleted file mode 100644
index e32fce173c51..000000000000
--- a/test/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 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/elf/AArch64/rel-abs32.test b/test/elf/AArch64/rel-abs32.test
deleted file mode 100644
index edd7b69e428d..000000000000
--- a/test/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 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/elf/AArch64/rel-abs64.test b/test/elf/AArch64/rel-abs64.test
deleted file mode 100644
index c125e3f2450d..000000000000
--- a/test/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 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/elf/AArch64/rel-bad.test b/test/elf/AArch64/rel-bad.test
deleted file mode 100644
index 6b9e831146f3..000000000000
--- a/test/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 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/elf/ARM/arm-symbols.test b/test/elf/ARM/arm-symbols.test
deleted file mode 100644
index b99960697679..000000000000
--- a/test/elf/ARM/arm-symbols.test
+++ /dev/null
@@ -1,52 +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 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
- Content: ''
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
-...
diff --git a/test/elf/ARM/defsym.test b/test/elf/ARM/defsym.test
deleted file mode 100644
index 0cd1736d924e..000000000000
--- a/test/elf/ARM/defsym.test
+++ /dev/null
@@ -1,51 +0,0 @@
-# Check that defined symbols are present in the generated executable
-
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor 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
- Content: ''
-Symbols:
- Global:
- - Name: fn
- Type: STT_FUNC
- Section: .text
-...
diff --git a/test/elf/ARM/entry-point.test b/test/elf/ARM/entry-point.test
deleted file mode 100644
index d168bb6463c6..000000000000
--- a/test/elf/ARM/entry-point.test
+++ /dev/null
@@ -1,77 +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 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 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
-
-# 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
- Content: ''
-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
- Content: ''
-Symbols:
- Global:
- - Name: _start
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
-...
diff --git a/test/elf/ARM/missing-symbol.test b/test/elf/ARM/missing-symbol.test
deleted file mode 100644
index f9b3e26ea1a3..000000000000
--- a/test/elf/ARM/missing-symbol.test
+++ /dev/null
@@ -1,39 +0,0 @@
-# Check that _MISSING_SYMBOL_ symbol is not resolved
-
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor 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
- Content: ''
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: _MISSING_SYMBOL_
-...
diff --git a/test/elf/ARM/rel-abs32.test b/test/elf/ARM/rel-abs32.test
deleted file mode 100644
index 57d323100feb..000000000000
--- a/test/elf/ARM/rel-abs32.test
+++ /dev/null
@@ -1,59 +0,0 @@
-# Check handling of R_ARM_ABS32 relocation.
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor 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
- Content: ''
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Size: 0x000000000000001C
- - Name: data
- Type: STT_OBJECT
- Section: .data
- Size: 0x0000000000000004
-...
diff --git a/test/elf/ARM/rel-arm-call.test b/test/elf/ARM/rel-arm-call.test
deleted file mode 100644
index 234b34eae92d..000000000000
--- a/test/elf/ARM/rel-arm-call.test
+++ /dev/null
@@ -1,60 +0,0 @@
-# Check handling of R_ARM_CALL relocation.
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor 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
-
----
-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
- Content: ''
-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/elf/ARM/rel-arm-jump24-veneer-b.test b/test/elf/ARM/rel-arm-jump24-veneer-b.test
deleted file mode 100644
index 4caeac083b8d..000000000000
--- a/test/elf/ARM/rel-arm-jump24-veneer-b.test
+++ /dev/null
@@ -1,101 +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 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=B-VENEER %s
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=B-ADDR %s
-
-# B-VENEER: Contents of section .text:
-# B-VENEER: 400074 010000ea
-# Call from main:
-# offset = 0x4 ^^
-# call site offset PC(arm) ___Z1fv_from_arm addr
-# 0x400074 + 0x4 + 0x8 = 0x400080
-#
-# Code of the veneer:
-# B-VENEER: {{[0-9a-f]+}} {{[0-9a-f]+}} 04f01fe5
-# B-VENEER: 400084 79004000
-# call addr = 0x400079 ^^
-# call addr _Z1fv addr Thumb mode
-# 0x400079 = 0x400078 | 0x1
-#
-# B-ADDR: SYMBOL TABLE:
-# B-ADDR: 00400080 l F .text {{[0-9a-f]+}} ___Z1fv_from_arm
-# B-ADDR: 00400074 g F .text {{[0-9a-f]+}} main
-# B-ADDR: 00400078 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
- Content: ''
-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
- Content: ''
-Symbols:
- Global:
- - Name: _Z1fv
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
-...
diff --git a/test/elf/ARM/rel-arm-jump24-veneer-bl.test b/test/elf/ARM/rel-arm-jump24-veneer-bl.test
deleted file mode 100644
index cd386dc5b1a4..000000000000
--- a/test/elf/ARM/rel-arm-jump24-veneer-bl.test
+++ /dev/null
@@ -1,100 +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 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=BL-VENEER %s
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=BL-ADDR %s
-
-# BL-VENEER: Contents of section .text:
-# BL-VENEER: 400084 0400000b
-# Call from main:
-# offset = 0x10 ^^
-# call site offset PC(arm) ___Z1fv_from_arm addr
-# 0x400084 + 0x10 + 0x8 = 0x40009c
-#
-# Code of the veneer:
-# BL-VENEER: 400094 {{[0-9a-f]+}} {{[0-9a-f]+}} {{[0-9a-f]+}} 95004000
-# call addr = 0x400095 ^^
-# call addr _Z1fv addr Thumb mode
-# 0x400095 = 0x400094 | 0x1
-#
-# BL-ADDR: SYMBOL TABLE:
-# BL-ADDR: 0040009c l F .text {{[0-9a-f]+}} ___Z1fv_from_arm
-# BL-ADDR: 00400074 g F .text {{[0-9a-f]+}} main
-# BL-ADDR: 00400094 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
- Content: ''
-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
- Content: ''
-Symbols:
- Global:
- - Name: _Z1fv
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
-...
diff --git a/test/elf/ARM/rel-arm-jump24.test b/test/elf/ARM/rel-arm-jump24.test
deleted file mode 100644
index 18eb8397d7b5..000000000000
--- a/test/elf/ARM/rel-arm-jump24.test
+++ /dev/null
@@ -1,58 +0,0 @@
-# Check handling of R_ARM_JUMP24 relocation.
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor 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
-
----
-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
- Content: ''
-Symbols:
- Global:
- - Name: _Z1fv
- Type: STT_FUNC
- Section: .text
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x000000000000001C
-...
diff --git a/test/elf/ARM/rel-arm-mov.test b/test/elf/ARM/rel-arm-mov.test
deleted file mode 100644
index e50aea4bb206..000000000000
--- a/test/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 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
- Content: 411C0000
-Symbols:
- Local:
- - Name: _ZL5data1
- Type: STT_OBJECT
- Section: .bss
- Size: 0x0000000000000004
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
-...
diff --git a/test/elf/ARM/rel-arm-prel31.test b/test/elf/ARM/rel-arm-prel31.test
deleted file mode 100644
index 1effc4eceb0e..000000000000
--- a/test/elf/ARM/rel-arm-prel31.test
+++ /dev/null
@@ -1,47 +0,0 @@
-# Check handling of R_ARM_PREL31 relocation.
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor 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 .ARM.extab:
-# CHECK: 4000a4 b1fffe7f
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400054 g F .text {{[0-9a-f]+}} __gxx_personality_v0
-
----
-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
-...
-
diff --git a/test/elf/ARM/rel-arm-thm-interwork.test b/test/elf/ARM/rel-arm-thm-interwork.test
deleted file mode 100644
index 8ee9186b48db..000000000000
--- a/test/elf/ARM/rel-arm-thm-interwork.test
+++ /dev/null
@@ -1,123 +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 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
- Content: ''
-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
- Content: ''
-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/elf/ARM/rel-rel32.test b/test/elf/ARM/rel-rel32.test
deleted file mode 100644
index 47779ac918e3..000000000000
--- a/test/elf/ARM/rel-rel32.test
+++ /dev/null
@@ -1,57 +0,0 @@
-# Check handling of R_ARM_REL32 relocation.
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor 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
- Content: ''
-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/elf/ARM/rel-thm-call.test b/test/elf/ARM/rel-thm-call.test
deleted file mode 100644
index b9bf8cefc0b8..000000000000
--- a/test/elf/ARM/rel-thm-call.test
+++ /dev/null
@@ -1,61 +0,0 @@
-# Check handling of R_ARM_THM_CALL relocation.
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor 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
-
----
-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
- Content: ''
-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/elf/ARM/rel-thm-jump11.test b/test/elf/ARM/rel-thm-jump11.test
deleted file mode 100644
index 4998c2b96c97..000000000000
--- a/test/elf/ARM/rel-thm-jump11.test
+++ /dev/null
@@ -1,141 +0,0 @@
-# Check handling of R_ARM_THM_JUMP11 relocation.
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor 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
-
----
-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
- Content: ''
- - Name: .comment
- Type: SHT_PROGBITS
- Flags: [ SHF_MERGE, SHF_STRINGS ]
- AddressAlign: 0x0000000000000001
- Content: 004743433A202863726F7373746F6F6C2D4E47206C696E61726F2D312E31332E312D342E392D323031342E3039202D204C696E61726F2047434320342E392D323031342E30392920342E392E32203230313430393034202870726572656C656173652900
- - Name: .note.GNU-stack
- Type: SHT_PROGBITS
- AddressAlign: 0x0000000000000001
- Content: ''
- - Name: .ARM.attributes
- Type: SHT_ARM_ATTRIBUTES
- AddressAlign: 0x0000000000000001
- Content: 4134000000616561626900012A00000005372D4100060A0741080109020A041204140115011703180119011A021B031C011E022201
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .text.startup
- Type: STT_SECTION
- Section: .text.startup
- - 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: .ARM.attributes
- Type: STT_SECTION
- Section: .ARM.attributes
- - 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/elf/ARM/rel-thm-jump24-veneer.test b/test/elf/ARM/rel-thm-jump24-veneer.test
deleted file mode 100644
index fffce44ca477..000000000000
--- a/test/elf/ARM/rel-thm-jump24-veneer.test
+++ /dev/null
@@ -1,100 +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 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=B-VENEER %s
-# RUN: llvm-objdump -s -t %t | FileCheck -check-prefix=B-ADDR %s
-
-# B-VENEER: Contents of section .text:
-# B-VENEER: 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:
-# B-VENEER: 400084 78470000 f9ffffea
-# offset = -0x1C ^^
-# call site offset PC(arm) _Z1fv
-# 0x400088 + (-0x1C) + 0x8 = 0x400074
-#
-# B-ADDR: SYMBOL TABLE:
-# B-ADDR: 00400084 l F .text {{[0-9a-f]+}} ___Z1fv_from_thumb
-# B-ADDR: 00400074 g F .text {{[0-9a-f]+}} _Z1fv
-# B-ADDR: 00400080 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
- Content: ''
-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
- Content: ''
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: _Z1fv
-...
diff --git a/test/elf/ARM/rel-thm-jump24.test b/test/elf/ARM/rel-thm-jump24.test
deleted file mode 100644
index 6c9b63447c9d..000000000000
--- a/test/elf/ARM/rel-thm-jump24.test
+++ /dev/null
@@ -1,59 +0,0 @@
-# Check handling of R_ARM_THM_JUMP24 relocation.
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor 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
-
----
-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
- Content: ''
-Symbols:
- Global:
- - Name: _Z1fv
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000011
-...
diff --git a/test/elf/ARM/rel-thm-mov.test b/test/elf/ARM/rel-thm-mov.test
deleted file mode 100644
index 25edc4cda4b9..000000000000
--- a/test/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 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
- Content: 411C0000
-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/elf/ARM/rel-tls-ie32.test b/test/elf/ARM/rel-tls-ie32.test
deleted file mode 100644
index 7b65c2f194c7..000000000000
--- a/test/elf/ARM/rel-tls-ie32.test
+++ /dev/null
@@ -1,109 +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 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 %s
-
-# CHECK: Contents of section .got:
-# CHECK: 401008 08000000 0c000000
-# tp_off(i) = 0x08 ^^ ^^ tp_off(j) = 0x0c
-# tp_off(i) + sizeof(i) = tp_off(j)
-# 0x08 + 0x04 = 0x0c
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400094 g F .text {{[0-9a-f]+}} main
-# CHECK: 00000000 g .tdata 00000004 i
-# sizeof(i) = 0x04 ^^
-# CHECK: 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
- Content: ''
-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
- Content: ''
- - 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/elf/ARM/rel-tls-le32.test b/test/elf/ARM/rel-tls-le32.test
deleted file mode 100644
index d0d3d5b6821a..000000000000
--- a/test/elf/ARM/rel-tls-le32.test
+++ /dev/null
@@ -1,61 +0,0 @@
-# Check handling of R_ARM_TLS_LE32 relocation.
-# RUN: yaml2obj -format=elf %s > %t-o.o
-# RUN: lld -flavor 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: 4000b4 {{[0-9a-f]+}} 08000000
-# tp_off = 0x000008 ^^
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400094 g F .text {{[0-9a-f]+}} main
-# CHECK: 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
- Content: ''
- - 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/elf/ARM/thm-symbols.test b/test/elf/ARM/thm-symbols.test
deleted file mode 100644
index c91505c98100..000000000000
--- a/test/elf/ARM/thm-symbols.test
+++ /dev/null
@@ -1,52 +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 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
- Content: ''
-Symbols:
- Global:
- - Name: main
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
-...
diff --git a/test/elf/ARM/undef-lazy-symbol.test b/test/elf/ARM/undef-lazy-symbol.test
deleted file mode 100644
index f32549e85be4..000000000000
--- a/test/elf/ARM/undef-lazy-symbol.test
+++ /dev/null
@@ -1,135 +0,0 @@
-# Check that _GLOBAL_OFFSET_TABLE_ symbol is resolved
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-got.o
-# RUN: lld -flavor 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_ (185)
-# 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 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 (188)
-# 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 (202)
-# 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 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_ (188)
-# 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 (210)
-# 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 (224)
-# 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
- Content: ''
-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
- Content: ''
-Symbols:
- Global:
- - Name: fn
- Type: STT_FUNC
- Section: .text
- Value: 0x0000000000000001
- - Name: __exidx_start
- - Name: __exidx_end
-...
diff --git a/test/elf/Hexagon/dynlib-data.test b/test/elf/Hexagon/dynlib-data.test
deleted file mode 100644
index f3260ba4847b..000000000000
--- a/test/elf/Hexagon/dynlib-data.test
+++ /dev/null
@@ -1,9 +0,0 @@
-RUN: lld -flavor 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/elf/Hexagon/dynlib-gotoff.test b/test/elf/Hexagon/dynlib-gotoff.test
deleted file mode 100644
index 752d3acd4c08..000000000000
--- a/test/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 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: 2^4
-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: 2^4
-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: 2^4
-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: 2^4
-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: 2^3
-CHECKGOTPLT: section-name: .got.plt
-CHECKGOTPLT: permissions: rw-
- - name: __got_c
-CHECKGOTPLT: type: got
-CHECKGOTPLT: content: [ 00, 00, 00, 00 ]
-CHECKGOTPLT: alignment: 2^2
-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: 2^2
-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: 2^2
-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: 2^2
-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: 2^2
-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/elf/Hexagon/dynlib-hash.test b/test/elf/Hexagon/dynlib-hash.test
deleted file mode 100644
index f93176492348..000000000000
--- a/test/elf/Hexagon/dynlib-hash.test
+++ /dev/null
@@ -1,9 +0,0 @@
-RUN: lld -flavor 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/elf/Hexagon/dynlib-rela.test b/test/elf/Hexagon/dynlib-rela.test
deleted file mode 100644
index 81617349e2f7..000000000000
--- a/test/elf/Hexagon/dynlib-rela.test
+++ /dev/null
@@ -1,9 +0,0 @@
-# Tests that the relocation sections have the right alignment.
-RUN: lld -flavor 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/elf/Hexagon/dynlib-syms.test b/test/elf/Hexagon/dynlib-syms.test
deleted file mode 100644
index e649230d9e90..000000000000
--- a/test/elf/Hexagon/dynlib-syms.test
+++ /dev/null
@@ -1,7 +0,0 @@
-RUN: lld -flavor 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/elf/Hexagon/dynlib.test b/test/elf/Hexagon/dynlib.test
deleted file mode 100644
index c5bf23fdf229..000000000000
--- a/test/elf/Hexagon/dynlib.test
+++ /dev/null
@@ -1,36 +0,0 @@
-RUN: lld -flavor 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/elf/Hexagon/hexagon-got-plt-order.test b/test/elf/Hexagon/hexagon-got-plt-order.test
deleted file mode 100644
index 7600ebe59fc5..000000000000
--- a/test/elf/Hexagon/hexagon-got-plt-order.test
+++ /dev/null
@@ -1,5 +0,0 @@
-RUN: lld -flavor 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/elf/Hexagon/hexagon-plt-setup.test b/test/elf/Hexagon/hexagon-plt-setup.test
deleted file mode 100644
index 15c4e22ed9c5..000000000000
--- a/test/elf/Hexagon/hexagon-plt-setup.test
+++ /dev/null
@@ -1,12 +0,0 @@
-RUN: lld -flavor 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/elf/Hexagon/maxalignment.test b/test/elf/Hexagon/maxalignment.test
deleted file mode 100644
index cac1c200734f..000000000000
--- a/test/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 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/elf/Hexagon/rela-order.test b/test/elf/Hexagon/rela-order.test
deleted file mode 100644
index 925a82c29290..000000000000
--- a/test/elf/Hexagon/rela-order.test
+++ /dev/null
@@ -1,9 +0,0 @@
-RUN: lld -flavor 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/elf/Hexagon/sda-base.test b/test/elf/Hexagon/sda-base.test
deleted file mode 100644
index 0bab92abf685..000000000000
--- a/test/elf/Hexagon/sda-base.test
+++ /dev/null
@@ -1,4 +0,0 @@
-RUN: lld -flavor 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/elf/Hexagon/zerofillquick-sdata.test b/test/elf/Hexagon/zerofillquick-sdata.test
deleted file mode 100644
index 5488e19f5c44..000000000000
--- a/test/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 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/elf/Inputs/consecutive-weak-defs.o.yaml b/test/elf/Inputs/consecutive-weak-defs.o.yaml
deleted file mode 100644
index 144c2426bae1..000000000000
--- a/test/elf/Inputs/consecutive-weak-defs.o.yaml
+++ /dev/null
@@ -1,66 +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
- Content: ''
-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/elf/Inputs/init_array.x86-64 b/test/elf/Inputs/init_array.x86-64
deleted file mode 100644
index 2425c227fd42..000000000000
--- a/test/elf/Inputs/init_array.x86-64
+++ /dev/null
Binary files differ
diff --git a/test/elf/Inputs/main-with-global-def.o.yaml b/test/elf/Inputs/main-with-global-def.o.yaml
deleted file mode 100644
index 55029614e1e8..000000000000
--- a/test/elf/Inputs/main-with-global-def.o.yaml
+++ /dev/null
@@ -1,56 +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
- Content: ''
-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/elf/Inputs/undef2-so.o.yaml b/test/elf/Inputs/undef2-so.o.yaml
deleted file mode 100644
index 9ecf374ced11..000000000000
--- a/test/elf/Inputs/undef2-so.o.yaml
+++ /dev/null
@@ -1,50 +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
- Content: ''
-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/elf/Mips/base-address-64.test b/test/elf/Mips/base-address-64.test
deleted file mode 100644
index 07110e7f918f..000000000000
--- a/test/elf/Mips/base-address-64.test
+++ /dev/null
@@ -1,78 +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 gnu -target mips64el --noinhibit-exec -o %t.exe %t.o
-# RUN: llvm-readobj -dynamic-table -program-headers %t.exe | FileCheck %s
-
-# CHECK: DynamicSection [ (13 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: 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/elf/Mips/base-address.test b/test/elf/Mips/base-address.test
deleted file mode 100644
index f55091f84c33..000000000000
--- a/test/elf/Mips/base-address.test
+++ /dev/null
@@ -1,109 +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 gnu -target mipsel --noinhibit-exec -o %t.exe %t.o
-# RUN: llvm-readobj -dynamic-table -program-headers %t.exe | FileCheck %s
-
-# 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 1 (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 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
- - Name: .reginfo
- Type: SHT_MIPS_REGINFO
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x01
- Size: 0x18
- - Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x08
- Content: '000020010101000100000000000000000000000000000000'
-Symbols:
- Local:
- - Name: .text
- Type: STT_SECTION
- Section: .text
- - Name: .data
- Type: STT_SECTION
- Section: .data
- - Name: .bss
- Type: STT_SECTION
- Section: .bss
- - Name: .reginfo
- Type: STT_SECTION
- Section: .reginfo
- - Name: .MIPS.abiflags
- Type: STT_SECTION
- Section: .MIPS.abiflags
- Global:
- - Name: main
- Section: .text
diff --git a/test/elf/Mips/ctors-order.test b/test/elf/Mips/ctors-order.test
deleted file mode 100644
index 344dcd5fc516..000000000000
--- a/test/elf/Mips/ctors-order.test
+++ /dev/null
@@ -1,163 +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 gnu -target mipsel -shared --output-filetype=yaml \
-# RUN: %t-crtbeginS.o %t-obj.o %t-crtendS.o | FileCheck %s
-# RUN: lld -flavor 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# CHECK-NEXT: section-choice: custom-required
-# CHECK-NEXT: section-name: .ctors.2
-# CHECK-NEXT: - ref-name: L003
-# CHECK-NEXT: type: data
-# CHECK-NEXT: alignment: 2^2
-# 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: 2^2
-# 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_HI16
- - Offset: 0x04
- Symbol: .ctors
- Type: R_MIPS_LO16
- - Offset: 0x08
- Symbol: .ctors
- Type: R_MIPS_HI16
- - 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/elf/Mips/dt-textrel-64.test b/test/elf/Mips/dt-textrel-64.test
deleted file mode 100644
index 32cc99e54b2f..000000000000
--- a/test/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 gnu -target mips64el -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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/elf/Mips/dt-textrel.test b/test/elf/Mips/dt-textrel.test
deleted file mode 100644
index ca854dff8e58..000000000000
--- a/test/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 gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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/elf/Mips/dynlib-dynamic.test b/test/elf/Mips/dynlib-dynamic.test
deleted file mode 100644
index 54afdec263a6..000000000000
--- a/test/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 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/elf/Mips/dynlib-dynsym-micro.test b/test/elf/Mips/dynlib-dynsym-micro.test
deleted file mode 100644
index 4d75945af7b0..000000000000
--- a/test/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 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 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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/elf/Mips/dynlib-dynsym.test b/test/elf/Mips/dynlib-dynsym.test
deleted file mode 100644
index d480c3cbbe41..000000000000
--- a/test/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 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 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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/elf/Mips/dynlib-fileheader-64.test b/test/elf/Mips/dynlib-fileheader-64.test
deleted file mode 100644
index 206f4fa7794d..000000000000
--- a/test/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 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: 0x170
-# CHECK: ProgramHeaderOffset: 0x40
-# CHECK: SectionHeaderOffset: 0x2140
-# 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: 4
-# CHECK: SectionHeaderEntrySize: 64
-# CHECK: SectionHeaderCount: 11
-# CHECK: StringTableSectionIndex: 8
-# 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/elf/Mips/dynlib-fileheader-micro-64.test b/test/elf/Mips/dynlib-fileheader-micro-64.test
deleted file mode 100644
index c03a951671ea..000000000000
--- a/test/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 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: 0x170
-# CHECK-NEXT: ProgramHeaderOffset: 0x40
-# CHECK-NEXT: SectionHeaderOffset: 0x2140
-# 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: 4
-# CHECK-NEXT: SectionHeaderEntrySize: 64
-# CHECK-NEXT: SectionHeaderCount: 11
-# CHECK-NEXT: StringTableSectionIndex: 8
-# 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/elf/Mips/dynlib-fileheader-micro.test b/test/elf/Mips/dynlib-fileheader-micro.test
deleted file mode 100644
index 139b3aa626c9..000000000000
--- a/test/elf/Mips/dynlib-fileheader-micro.test
+++ /dev/null
@@ -1,82 +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 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: 0x100
-# CHECK-NEXT: ProgramHeaderOffset: 0x34
-# CHECK-NEXT: SectionHeaderOffset: 0x2100
-# 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: 4
-# CHECK-NEXT: SectionHeaderEntrySize: 40
-# CHECK-NEXT: SectionHeaderCount: 11
-# CHECK-NEXT: StringTableSectionIndex: 8
-# 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: .reginfo
- Type: SHT_MIPS_REGINFO
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x01
- Size: 0x18
- - Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x08
- Size: 0x18
-
-Symbols:
- Global:
- - Name: glob
- Section: .text
- Other: [ STO_MIPS_MICROMIPS ]
diff --git a/test/elf/Mips/dynlib-fileheader.test b/test/elf/Mips/dynlib-fileheader.test
deleted file mode 100644
index 5dd9d6a64a71..000000000000
--- a/test/elf/Mips/dynlib-fileheader.test
+++ /dev/null
@@ -1,80 +0,0 @@
-# Check ELF Header for shared library.
-
-# Build shared library
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor 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: 0x100
-# CHECK: ProgramHeaderOffset: 0x34
-# CHECK: SectionHeaderOffset: 0x2100
-# 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: 4
-# CHECK: SectionHeaderEntrySize: 40
-# CHECK: SectionHeaderCount: 11
-# CHECK: StringTableSectionIndex: 8
-# 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: .reginfo
- Type: SHT_MIPS_REGINFO
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x01
- Size: 0x18
- - Name: .MIPS.abiflags
- Type: SHT_MIPS_ABIFLAGS
- Flags: [ SHF_ALLOC ]
- AddressAlign: 0x08
- Size: 0x18
-
-Symbols:
- Global:
- - Name: glob
- Section: .text
diff --git a/test/elf/Mips/dynsym-table-1.test b/test/elf/Mips/dynsym-table-1.test
deleted file mode 100644
index 43c48e730405..000000000000
--- a/test/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 gnu -target mipsel -shared -o %t-bar.so %t-bar.o
-# RUN: lld -flavor gnu -target mipsel -shared -o %t-foo.so %t-foo.o %t-bar.so
-# RUN: lld -flavor 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 0x401000
-# 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/elf/Mips/dynsym-table-2.test b/test/elf/Mips/dynsym-table-2.test
deleted file mode 100644
index 538aa758910e..000000000000
--- a/test/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 gnu -target mipsel -shared -o %t-bar.so %t-bar.o
-# RUN: lld -flavor 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 0x1000
-# 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/elf/Mips/e-flags-merge-1-64.test b/test/elf/Mips/e-flags-merge-1-64.test
deleted file mode 100644
index d5719539baaa..000000000000
--- a/test/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 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/elf/Mips/e-flags-merge-1.test b/test/elf/Mips/e-flags-merge-1.test
deleted file mode 100644
index 1f1d7aca6c41..000000000000
--- a/test/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 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 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/elf/Mips/e-flags-merge-10.test b/test/elf/Mips/e-flags-merge-10.test
deleted file mode 100644
index a0aa45d5f2c8..000000000000
--- a/test/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 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/elf/Mips/e-flags-merge-11.test b/test/elf/Mips/e-flags-merge-11.test
deleted file mode 100644
index b4c0039bd198..000000000000
--- a/test/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 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/elf/Mips/e-flags-merge-2-64.test b/test/elf/Mips/e-flags-merge-2-64.test
deleted file mode 100644
index a169e7ea1645..000000000000
--- a/test/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 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/elf/Mips/e-flags-merge-2.test b/test/elf/Mips/e-flags-merge-2.test
deleted file mode 100644
index 41d4a0b0c45e..000000000000
--- a/test/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 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/elf/Mips/e-flags-merge-3-64.test b/test/elf/Mips/e-flags-merge-3-64.test
deleted file mode 100644
index 54065a63fb94..000000000000
--- a/test/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 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 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 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 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/elf/Mips/e-flags-merge-3.test b/test/elf/Mips/e-flags-merge-3.test
deleted file mode 100644
index e2d9f6c2e2fc..000000000000
--- a/test/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 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 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 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 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/elf/Mips/e-flags-merge-4-64.test b/test/elf/Mips/e-flags-merge-4-64.test
deleted file mode 100644
index 9ffa61343711..000000000000
--- a/test/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 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/elf/Mips/e-flags-merge-4.test b/test/elf/Mips/e-flags-merge-4.test
deleted file mode 100644
index 096b04d676e9..000000000000
--- a/test/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 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/elf/Mips/e-flags-merge-5-64.test b/test/elf/Mips/e-flags-merge-5-64.test
deleted file mode 100644
index e629aedbc154..000000000000
--- a/test/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 gnu -target mips64el -shared -o %t.so \
-# RUN: %t-32.o %t-64.o 2>&1 | FileCheck %s
-
-# CHECK: Bitness is incompatible with that of the selected target
-
-# 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/elf/Mips/e-flags-merge-5.test b/test/elf/Mips/e-flags-merge-5.test
deleted file mode 100644
index 3b5b397ab780..000000000000
--- a/test/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 gnu -target mipsel -shared -o %t.so \
-# RUN: %t-32.o %t-64.o 2>&1 | FileCheck %s
-
-# CHECK: Bitness is incompatible with that of the selected target
-
-# 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/elf/Mips/e-flags-merge-6-64.test b/test/elf/Mips/e-flags-merge-6-64.test
deleted file mode 100644
index fbc32b7135b2..000000000000
--- a/test/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 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/elf/Mips/e-flags-merge-6.test b/test/elf/Mips/e-flags-merge-6.test
deleted file mode 100644
index 759c8b63c97d..000000000000
--- a/test/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 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/elf/Mips/e-flags-merge-7-64.test b/test/elf/Mips/e-flags-merge-7-64.test
deleted file mode 100644
index 07ed6bb54836..000000000000
--- a/test/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 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/elf/Mips/e-flags-merge-7.test b/test/elf/Mips/e-flags-merge-7.test
deleted file mode 100644
index 7e114ff968fe..000000000000
--- a/test/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 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/elf/Mips/e-flags-merge-8.test b/test/elf/Mips/e-flags-merge-8.test
deleted file mode 100644
index 57af77d70260..000000000000
--- a/test/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 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/elf/Mips/e-flags-merge-9.test b/test/elf/Mips/e-flags-merge-9.test
deleted file mode 100644
index dea32f07cb9e..000000000000
--- a/test/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 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/elf/Mips/entry-name.test b/test/elf/Mips/entry-name.test
deleted file mode 100644
index b10adc68bde8..000000000000
--- a/test/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 gnu -target mipsel --noinhibit-exec -o %t.exe %t.o
-# RUN: llvm-nm %t.exe | FileCheck %s
-
-# CHECK: U __start
-# CHECK: 00400108 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/elf/Mips/exe-dynamic.test b/test/elf/Mips/exe-dynamic.test
deleted file mode 100644
index 28d2b13fbce8..000000000000
--- a/test/elf/Mips/exe-dynamic.test
+++ /dev/null
@@ -1,108 +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 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 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 [ (18 entries)
-# CHECK: Tag Type Name/Value
-# CHECK-NEXT: 0x00000004 HASH 0x400104
-# CHECK-NEXT: 0x00000005 STRTAB 0x400138
-# CHECK-NEXT: 0x00000006 SYMTAB 0x400118
-# CHECK-NEXT: 0x0000000A STRSZ 28 (bytes)
-# CHECK-NEXT: 0x0000000B SYMENT 16 (bytes)
-# CHECK-NEXT: 0x00000002 PLTRELSZ 8 (bytes)
-# CHECK-NEXT: 0x70000032 MIPS_PLTGOT 0x402000
-# CHECK-NEXT: 0x00000014 PLTREL REL
-# CHECK-NEXT: 0x00000017 JMPREL 0x400154
-# CHECK-NEXT: 0x70000001 MIPS_RLD_VERSION 1
-# 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 0x401000
-# 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/elf/Mips/exe-dynsym-micro.test b/test/elf/Mips/exe-dynsym-micro.test
deleted file mode 100644
index e3b00277ef6a..000000000000
--- a/test/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 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 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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/elf/Mips/exe-dynsym.test b/test/elf/Mips/exe-dynsym.test
deleted file mode 100644
index a59916c4be4c..000000000000
--- a/test/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 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 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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/elf/Mips/exe-fileheader-64.test b/test/elf/Mips/exe-fileheader-64.test
deleted file mode 100644
index 63baff53e678..000000000000
--- a/test/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 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: 0x1200001A0
-# CHECK: ProgramHeaderOffset: 0x40
-# CHECK: SectionHeaderOffset: 0x1300
-# 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: 5
-# CHECK: SectionHeaderEntrySize: 64
-# CHECK: SectionHeaderCount: 11
-# CHECK: StringTableSectionIndex: 8
-# 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/elf/Mips/exe-fileheader-micro-64.test b/test/elf/Mips/exe-fileheader-micro-64.test
deleted file mode 100644
index 044c2f729f38..000000000000
--- a/test/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 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: 0x1200001A1
-# CHECK: ProgramHeaderOffset: 0x40
-# CHECK: SectionHeaderOffset: 0x1300
-# 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: 5
-# CHECK: SectionHeaderEntrySize: 64
-# CHECK: SectionHeaderCount: 11
-# CHECK: StringTableSectionIndex: 8
-# 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/elf/Mips/exe-fileheader-micro.test b/test/elf/Mips/exe-fileheader-micro.test
deleted file mode 100644
index 351f299b04cd..000000000000
--- a/test/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 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: 0
-# 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: 0x400109
-# CHECK-NEXT: ProgramHeaderOffset: 0x34
-# CHECK-NEXT: SectionHeaderOffset: 0x1268
-# 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: 5
-# CHECK-NEXT: SectionHeaderEntrySize: 40
-# CHECK-NEXT: SectionHeaderCount: 11
-# CHECK-NEXT: StringTableSectionIndex: 8
-# 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/elf/Mips/exe-fileheader.test b/test/elf/Mips/exe-fileheader.test
deleted file mode 100644
index ff0d38198c31..000000000000
--- a/test/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 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 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: 0x400190
-# CHECK: ProgramHeaderOffset: 0x34
-# CHECK: SectionHeaderOffset: 0x2280
-# CHECK: Flags [ (0x70001005)
-# CHECK: EF_MIPS_ABI_O32 (0x1000)
-# CHECK: EF_MIPS_ARCH_32R2 (0x70000000)
-# CHECK: EF_MIPS_CPIC (0x4)
-# CHECK: EF_MIPS_NOREORDER (0x1)
-# CHECK: ]
-# CHECK: HeaderSize: 52
-# CHECK: ProgramHeaderEntrySize: 32
-# CHECK: ProgramHeaderCount: 6
-# CHECK: SectionHeaderEntrySize: 40
-# CHECK: SectionHeaderCount: 14
-# CHECK: StringTableSectionIndex: 11
-# 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/elf/Mips/exe-got-micro.test b/test/elf/Mips/exe-got-micro.test
deleted file mode 100644
index d2d1588ab964..000000000000
--- a/test/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 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 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: 2^2
-# GOT: section-choice: custom-required
-# GOT: section-name: .got
-# GOT: permissions: rw-
-# GOT: - type: got
-# GOT: content: [ 00, 00, 00, 80 ]
-# GOT: alignment: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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/elf/Mips/exe-got.test b/test/elf/Mips/exe-got.test
deleted file mode 100644
index 7254c87530bc..000000000000
--- a/test/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 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 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: 2^2
-# GOT: section-choice: custom-required
-# GOT: section-name: .got
-# GOT: permissions: rw-
-# GOT: - type: got
-# GOT: content: [ 00, 00, 00, 80 ]
-# GOT: alignment: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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/elf/Mips/got-page-32.test b/test/elf/Mips/got-page-32.test
deleted file mode 100644
index 00376da78663..000000000000
--- a/test/elf/Mips/got-page-32.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 gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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: T0 (1)
-# GOT-NEXT: Value: 0x400154
-# GOT: Symbol {
-# GOT: Name: LT1 (4)
-# GOT-NEXT: Value: 0x40017C
-# GOT: Symbol {
-# GOT: Name: LT2 (8)
-# GOT-NEXT: Value: 0x400180
-# 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: 0x40017C
-# 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: ]
-# GOT-NEXT: Global entries [
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401014
-# 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@ (1)
-# GOT-NEXT: }
-# GOT-NEXT: Entry {
-# GOT-NEXT: Address: 0x401018
-# 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@ (4)
-# GOT-NEXT: }
-# GOT-NEXT: ]
-# GOT-NEXT: Number of TLS and multi-GOT entries: 0
-# GOT-NEXT: }
-
-# RAW: Contents of section .text:
-# RAW-NEXT: 400154 24800000 18800000 24800000 28800000 $.......$...(...
-# ^ = -32732 (T1)
-# ^ = -32744 (LT1)
-# ^ -32732 (T1)
-# ^ -32728 (T2)
-# RAW-NEXT: 400164 1c800000 20800000 00000000 00000000 .... ...........
-# ^ -32740 (PAGE)
-# ^ -32736 (PAGE)
-# ^ T1 OFST
-# ^ T2 OFST
-# RAW-NEXT: 400174 7c010000 80010000 00000000 00000000 |...............
-# ^ LT1 OFST
-# ^ LT2 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: 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/elf/Mips/got-page-64.test b/test/elf/Mips/got-page-64.test
deleted file mode 100644
index 21bece5d3242..000000000000
--- a/test/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 gnu -target mips64el -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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: 0x1200001F0
-# GOT: Symbol {
-# GOT: Name: LT1 (4)
-# GOT-NEXT: Value: 0x120000218
-# GOT: Symbol {
-# GOT: Name: LT2 (8)
-# GOT-NEXT: Value: 0x12000021C
-# 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: 0x120000218
-# 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: 1200001f0 38800000 20800000 38800000 40800000 8... ...8...@...
-# ^ = -32712 (T1)
-# ^ = -32736 (LT1)
-# ^ -32712 (T1)
-# ^ -32704 (T2)
-# RAW-NEXT: 120000200 28800000 30800000 00000000 00000000 (...0...........
-# ^ -32728 (PAGE)
-# ^ -32720 (PAGE)
-# ^ T1 OFST
-# ^ T2 OFST
-# RAW-NEXT: 120000210 18020000 1c020000 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/elf/Mips/got16-2.test b/test/elf/Mips/got16-2.test
deleted file mode 100644
index 6f576536c541..000000000000
--- a/test/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 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/elf/Mips/got16-micro.test b/test/elf/Mips/got16-micro.test
deleted file mode 100644
index 6b77613581ec..000000000000
--- a/test/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 gnu -target mipsel -shared --noinhibit-exec \
-# RUN: --output-filetype=yaml %t.o \
-# RUN: | FileCheck -check-prefix YAML %s
-# RUN: lld -flavor 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 2^4
-# 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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 00000000 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/elf/Mips/got16.test b/test/elf/Mips/got16.test
deleted file mode 100644
index 9090d3003c14..000000000000
--- a/test/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 gnu -target mipsel -shared --noinhibit-exec \
-# RUN: --output-filetype=yaml %t.o \
-# RUN: | FileCheck -check-prefix YAML %s
-# RUN: lld -flavor 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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: 2^2
-# 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/elf/Mips/gotsym.test b/test/elf/Mips/gotsym.test
deleted file mode 100644
index 4581901958aa..000000000000
--- a/test/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 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 g *ABS* 00000000 _GLOBAL_OFFSET_TABLE_
-# SHARED: 00008ff0 g *ABS* 00000000 _gp
-# SHARED: 00008ff0 g *ABS* 00000000 _gp_disp
-
-# RUN: lld -flavor 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 g *ABS* 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/elf/Mips/gp-sym-1-micro.test b/test/elf/Mips/gp-sym-1-micro.test
deleted file mode 100644
index 76274eaaa8ac..000000000000
--- a/test/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 gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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 (203)
-# 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/elf/Mips/gp-sym-1.test b/test/elf/Mips/gp-sym-1.test
deleted file mode 100644
index 6c2ffb62629d..000000000000
--- a/test/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 gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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 (203)
-# 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/elf/Mips/gp-sym-2.test b/test/elf/Mips/gp-sym-2.test
deleted file mode 100644
index 6b9e5a5e52d9..000000000000
--- a/test/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 gnu -target mipsel -shared -o %t-1.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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 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/elf/Mips/hilo16-1.test b/test/elf/Mips/hilo16-1.test
deleted file mode 100644
index c2863408c888..000000000000
--- a/test/elf/Mips/hilo16-1.test
+++ /dev/null
@@ -1,44 +0,0 @@
-# REQUIRES: mips
-
-# Check handling multiple HI16 relocation followed by a single LO16 relocation.
-#
-# RUN: llvm-mc -triple=mipsel -filetype=obj -o=%t-obj %s
-# RUN: lld -flavor 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: {{[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]+}}: 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]+}}: 55 01 08 85 lh $8, 341($8)
-
-# CHECK: SYMBOL TABLE:
-# CHECK: {{[0-9a-f]+}} g F .text 00000024 glob1
-# CHECK: {{[0-9a-f]+}} g F .text 00000004 glob2
-
- .global glob1
- .ent glob1
-glob1:
- lui $t0,%hi(glob2+0x1)
- lui $t0,%hi(glob2+(-0x1))
- lui $t0,%hi(glob2+0x1ff)
- lui $t0,%hi(glob2+(-0x1ff))
- lui $t0,%hi(glob2+0x1ffff)
- lui $t0,%hi(glob2+(-0x1ffff))
- lui $t0,%hi(glob2+0x1ffffff)
- lui $t0,%hi(glob2+(-0x1ffffff))
-
- lh $t0,%lo(glob2+(-0x1ffffff))($t0)
- .end glob1
-
- .global glob2
- .ent glob2
-glob2:
- nop
- .end glob2
diff --git a/test/elf/Mips/hilo16-2.test b/test/elf/Mips/hilo16-2.test
deleted file mode 100644
index 68cb26eec788..000000000000
--- a/test/elf/Mips/hilo16-2.test
+++ /dev/null
@@ -1,68 +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 -triple=mipsel -filetype=obj -o=%t-obj %s
-# RUN: lld -flavor 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: {{[0-9a-f]+}}: 40 00 08 3c lui $8, 64
-# CHECK-NEXT: {{[0-9a-f]+}}: 71 01 08 85 lh $8, 369($8)
-# CHECK-NEXT: {{[0-9a-f]+}}: 40 00 08 3c lui $8, 64
-# CHECK-NEXT: {{[0-9a-f]+}}: 6f 01 08 85 lh $8, 367($8)
-# CHECK-NEXT: {{[0-9a-f]+}}: 40 00 08 3c lui $8, 64
-# CHECK-NEXT: {{[0-9a-f]+}}: 6f 03 08 85 lh $8, 879($8)
-# CHECK-NEXT: {{[0-9a-f]+}}: 40 00 08 3c lui $8, 64
-# CHECK-NEXT: {{[0-9a-f]+}}: 71 ff 08 85 lh $8, -143($8)
-# CHECK-NEXT: {{[0-9a-f]+}}: 42 00 08 3c lui $8, 66
-# CHECK-NEXT: {{[0-9a-f]+}}: 6f 01 08 85 lh $8, 367($8)
-# CHECK-NEXT: {{[0-9a-f]+}}: 3e 00 08 3c lui $8, 62
-# CHECK-NEXT: {{[0-9a-f]+}}: 71 01 08 85 lh $8, 369($8)
-# CHECK-NEXT: {{[0-9a-f]+}}: 40 02 08 3c lui $8, 576
-# CHECK-NEXT: {{[0-9a-f]+}}: 6f 01 08 85 lh $8, 367($8)
-# CHECK-NEXT: {{[0-9a-f]+}}: 40 fe 08 3c lui $8, 65088
-# CHECK-NEXT: {{[0-9a-f]+}}: 71 01 08 85 lh $8, 369($8)
-
-# CHECK: SYMBOL TABLE:
-# CHECK: {{[0-9a-f]+}} g F .text 00000040 glob1
-# CHECK: {{[0-9a-f]+}} g F .text 00000004 glob2
-
- .global glob1
- .ent glob1
-glob1:
- lui $t0,%hi(glob2+0x1)
- lh $t0,%lo(glob2+0x1)($t0)
-
- lui $t0,%hi(glob2+(-0x1))
- lh $t0,%lo(glob2+(-0x1))($t0)
-
- lui $t0,%hi(glob2+0x1ff)
- lh $t0,%lo(glob2+0x1ff)($t0)
-
- lui $t0,%hi(glob2+(-0x1ff))
- lh $t0,%lo(glob2+(-0x1ff))($t0)
-
- lui $t0,%hi(glob2+0x1ffff)
- lh $t0,%lo(glob2+0x1ffff)($t0)
-
- lui $t0,%hi(glob2+(-0x1ffff))
- lh $t0,%lo(glob2+(-0x1ffff))($t0)
-
- lui $t0,%hi(glob2+0x1ffffff) # truncate
- lh $t0,%lo(glob2+0x1ffffff)($t0)
-
- lui $t0,%hi(glob2+(-0x1ffffff)) # truncate
- lh $t0,%lo(glob2+(-0x1ffffff))($t0)
- .end glob1
-
- .global glob2
- .ent glob2
-glob2:
- nop
- .end glob2
diff --git a/test/elf/Mips/hilo16-3.test b/test/elf/Mips/hilo16-3.test
deleted file mode 100644
index daf4807d719a..000000000000
--- a/test/elf/Mips/hilo16-3.test
+++ /dev/null
@@ -1,45 +0,0 @@
-# REQUIRES: mips
-
-# 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: llvm-mc -triple=mipsel -filetype=obj -o=%t-obj %s
-# RUN: lld -flavor gnu -target mipsel -shared -o %t-so %t-obj
-# RUN: llvm-objdump -t -disassemble %t-so | FileCheck %s
-
-# CHECK: Disassembly of section .text:
-# CHECK: glob1:
-# CHECK-NEXT: {{[0-9a-f]+}}: 01 00 08 3c lui $8, 1
-# CHECK-NEXT: {{[0-9a-f]+}}: 01 8f 08 85 lh $8, -28927($8)
-# CHECK-NEXT: {{[0-9a-f]+}}: 01 00 08 3c lui $8, 1
-# CHECK-NEXT: {{[0-9a-f]+}}: f7 8e 08 85 lh $8, -28937($8)
-# CHECK-NEXT: {{[0-9a-f]+}}: 01 00 08 3c lui $8, 1
-# CHECK-NEXT: {{[0-9a-f]+}}: ef 90 08 85 lh $8, -28433($8)
-# CHECK-NEXT: {{[0-9a-f]+}}: 01 00 08 3c lui $8, 1
-# CHECK-NEXT: {{[0-9a-f]+}}: e9 8c 08 85 lh $8, -29463($8)
-# CHECK-NEXT: {{[0-9a-f]+}}: 03 00 08 3c lui $8, 3
-# CHECK-NEXT: {{[0-9a-f]+}}: df 8e 08 85 lh $8, -28961($8)
-
-# CHECK: SYMBOL TABLE:
-# CHECK: {{[0-9a-f]+}} g F .text 00000028 glob1
-# CHECK: {{[0-9a-f]+}} g *ABS* 00000000 _gp_disp
-
- .global glob1
-glob1:
- lui $t0,%hi(_gp_disp+0x1)
- lh $t0,%lo(_gp_disp+0x1)($t0)
-
- lui $t0,%hi(_gp_disp+(-0x1))
- lh $t0,%lo(_gp_disp+(-0x1))($t0)
-
- lui $t0,%hi(_gp_disp+0x1ff)
- lh $t0,%lo(_gp_disp+0x1ff)($t0)
-
- lui $t0,%hi(_gp_disp+(-0x1ff))
- lh $t0,%lo(_gp_disp+(-0x1ff))($t0)
-
- lui $t0,%hi(_gp_disp+0x1ffff)
- lh $t0,%lo(_gp_disp+0x1ffff)($t0)
diff --git a/test/elf/Mips/hilo16-4.test b/test/elf/Mips/hilo16-4.test
deleted file mode 100644
index 8a13f7b131fd..000000000000
--- a/test/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 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/elf/Mips/hilo16-5.test b/test/elf/Mips/hilo16-5.test
deleted file mode 100644
index 91aca8b1c366..000000000000
--- a/test/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 gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -o %t-o.o -docnum 2 %s
-# RUN: lld -flavor 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/elf/Mips/hilo16-8-micro.test b/test/elf/Mips/hilo16-8-micro.test
deleted file mode 100644
index 3248804f8f54..000000000000
--- a/test/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 -triple=mipsel -mattr=micromips -filetype=obj -o=%t-obj %s
-# RUN: lld -flavor gnu -target mipsel -e glob1 -o %t-exe %t-obj
-# RUN: llvm-objdump -t -d -mattr=micromips %t-exe | FileCheck %s
-
-# CHECK: Disassembly of section .text:
-# CHECK-NEXT: glob1:
-# CHECK-NEXT: 400130: a8 41 40 00 lui $8, 64
-# CHECK-NEXT: 400134: 08 3d 6a 01 lh $8, 362($8)
-# CHECK-NEXT: 400138: a8 41 41 00 lui $8, 65
-# CHECK-NEXT: 40013c: 08 3d 68 81 lh $8, -32408($8)
-# CHECK-NEXT: 400140: a8 41 41 00 lui $8, 65
-# CHECK-NEXT: 400144: 08 3d e9 81 lh $8, -32279($8)
-# CHECK-NEXT: 400148: a8 41 42 00 lui $8, 66
-# CHECK-NEXT: 40014c: 08 3d 69 81 lh $8, -32407($8)
-# CHECK-NEXT: 400150: a8 41 40 40 lui $8, 16448
-# CHECK-NEXT: 400154: 08 3d 69 01 lh $8, 361($8)
-# CHECK-NEXT: 400158: a8 41 40 80 lui $8, 32832
-# CHECK-NEXT: 40015c: 08 3d 69 01 lh $8, 361($8)
-# CHECK-NEXT: 400160: a8 41 c1 80 lui $8, 32961
-# CHECK-NEXT: 400164: 08 3d e9 81 lh $8, -32279($8)
-
-# CHECK: glob2:
-# CHECK-NEXT: 400168: a8 41 40 00 lui $8, 64
-# CHECK-NEXT: 40016c: a8 41 40 00 lui $8, 64
-# CHECK-NEXT: 400170: a8 41 41 00 lui $8, 65
-# CHECK-NEXT: 400174: a8 41 42 00 lui $8, 66
-# CHECK-NEXT: 400178: a8 41 40 40 lui $8, 16448
-# CHECK-NEXT: 40017c: a8 41 40 80 lui $8, 32832
-# CHECK-NEXT: 400180: a8 41 c1 80 lui $8, 32961
-# CHECK-NEXT: 400184: 08 3d b1 81 lh $8, -32335($8)
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400130 g F .text 00000038 glob1
-# CHECK: 00400168 g F .text 00000020 glob2
-
- .globl glob1
- .type glob1, @function
- .set micromips
- .ent glob1
-glob1:
- lui $t0,%hi(glob2+0x00000001)
- lh $t0,%lo(glob2+0x00000001)($t0)
-
- lui $t0,%hi(glob2+0x00007fff)
- lh $t0,%lo(glob2+0x00007fff)($t0)
-
- lui $t0,%hi(glob2+0x00008080)
- lh $t0,%lo(glob2+0x00008080)($t0)
-
- lui $t0,%hi(glob2+0x00018000)
- lh $t0,%lo(glob2+0x00018000)($t0)
-
- lui $t0,%hi(glob2+0x40000000)
- lh $t0,%lo(glob2+0x40000000)($t0)
-
- lui $t0,%hi(glob2+0x80000000)
- lh $t0,%lo(glob2+0x80000000)($t0)
-
- lui $t0,%hi(glob2+0x80808080)
- lh $t0,%lo(glob2+0x80808080)($t0)
- .end glob1
-
- .globl glob2
- .type glob2, @function
- .set micromips
- .ent glob2
-glob2:
- lui $t0,%hi(glob1+0x00000001)
- lui $t0,%hi(glob1+0x00007fff)
- lui $t0,%hi(glob1+0x00008080)
- lui $t0,%hi(glob1+0x00018000)
- lui $t0,%hi(glob1+0x40000000)
- lui $t0,%hi(glob1+0x80000000)
- lui $t0,%hi(glob1+0x80808080)
- lh $t0,%lo(glob1+0x80808080)($t0)
- .end glob2
diff --git a/test/elf/Mips/hilo16-9-micro.test b/test/elf/Mips/hilo16-9-micro.test
deleted file mode 100644
index 30ad10ce0dd4..000000000000
--- a/test/elf/Mips/hilo16-9-micro.test
+++ /dev/null
@@ -1,68 +0,0 @@
-# REQUIRES: mips
-
-# Check calculation of AHL addendums for R_MICROMIPS_HI16 / R_MICROMIPS_LO16
-# relocations for the _gp_disp symbol.
-#
-# RUN: llvm-mc -triple=mipsel -mattr=micromips -filetype=obj -o=%t-obj %s
-# RUN: lld -flavor gnu -target mipsel -shared -o %t-so %t-obj
-# RUN: llvm-objdump -t -d -mattr=micromips %t-so | FileCheck %s
-
-# CHECK: Disassembly of section .text:
-# CHECK-NEXT: glob1:
-# CHECK-NEXT: 130: a8 41 01 00 lui $8, 1
-# CHECK-NEXT: 134: 08 3d c0 9e lh $8, -24896($8)
-# CHECK-NEXT: 138: a8 41 01 00 lui $8, 1
-# CHECK-NEXT: 13c: 08 3d b6 1e lh $8, 7862($8)
-# CHECK-NEXT: 140: a8 41 01 00 lui $8, 1
-# CHECK-NEXT: 144: 08 3d 2f 1f lh $8, 7983($8)
-# CHECK-NEXT: 148: a8 41 02 00 lui $8, 2
-# CHECK-NEXT: 14c: 08 3d a7 1e lh $8, 7847($8)
-# CHECK-NEXT: 150: a8 41 01 40 lui $8, 16385
-# CHECK-NEXT: 154: 08 3d 9f 9e lh $8, -24929($8)
-
-# CHECK: glob2:
-# CHECK-NEXT: 158: a8 41 01 00 lui $8, 1
-# CHECK-NEXT: 15c: a8 41 01 00 lui $8, 1
-# CHECK-NEXT: 160: a8 41 02 00 lui $8, 2
-# CHECK-NEXT: 164: a8 41 03 00 lui $8, 3
-# CHECK-NEXT: 168: a8 41 01 40 lui $8, 16385
-# CHECK-NEXT: 16c: 08 3d 87 9e lh $8, -24953($8)
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 00000130 g F .text 00000028 glob1
-# CHECK: 00000158 g F .text 00000018 glob2
-# CHECK: 00009ff0 g *ABS* 00000000 _gp_disp
-
- .globl glob1
- .type glob1, @function
- .set micromips
- .ent glob1
-glob1:
- lui $t0,%hi(_gp_disp+0x00000001)
- lh $t0,%lo(_gp_disp+0x00000001)($t0)
-
- lui $t0,%hi(_gp_disp+0x00007fff)
- lh $t0,%lo(_gp_disp+0x00007fff)($t0)
-
- lui $t0,%hi(_gp_disp+0x00008080)
- lh $t0,%lo(_gp_disp+0x00008080)($t0)
-
- lui $t0,%hi(_gp_disp+0x00018000)
- lh $t0,%lo(_gp_disp+0x00018000)($t0)
-
- lui $t0,%hi(_gp_disp+0x40000000)
- lh $t0,%lo(_gp_disp+0x40000000)($t0)
- .end glob1
-
- .globl glob2
- .type glob2, @function
- .set micromips
- .ent glob2
-glob2:
- lui $t0,%hi(_gp_disp+0x00000001)
- lui $t0,%hi(_gp_disp+0x00007fff)
- lui $t0,%hi(_gp_disp+0x00008080)
- lui $t0,%hi(_gp_disp+0x00018000)
- lui $t0,%hi(_gp_disp+0x40000000)
- lh $t0,%lo(_gp_disp+0x40000000)($t0)
- .end glob2
diff --git a/test/elf/Mips/initfini-micro.test b/test/elf/Mips/initfini-micro.test
deleted file mode 100644
index ba30e89ade21..000000000000
--- a/test/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 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/elf/Mips/interpreter-64.test b/test/elf/Mips/interpreter-64.test
deleted file mode 100644
index 3ece3e6a467a..000000000000
--- a/test/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 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/elf/Mips/interpreter.test b/test/elf/Mips/interpreter.test
deleted file mode 100644
index 5355f7709fbd..000000000000
--- a/test/elf/Mips/interpreter.test
+++ /dev/null
@@ -1,26 +0,0 @@
-# Check program interpreter setup.
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor 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/elf/Mips/invalid-reginfo.test b/test/elf/Mips/invalid-reginfo.test
deleted file mode 100644
index d56223bf2e04..000000000000
--- a/test/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 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/elf/Mips/jalx-align-err.test b/test/elf/Mips/jalx-align-err.test
deleted file mode 100644
index 3db18fc98fac..000000000000
--- a/test/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 gnu -target mipsel -e T0 -o %t-exe %t-obj 2>&1 \
-# RUN: | FileCheck %s
-
-# CHECK: The jalx target 0x400116 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/elf/Mips/jump-fix-err.test b/test/elf/Mips/jump-fix-err.test
deleted file mode 100644
index 981179938397..000000000000
--- a/test/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 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/elf/Mips/la25-stub-micro.test b/test/elf/Mips/la25-stub-micro.test
deleted file mode 100644
index d41297a0ddc3..000000000000
--- a/test/elf/Mips/la25-stub-micro.test
+++ /dev/null
@@ -1,140 +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 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: 0x400135
-# SYM: Name: T1N (1)
-# SYM-NEXT: Value: 0x400111
-# SYM: Name: T1 (5)
-# SYM-NEXT: Value: 0x400121
-# SYM: Name: glob (8)
-# SYM-NEXT: Value: 0x400125
-
-# ASM: Contents of section .text:
-# ASM-NEXT: 400110 00000000 00000000 00000000 00000000
-# ASM-NEXT: 400120 00000000 00000000 00000000 10f04900
-# 0x100049 << 2 == 0x400125 (jalx glob) --^
-# ASM-NEXT: 400130 00000000 20f49200 00000000 20f48800
-# ^-- 0x100049 << 2 == 0x400124 (jal glob)
-# 0x100044 << 2 == 0x400110 (jal T1N) --^
-# ASM-NEXT: 400140 00000000 20f4a800 00000000 00000000
-# ^-- 0x100054 << 2 == 0x400150 (jal T1 stub)
-# ASM-NEXT: 400150 b9414000 20d49000 39332101 00000000
-# ^-- j 0x400120 (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/elf/Mips/la25-stub.test b/test/elf/Mips/la25-stub.test
deleted file mode 100644
index 2c4b26452cec..000000000000
--- a/test/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 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: 0x400134
-# SYM: Name: T1N (1)
-# SYM-NEXT: Value: 0x400110
-# SYM: Name: T1 (5)
-# SYM-NEXT: Value: 0x400120
-# SYM: Name: glob (8)
-# SYM-NEXT: Value: 0x400124
-
-# ASM: Contents of section .text:
-# ASM-NEXT: 400110 00000000 00000000 00000000 00000000
-# ASM-NEXT: 400120 00000000 00000000 00000000 49001000
-# 0x100049 << 2 == 0x400124 (glob) --^
-# ASM-NEXT: 400130 00000000 49001000 00000000 44001000
-# ^-- 0x100049 << 2 == 0x400124 (glob)
-# 0x100044 << 2 == 0x400110 (T1N) --^
-# ASM-NEXT: 400140 00000000 54001000 00000000 00000000
-# ^-- 0x100054 << 2 == 0x400150 (T1 stub)
-# ASM-NEXT: 400150 4000193c 48001008 20013927 00000000
-# ^-- j 0x400120 (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/elf/Mips/mips-options-gp0.test b/test/elf/Mips/mips-options-gp0.test
deleted file mode 100644
index 339ab97253b6..000000000000
--- a/test/elf/Mips/mips-options-gp0.test
+++ /dev/null
@@ -1,78 +0,0 @@
-# Check reading GP0 value from .MIPS.options section
-#
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor gnu -target mipsel -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 (1)
-# SYM-NEXT: Value: 0xCC
-# SYM-NEXT: Size: 4
-# SYM-NEXT: Binding: Local (0x0)
-# SYM-NEXT: Type: Function (0x2)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .text (0x4)
-
-# SYM: Name: _gp (34)
-# 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)
-
-# 0xffff80dc == 0x0 (addend) + 0x00cc (L1) + 0x1000 (GP0) - 0x8ff0 (_gp)
-# SEC: Contents of section .rodata:
-# SEC-NEXT: 00d4 dc80ffff 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:
-- 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_REL
- 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: "0128000000000000000000000000000000000000000000000000000000100000"
-
-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/elf/Mips/n64-rel-chain.test b/test/elf/Mips/n64-rel-chain.test
deleted file mode 100644
index 0ae7af73ae83..000000000000
--- a/test/elf/Mips/n64-rel-chain.test
+++ /dev/null
@@ -1,134 +0,0 @@
-# Check handling MIPS N64 ABI relocation "chains".
-
-# RUN: yaml2obj -format=elf -docnum 1 %s > %t-so.o
-# RUN: lld -flavor gnu -target mips64el -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor gnu -target mips64el -e T0 -o %t.exe %t-o.o %t.so
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 1200001d0 01000000 00000000 208e0000 00000000 ........ .......
-# CHECK-NEXT: 1200001e0 20800000 f8010000 28800000 00000000 .......(.......
-# CHECK: Contents of section .pdr:
-# CHECK-NEXT: 0000 d0010020 e0010020 ... ...
-
----
-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/elf/Mips/opt-emulation.test b/test/elf/Mips/opt-emulation.test
deleted file mode 100644
index 2d1e7142c386..000000000000
--- a/test/elf/Mips/opt-emulation.test
+++ /dev/null
@@ -1,41 +0,0 @@
-# Check MIPS specific arguments of the -m command line option.
-
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor gnu -target mipsel -m elf32ltsmip -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: 0
-# 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/elf/Mips/pc23-range.test b/test/elf/Mips/pc23-range.test
deleted file mode 100644
index 7166176c4628..000000000000
--- a/test/elf/Mips/pc23-range.test
+++ /dev/null
@@ -1,56 +0,0 @@
-# Check that LLD shows an error if ADDIUPC immediate is out of range.
-
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor gnu -target mipsel -o %t-exe %t-obj 2>&1 | FileCheck %s
-
-# CHECK: The addiupc instruction immediate 0x02000008 is out of range
-
-!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: "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/elf/Mips/plt-entry-mixed-1.test b/test/elf/Mips/plt-entry-mixed-1.test
deleted file mode 100644
index bc45763fa16d..000000000000
--- a/test/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 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 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: 21 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/elf/Mips/plt-entry-mixed-2.test b/test/elf/Mips/plt-entry-mixed-2.test
deleted file mode 100644
index 5aec7d7a328a..000000000000
--- a/test/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 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 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 2178e003 82c01800 09f82003 feff1827 !x........ ....'
-# CHECK-NEXT: 400190 40000f3c 0820f98d 08002003 0820f825 @..<. .... .. .%
-# CHECK-NEXT: 4001a0 00799a07 22ff0000 9945020f .y.."....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: 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/elf/Mips/plt-entry-mixed-3.test b/test/elf/Mips/plt-entry-mixed-3.test
deleted file mode 100644
index c61991b4b139..000000000000
--- a/test/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 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 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/elf/Mips/plt-entry-mixed-4.test b/test/elf/Mips/plt-entry-mixed-4.test
deleted file mode 100644
index acf5060621f6..000000000000
--- a/test/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 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 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 2178e003 82c01800 09f82003 feff1827 !x........ ....'
-# 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/elf/Mips/plt-entry-r6.test b/test/elf/Mips/plt-entry-r6.test
deleted file mode 100644
index bb05531487ff..000000000000
--- a/test/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 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 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: 21 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/elf/Mips/plt-header-micro.test b/test/elf/Mips/plt-header-micro.test
deleted file mode 100644
index ce042741cd32..000000000000
--- a/test/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 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 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/elf/Mips/plt-header-mixed.test b/test/elf/Mips/plt-header-mixed.test
deleted file mode 100644
index 0d3af19ee593..000000000000
--- a/test/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 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 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: 21 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/elf/Mips/plt-header.test b/test/elf/Mips/plt-header.test
deleted file mode 100644
index caf7e83ea5e2..000000000000
--- a/test/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 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 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: 21 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/elf/Mips/r26-1-micro.test b/test/elf/Mips/r26-1-micro.test
deleted file mode 100644
index 629754febc7e..000000000000
--- a/test/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 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 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/elf/Mips/r26-1.test b/test/elf/Mips/r26-1.test
deleted file mode 100644
index abc0a7ce5a81..000000000000
--- a/test/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 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 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/elf/Mips/r26-2-micro.test b/test/elf/Mips/r26-2-micro.test
deleted file mode 100644
index b92b9acf4c84..000000000000
--- a/test/elf/Mips/r26-2-micro.test
+++ /dev/null
@@ -1,88 +0,0 @@
-# REQUIRES: mips
-
-# Check reading addendum for R_MICROMIPS_26_S1 relocation.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor gnu -target mipsel -o %t-exe %t-obj
-# RUN: llvm-objdump -d -mattr=micromips %t-exe | FileCheck -check-prefix=DIS %s
-# RUN: llvm-objdump -t %t-exe | FileCheck %s
-
-# DIS: Disassembly of section .text:
-# DIS-NEXT: loc0:
-# DIS-NEXT: 400110: 00 00 00 00 nop
-
-# DIS: __start:
-# DIS-NEXT: 400114: 20 f4 8e e0 jal 4309276
-# DIS-NEXT: 400118: 00 00 00 00 nop
-# DIS-NEXT: 40011c: 20 f4 9a e0 jal 4309300
-# DIS-NEXT: 400120: 00 00 00 00 nop
-
-# DIS: loc1:
-# DIS-NEXT: 400124: 20 f4 89 00 jal 4194578
-# DIS-NEXT: 400128: 00 00 00 00 nop
-# DIS-NEXT: 40012c: 20 f4 91 00 jal 4194594
-# DIS-NEXT: 400130: 00 00 00 00 nop
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400124 l F .text 00000010 loc1
-# CHECK: 00400114 g F .text 00000010 __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
-# nop
-# jal __start + 0x1C000
-# nop
-# jal loc + 0x1C000
-# nop
-# jal __start + 7FFFFE2
-# nop
-# jal loc + 7FFFFEA
-# nop
- Content: "0000000000f404e00000000000f408e000000000FFF7FFFF00000000FFF7FFFF00000000"
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x4
- Symbol: __start
- Type: R_MICROMIPS_26_S1
- - Offset: 0xC
- Symbol: loc1
- Type: R_MICROMIPS_26_S1
- - Offset: 0x14
- Symbol: __start
- Type: R_MICROMIPS_26_S1
- - Offset: 0x1C
- Symbol: loc1
- Type: R_MICROMIPS_26_S1
-
-Symbols:
- Global:
- - Name: __start
- Section: .text
- Value: 0x4
- Size: 8
- Other: [ STO_MIPS_MICROMIPS ]
- Local:
- - Name: loc0
- Section: .text
- Value: 0
- Size: 4
- Other: [ STO_MIPS_MICROMIPS ]
- - Name: loc1
- Section: .text
- Value: 0x14
- Size: 8
- Other: [ STO_MIPS_MICROMIPS ]
diff --git a/test/elf/Mips/r26-2.test b/test/elf/Mips/r26-2.test
deleted file mode 100644
index 0f0063ae1334..000000000000
--- a/test/elf/Mips/r26-2.test
+++ /dev/null
@@ -1,82 +0,0 @@
-# REQUIRES: mips
-
-# Check reading addendum for R_MIPS_26 relocation.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor gnu -target mipsel -o %t-exe %t-obj
-# RUN: llvm-objdump -t -disassemble %t-exe | FileCheck %s
-
-# CHECK: Disassembly of section .text:
-# CHECK-NEXT: __start:
-# CHECK-NEXT: 400110: 00 00 00 00 nop
-# CHECK-NEXT: 400114: 44 70 10 0c jal 4309264
-# 0x107044 << 2 = 0x41C110 = _start + (0x7000 << 2)
-# CHECK-NEXT: 400118: 00 00 00 00 nop
-#
-# CHECK: loc:
-# CHECK-NEXT: 40011c: 47 70 10 0c jal 4309276
-# 0x107047 << 2 = 0x41C11C = loc + (0x7000 << 2)
-# CHECK-NEXT: 400120: 00 00 00 00 nop
-# CHECK-NEXT: 400124: 43 00 10 0c jal 4194572
-# 0x100043 << 2 = 0x40010C = _start - 4
-# CHECK-NEXT: 400128: 00 00 00 00 nop
-# CHECK-NEXT: 40012c: 46 00 10 0c jal 4194584
-# 0x100046 << 2 = 0x400118 = loc - 4
-# CHECK-NEXT: 400130: 00 00 00 00 nop
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 0040011c l F .text 00000018 loc
-# CHECK: 00400110 g F .text 0000000c __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_32]
-
-Sections:
-- Name: .text
- Type: SHT_PROGBITS
-# nop
-# jal __start + 0x1C000
-# nop
-# jal loc + 0x1C000
-# nop
-# jal __start - 1
-# nop
-# jal loc - 1
-# nop
- Content: "000000000070000C000000000070000C00000000FFFFFF0F00000000FFFFFF0F00000000"
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x4
- Symbol: __start
- Type: R_MIPS_26
- - Offset: 0xC
- Symbol: loc
- Type: R_MIPS_26
- - Offset: 0x14
- Symbol: __start
- Type: R_MIPS_26
- - Offset: 0x1C
- Symbol: loc
- Type: R_MIPS_26
-
-Symbols:
- Global:
- - Name: __start
- Section: .text
- Value: 0x0
- Size: 4
- Local:
- - Name: loc
- Section: .text
- Value: 0xc
- Size: 4
diff --git a/test/elf/Mips/rel-32.test b/test/elf/Mips/rel-32.test
deleted file mode 100644
index beefde59b7b1..000000000000
--- a/test/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 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/elf/Mips/rel-64.test b/test/elf/Mips/rel-64.test
deleted file mode 100644
index e05b75687038..000000000000
--- a/test/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 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/elf/Mips/rel-copy-micro.test b/test/elf/Mips/rel-copy-micro.test
deleted file mode 100644
index afa99198e37f..000000000000
--- a/test/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 gnu -target mipsel -shared -o %t1.so %t-so1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-so2.o
-# RUN: lld -flavor gnu -target mipsel -shared -o %t2.so %t-so2.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-o.o
-# RUN: lld -flavor 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 (0xA)
-# 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 (0xA)
-# 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/elf/Mips/rel-copy-pc.test b/test/elf/Mips/rel-copy-pc.test
deleted file mode 100644
index 2dd702334fed..000000000000
--- a/test/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 gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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 (0xA)
-# 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/elf/Mips/rel-copy.test b/test/elf/Mips/rel-copy.test
deleted file mode 100644
index 648a25e22ae7..000000000000
--- a/test/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 gnu -target mipsel -shared -o %t1.so %t-so1.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-so2.o
-# RUN: lld -flavor gnu -target mipsel -shared -o %t2.so %t-so2.o
-# RUN: yaml2obj -format=elf -docnum 3 %s > %t-o.o
-# RUN: lld -flavor 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: 0x402010
-# CHECK-NEXT: Size: 4
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Object (0x1)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: .bss (0xA)
-# CHECK-NEXT: }
-# CHECK-NEXT: Symbol {
-# CHECK-NEXT: Name: D3@ (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 (0xA)
-# 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/elf/Mips/rel-dynamic-01-micro.test b/test/elf/Mips/rel-dynamic-01-micro.test
deleted file mode 100644
index 6e0a41bf2606..000000000000
--- a/test/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 gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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: 0x402018 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: 0x402018
-# 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 (0xD)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: T1@ (4)
-# PLT-SYM-NEXT: Value: 0x4001D5
-# 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/elf/Mips/rel-dynamic-01.test b/test/elf/Mips/rel-dynamic-01.test
deleted file mode 100644
index ca4619668bd2..000000000000
--- a/test/elf/Mips/rel-dynamic-01.test
+++ /dev/null
@@ -1,237 +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 gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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: 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: 21 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: 0x402018 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: 0x402018
-# 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 (0xD)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: T1@ (4)
-# PLT-SYM-NEXT: Value: 0x400220
-# 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: ]
-
-# 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/elf/Mips/rel-dynamic-02.test b/test/elf/Mips/rel-dynamic-02.test
deleted file mode 100644
index 4de86383482c..000000000000
--- a/test/elf/Mips/rel-dynamic-02.test
+++ /dev/null
@@ -1,82 +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-obj
-# RUN: lld -flavor gnu -target mipsel -shared --noinhibit-exec -o %t1-so %t-obj
-# RUN: llvm-readobj -dt -r -s %t1-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: 0x140 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: None (0x0)
-# PLT-SYM-NEXT: Other: 0
-# PLT-SYM-NEXT: Section: Undefined (0x0)
-
-!ELF
-FileHeader: !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: "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: 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/elf/Mips/rel-dynamic-03-micro.test b/test/elf/Mips/rel-dynamic-03-micro.test
deleted file mode 100644
index 5de2cdcdc131..000000000000
--- a/test/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 gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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/elf/Mips/rel-dynamic-03.test b/test/elf/Mips/rel-dynamic-03.test
deleted file mode 100644
index cc791b051748..000000000000
--- a/test/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 gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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: 21 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/elf/Mips/rel-dynamic-04-micro.test b/test/elf/Mips/rel-dynamic-04-micro.test
deleted file mode 100644
index 1c58efdf5f70..000000000000
--- a/test/elf/Mips/rel-dynamic-04-micro.test
+++ /dev/null
@@ -1,211 +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 gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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.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: ]
-
-# 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/elf/Mips/rel-dynamic-04.test b/test/elf/Mips/rel-dynamic-04.test
deleted file mode 100644
index 5b5bcce01cd8..000000000000
--- a/test/elf/Mips/rel-dynamic-04.test
+++ /dev/null
@@ -1,206 +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 gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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.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: ]
-
-# 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/elf/Mips/rel-dynamic-05-micro.test b/test/elf/Mips/rel-dynamic-05-micro.test
deleted file mode 100644
index d1c87076b596..000000000000
--- a/test/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 gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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/elf/Mips/rel-dynamic-05.test b/test/elf/Mips/rel-dynamic-05.test
deleted file mode 100644
index 3bfbd3f6efdb..000000000000
--- a/test/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 gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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: 0x400190
-# PLT-NEXT: Offset: 0x190
-# 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: 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: 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: 0x4001D0
-# 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: 0x4001E0
-# 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: 0x4001F0
-# 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/elf/Mips/rel-dynamic-06-64.test b/test/elf/Mips/rel-dynamic-06-64.test
deleted file mode 100644
index c153eb22af4c..000000000000
--- a/test/elf/Mips/rel-dynamic-06-64.test
+++ /dev/null
@@ -1,101 +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 gnu -target mips64el -shared -o %t.so %t.o
-# RUN: llvm-readobj -dt -r -s %t.so | FileCheck -check-prefix=CHECK %s
-
-# CHECK: Sections [
-# CHECK: Section {
-# CHECK-NOT: Name: .plt ({{[0-9]+}})
-
-# CHECK: Relocations [
-# CHECK-NEXT: Section (4) .rel.dyn {
-# CHECK-NEXT: 0x170 R_MIPS_REL32/R_MIPS_64/R_MIPS_NONE T0 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: T1@ (4)
-# CHECK-NEXT: Value: 0x174
-# CHECK-NEXT: Size: 4
-# 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: T0@ (1)
-# CHECK-NEXT: Value: 0x170
-# CHECK-NEXT: Size: 4
-# CHECK-NEXT: Binding: Global (0x1)
-# CHECK-NEXT: Type: Function (0x2)
-# CHECK-NEXT: Other: 0
-# CHECK-NEXT: Section: .text (0x5)
-# CHECK-NEXT: }
-# 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_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/elf/Mips/rel-dynamic-06.test b/test/elf/Mips/rel-dynamic-06.test
deleted file mode 100644
index 433eb5fadf59..000000000000
--- a/test/elf/Mips/rel-dynamic-06.test
+++ /dev/null
@@ -1,103 +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-obj
-# RUN: lld -flavor gnu -target mipsel -shared -o %t1-so %t-obj
-# RUN: llvm-readobj -dt -r -s %t1-so | FileCheck -check-prefix=PLT1 %s
-
-# PLT1-SYM: Sections [
-# PLT1-SYM: Section {
-# PLT1-SYM-NOT: Name: .plt ({{[0-9]+}})
-
-# PLT1: Relocations [
-# PLT1-NEXT: Section (4) .rel.dyn {
-# PLT1-NEXT: 0x100 R_MIPS_REL32 T0 0x0
-# PLT1-NEXT: }
-# PLT1-NEXT: ]
-
-# PLT1: DynamicSymbols [
-# PLT1-NEXT: Symbol {
-# PLT1-NEXT: Name: @ (0)
-# PLT1-NEXT: Value: 0x0
-# PLT1-NEXT: Size: 0
-# PLT1-NEXT: Binding: Local (0x0)
-# PLT1-NEXT: Type: None (0x0)
-# PLT1-NEXT: Other: 0
-# PLT1-NEXT: Section: Undefined (0x0)
-# PLT1-NEXT: }
-# PLT1-NEXT: Symbol {
-# PLT1-NEXT: Name: T1@ (4)
-# PLT1-NEXT: Value: 0x104
-# PLT1-NEXT: Size: 4
-# PLT1-NEXT: Binding: Global (0x1)
-# PLT1-NEXT: Type: Function (0x2)
-# PLT1-NEXT: Other: 0
-# PLT1-NEXT: Section: .text (0x5)
-# PLT1-NEXT: }
-# PLT1-NEXT: Symbol {
-# PLT1-NEXT: Name: T0@ (1)
-# PLT1-NEXT: Value: 0x100
-# PLT1-NEXT: Size: 4
-# PLT1-NEXT: Binding: Global (0x1)
-# PLT1-NEXT: Type: Function (0x2)
-# PLT1-NEXT: Other: 0
-# PLT1-NEXT: Section: .text (0x5)
-# PLT1-NEXT: }
-# PLT1-NEXT: ]
-
-!ELF
-FileHeader: !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: "0000000000000000"
- AddressAlign: 16
- Flags: [SHF_EXECINSTR, SHF_ALLOC]
-
-- Name: .rel.text
- Type: SHT_REL
- Info: .text
- AddressAlign: 4
- Relocations:
- - Offset: 0x00
- Symbol: T0
- Type: R_MIPS_32
-
-- Name: .pdr
- Type: SHT_PROGBITS
- Content: "0000000000000000"
- AddressAlign: 16
- Flags: []
-
-- Name: .rel.pdr
- Type: SHT_REL
- Info: .pdr
- 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
- Section: .text
- Type: STT_FUNC
- Value: 0x4
- Size: 4
diff --git a/test/elf/Mips/rel-dynamic-07-64.test b/test/elf/Mips/rel-dynamic-07-64.test
deleted file mode 100644
index f7a1c4425823..000000000000
--- a/test/elf/Mips/rel-dynamic-07-64.test
+++ /dev/null
@@ -1,261 +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 gnu -target mips64el -shared -o %t1.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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
-
-# 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: ]
-
-# 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/elf/Mips/rel-dynamic-07.test b/test/elf/Mips/rel-dynamic-07.test
deleted file mode 100644
index fc163b9a12f7..000000000000
--- a/test/elf/Mips/rel-dynamic-07.test
+++ /dev/null
@@ -1,276 +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 gnu -target mipsel -shared -o %t1.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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
-
-# 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: ]
-
-# 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/elf/Mips/rel-dynamic-08-64.test b/test/elf/Mips/rel-dynamic-08-64.test
deleted file mode 100644
index d845d7407c1c..000000000000
--- a/test/elf/Mips/rel-dynamic-08-64.test
+++ /dev/null
@@ -1,233 +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 gnu -target mips64el -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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
-
-# 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: ]
-
-# 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/elf/Mips/rel-dynamic-08-micro.test b/test/elf/Mips/rel-dynamic-08-micro.test
deleted file mode 100644
index de0038956086..000000000000
--- a/test/elf/Mips/rel-dynamic-08-micro.test
+++ /dev/null
@@ -1,236 +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 gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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
-
-# 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: ]
-
-# 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/elf/Mips/rel-dynamic-08.test b/test/elf/Mips/rel-dynamic-08.test
deleted file mode 100644
index 62f4dc278b05..000000000000
--- a/test/elf/Mips/rel-dynamic-08.test
+++ /dev/null
@@ -1,233 +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 gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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
-
-# 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: ]
-
-# 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/elf/Mips/rel-dynamic-09-micro.test b/test/elf/Mips/rel-dynamic-09-micro.test
deleted file mode 100644
index 07ffce9eb074..000000000000
--- a/test/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 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/elf/Mips/rel-dynamic-09.test b/test/elf/Mips/rel-dynamic-09.test
deleted file mode 100644
index 18eeb9dd33d8..000000000000
--- a/test/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 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/elf/Mips/rel-dynamic-10-micro.test b/test/elf/Mips/rel-dynamic-10-micro.test
deleted file mode 100644
index 6b3f2af3db32..000000000000
--- a/test/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 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/elf/Mips/rel-dynamic-10.test b/test/elf/Mips/rel-dynamic-10.test
deleted file mode 100644
index 4df558167fc7..000000000000
--- a/test/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 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/elf/Mips/rel-dynamic-11.test b/test/elf/Mips/rel-dynamic-11.test
deleted file mode 100644
index 20295396cd08..000000000000
--- a/test/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 gnu -target mipsel -shared -o %t1.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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/elf/Mips/rel-dynamic-12.test b/test/elf/Mips/rel-dynamic-12.test
deleted file mode 100644
index 2a4061ab4035..000000000000
--- a/test/elf/Mips/rel-dynamic-12.test
+++ /dev/null
@@ -1,213 +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 gnu -target mipsel -shared -o %t.so %t-so.o
-# RUN: yaml2obj -format=elf -docnum 2 %s > %t-o.o
-# RUN: lld -flavor 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: 0x402014 R_MIPS_REL32 T2 0x0
-# PLT-SYM-NEXT: 0x402014 R_MIPS_REL32 D2 0x0
-# PLT-SYM-NEXT: 0x402018 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: 0x402018
-# 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 (0xD)
-# PLT-SYM-NEXT: }
-# PLT-SYM-NEXT: Symbol {
-# PLT-SYM-NEXT: Name: T1@ (4)
-# PLT-SYM-NEXT: Value: 0x400220
-# 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: ]
-
-# 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/elf/Mips/rel-gprel16.test b/test/elf/Mips/rel-gprel16.test
deleted file mode 100644
index dc188ea6825a..000000000000
--- a/test/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 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 (1)
-# SYM-NEXT: Value: 0xCC
-# SYM-NEXT: Size: 4
-# SYM-NEXT: Binding: Local (0x0)
-# SYM-NEXT: Type: Function (0x2)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .text (0x4)
-
-# SYM: Name: G1 (4)
-# SYM-NEXT: Value: 0xD0
-# SYM-NEXT: Size: 4
-# SYM-NEXT: Binding: Global (0x1)
-# SYM-NEXT: Type: Function (0x2)
-# SYM-NEXT: Other: 0
-# SYM-NEXT: Section: .text (0x4)
-
-# SYM: Name: _gp (34)
-# 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)
-
-# 0x160db == 0xffff (addend) + 0x00cc (L1) + 0x01f000 (GP0) - 0x8ff0 (_gp)
-# SEC: Contents of section .rodata:
-# SEC-NEXT: 00d4 db600008 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: ffff0008000000000000000000000000
-
-- 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: 000000000000000000000000000000000000000000f00100
-
-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/elf/Mips/rel-gprel32-64.test b/test/elf/Mips/rel-gprel32-64.test
deleted file mode 100644
index 723c8e1ee738..000000000000
--- a/test/elf/Mips/rel-gprel32-64.test
+++ /dev/null
@@ -1,70 +0,0 @@
-# Check R_MIPS_GPREL32/R_MIPS_64 relocations handling.
-
-# RUN: yaml2obj -format=elf %s > %t.o
-# RUN: lld -flavor gnu -target mips64el -e T0 -o %t.exe %t.o
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 1200001a0 c871ffff ffffffff c871ffff c871ffff .q.......q...q..
-# CHECK-NEXT: 1200001b0 c871ffff ffffffff 00000000 00000000 .q..............
-
----
-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
-
- Global:
- - Name: LT1
- Type: STT_FUNC
- Section: .text
- Value: 0x18
- Size: 0x8
- - Name: T0
- Type: STT_FUNC
- Section: .text
- Value: 0x0
- Size: 0x18
-...
diff --git a/test/elf/Mips/rel-gprel32.test b/test/elf/Mips/rel-gprel32.test
deleted file mode 100644
index 73ae6f161979..000000000000
--- a/test/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 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 (1)
-# SYM-NEXT: Value: 0x400108
-# 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 (212)
-# 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)
-
-# 0x08FF711B == 0x8000001 (addend) + 0x400108 ($L1) +
-# 0x1000002 (GP0) - 0x408FF0 (_gp)
-# SEC: Contents of section .rodata:
-# SEC-NEXT: 400118 1b71ff08 00000000 00000000 00000000 .q..............
-
-!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/elf/Mips/rel-pc-hilo.test b/test/elf/Mips/rel-pc-hilo.test
deleted file mode 100644
index 89cd2b121797..000000000000
--- a/test/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 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: 400110 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: 00400110 g F .text 0000000c T0
-# CHECK: 0040011c 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/elf/Mips/rel-pc18-s3.test b/test/elf/Mips/rel-pc18-s3.test
deleted file mode 100644
index 5d5d5c7ce658..000000000000
--- a/test/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 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: 400110 00000000 01000000 00000000 00000000
-# ^ V
-# A = -1 << 3 = -8 =>
-# V = (T1 - 8 - (T0|7)^7) >> 3 =>
-# V => 8 >> 3 = 1
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400110 g F .text 00000010 T0
-# CHECK: 00400120 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/elf/Mips/rel-pc19-s2.test b/test/elf/Mips/rel-pc19-s2.test
deleted file mode 100644
index 479965df814f..000000000000
--- a/test/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 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: 400110 01000000 00000000 00000000
-# ^ V
-# A = -1 << 2 = -4 =>
-# V = (T1 - 4 - T0) >> 2 =>
-# V => 4 >> 2 = 1
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400110 g F .text 00000008 T0
-# CHECK: 00400118 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/elf/Mips/rel-pc21-s2.test b/test/elf/Mips/rel-pc21-s2.test
deleted file mode 100644
index 44d840e94c32..000000000000
--- a/test/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 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: 400110 01000000 00000000 00000000
-# ^ V
-# A = -1 << 2 = -4 =>
-# V = (T1 - 4 - T0) >> 2 =>
-# V => 4 >> 2 = 1
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400110 g F .text 00000008 T0
-# CHECK: 00400118 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/elf/Mips/rel-pc26-s2.test b/test/elf/Mips/rel-pc26-s2.test
deleted file mode 100644
index abd05040f0c3..000000000000
--- a/test/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 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: 400110 01000000 00000000 00000000
-# ^ V
-# A = -1 << 2 = -4 =>
-# V = (T1 - 4 - T0) >> 2 =>
-# V => 4 >> 2 = 1
-
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400110 g F .text 00000008 T0
-# CHECK: 00400118 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/elf/Mips/rel-pc32.test b/test/elf/Mips/rel-pc32.test
deleted file mode 100644
index e448e8afc30e..000000000000
--- a/test/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 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 05000080 fdffff7f ............
-# ^^ data2 + 0x80000001 - data1
-# ^^ data1 + 0x80000001 - data2
-# 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_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/elf/Mips/rel-pc7-10-16-23.test b/test/elf/Mips/rel-pc7-10-16-23.test
deleted file mode 100644
index c38b9eed2a5e..000000000000
--- a/test/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 gnu -target mipsel -o %t-exe %t-obj
-# RUN: llvm-objdump -s -t %t-exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK-NEXT: 400110 00000000 80780500 a240fcff 000c03cc .....x...@......
-# ^^ addiu s1,$pc,20
-# ^^ bnezc v0,400114 <__start+0x4>
-# ^^ b 400126 <L1>
-# CHECK-NEXT: 400120 000c03ad 00000000 00000000 00000000 ................
-# ^^ bnez v0,40012a <L2>
-# CHECK: SYMBOL TABLE:
-# CHECK: 00400124 l F .text 00000002 L0
-# CHECK: 00400126 l F .text 00000004 L1
-# CHECK: 0040012a l F .text 00000004 L2
-# CHECK: 0040012e l F .text 00000002 L3
-# CHECK: 00400110 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/elf/Mips/rel-sub.test b/test/elf/Mips/rel-sub.test
deleted file mode 100644
index 93e569a22035..000000000000
--- a/test/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 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/elf/Mips/st-other.test b/test/elf/Mips/st-other.test
deleted file mode 100644
index 8d15e75676b0..000000000000
--- a/test/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 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 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: 0xEC
-# 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: 0xF1
-# 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: 0x400108
-# 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: 0x40010D
-# 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/elf/Mips/tls-1-micro.test b/test/elf/Mips/tls-1-micro.test
deleted file mode 100644
index bd962b4e9e80..000000000000
--- a/test/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 gnu -target mipsel -e L0 -o %t.exe %t.o
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK: 400150 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/elf/Mips/tls-1.test b/test/elf/Mips/tls-1.test
deleted file mode 100644
index 99176e69171d..000000000000
--- a/test/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 gnu -target mipsel -e L0 -o %t.exe %t.o
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-# CHECK: Contents of section .text:
-# CHECK: 400150 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/elf/Mips/tls-2-64.test b/test/elf/Mips/tls-2-64.test
deleted file mode 100644
index a068934aeafa..000000000000
--- a/test/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 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/elf/Mips/tls-2-micro.test b/test/elf/Mips/tls-2-micro.test
deleted file mode 100644
index 5a1fe2904ac9..000000000000
--- a/test/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 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/elf/Mips/tls-2.test b/test/elf/Mips/tls-2.test
deleted file mode 100644
index 32b2bc105112..000000000000
--- a/test/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 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/elf/Mips/tls-3-micro.test b/test/elf/Mips/tls-3-micro.test
deleted file mode 100644
index 0e0f3d556f8f..000000000000
--- a/test/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 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 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/elf/Mips/tls-3.test b/test/elf/Mips/tls-3.test
deleted file mode 100644
index 7e54724fade5..000000000000
--- a/test/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 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 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/elf/Mips/tls-4-micro.test b/test/elf/Mips/tls-4-micro.test
deleted file mode 100644
index 1b0d03fa8875..000000000000
--- a/test/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 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/elf/Mips/tls-4.test b/test/elf/Mips/tls-4.test
deleted file mode 100644
index fb42f0d93378..000000000000
--- a/test/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 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/elf/Mips/tls-5-64.test b/test/elf/Mips/tls-5-64.test
deleted file mode 100644
index 784d71efc48f..000000000000
--- a/test/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 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/elf/Mips/tls-5-micro.test b/test/elf/Mips/tls-5-micro.test
deleted file mode 100644
index 89d1d98a6877..000000000000
--- a/test/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 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/elf/Mips/tls-5.test b/test/elf/Mips/tls-5.test
deleted file mode 100644
index 378ce321b8c9..000000000000
--- a/test/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 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/elf/X86_64/ExampleTarget/triple.test b/test/elf/X86_64/ExampleTarget/triple.test
deleted file mode 100644
index 3aecceb4305e..000000000000
--- a/test/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 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/elf/X86_64/Inputs/generaltls-so.o.yaml b/test/elf/X86_64/Inputs/generaltls-so.o.yaml
deleted file mode 100644
index f0649e7639a6..000000000000
--- a/test/elf/X86_64/Inputs/generaltls-so.o.yaml
+++ /dev/null
@@ -1,68 +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
- Content: ''
- - 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/elf/X86_64/alignoffset.test b/test/elf/X86_64/alignoffset.test
deleted file mode 100644
index b061f8937935..000000000000
--- a/test/elf/X86_64/alignoffset.test
+++ /dev/null
@@ -1,119 +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 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
- Content: ''
- - 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/elf/X86_64/debug.test b/test/elf/X86_64/debug.test
deleted file mode 100644
index a13d12fba382..000000000000
--- a/test/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 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 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/elf/X86_64/defsym.test b/test/elf/X86_64/defsym.test
deleted file mode 100644
index 5d2256a09ac8..000000000000
--- a/test/elf/X86_64/defsym.test
+++ /dev/null
@@ -1,22 +0,0 @@
-RUN: lld -flavor 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/elf/X86_64/demangle.test b/test/elf/X86_64/demangle.test
deleted file mode 100644
index 1977fd7f1e3a..000000000000
--- a/test/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 gnu -target x86_64 %p/Inputs/undefcpp.o --noinhibit-exec 2>&1 | FileCheck -check-prefix=DEMANGLE %s
-RUN: lld -flavor gnu -target x86_64 %p/Inputs/undefcpp.o --noinhibit-exec --no-demangle 2>&1 | FileCheck -check-prefix=NODEMANGLE %s
-RUN: lld -flavor 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/elf/X86_64/dontignorezerosize-sections.test b/test/elf/X86_64/dontignorezerosize-sections.test
deleted file mode 100644
index 101e6cb55b24..000000000000
--- a/test/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 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/elf/X86_64/dynamicvars.test b/test/elf/X86_64/dynamicvars.test
deleted file mode 100644
index f5db73063650..000000000000
--- a/test/elf/X86_64/dynamicvars.test
+++ /dev/null
@@ -1,124 +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 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
- Content: ''
- - 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/elf/X86_64/dynlib-nointerp-section.test b/test/elf/X86_64/dynlib-nointerp-section.test
deleted file mode 100644
index dca3d925b38b..000000000000
--- a/test/elf/X86_64/dynlib-nointerp-section.test
+++ /dev/null
@@ -1,4 +0,0 @@
-RUN: lld -flavor 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/elf/X86_64/dynlib-search.test b/test/elf/X86_64/dynlib-search.test
deleted file mode 100644
index 017208ac11ad..000000000000
--- a/test/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 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/elf/X86_64/dynsym-weak.test b/test/elf/X86_64/dynsym-weak.test
deleted file mode 100644
index 4f05656a41f2..000000000000
--- a/test/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 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 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 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 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/elf/X86_64/extern-tls.test b/test/elf/X86_64/extern-tls.test
deleted file mode 100644
index c8e7580e5f3c..000000000000
--- a/test/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 gnu -target x86_64-linux %p/Inputs/externtls.x86-64 -static \
-RUN: --output-filetype=yaml --noinhibit-exec | FileCheck %s -check-prefix=CHECKGOT
-
- - name: __got_tls_extern_tls
-CHECKGOT: type: got
-CHECKGOT: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
-CHECKGOT: alignment: 2^3
-CHECKGOT: section-choice: custom-required
-CHECKGOT: section-name: .got
-CHECKGOT: permissions: rw-
-CHECKGOT: references:
-CHECKGOT: - kind: R_X86_64_TPOFF64
-CHECKGOT: offset: 0
-CHECKGOT: target: extern_tls
diff --git a/test/elf/X86_64/general-dynamic-tls.test b/test/elf/X86_64/general-dynamic-tls.test
deleted file mode 100644
index c1a6f6e5d120..000000000000
--- a/test/elf/X86_64/general-dynamic-tls.test
+++ /dev/null
@@ -1,129 +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 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 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
- Content: ''
- - 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/elf/X86_64/imagebase.test b/test/elf/X86_64/imagebase.test
deleted file mode 100644
index 67c3b6e1ff49..000000000000
--- a/test/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 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
- Content: '64000000'
- - 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/elf/X86_64/initfini-order.test b/test/elf/X86_64/initfini-order.test
deleted file mode 100644
index d3981eb0914e..000000000000
--- a/test/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 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/elf/X86_64/initfini.test b/test/elf/X86_64/initfini.test
deleted file mode 100644
index d882352a1c38..000000000000
--- a/test/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 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/elf/X86_64/largebss.test b/test/elf/X86_64/largebss.test
deleted file mode 100644
index d2dde4954139..000000000000
--- a/test/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 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/elf/X86_64/layoutpass-order.test b/test/elf/X86_64/layoutpass-order.test
deleted file mode 100644
index e4ebef1d52db..000000000000
--- a/test/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 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/elf/X86_64/maxpagesize.test b/test/elf/X86_64/maxpagesize.test
deleted file mode 100644
index 649d09fcada0..000000000000
--- a/test/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 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 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 gnu -target x86_64 %t.o -o %t.exe -static \
-# RUN: --no-align-segments --noinhibit-exec -z max-page-size=0x1010
-# RUN: lld -flavor gnu -target x86_64 %t.o -o %t1.exe -static \
-# RUN: --no-align-segments --noinhibit-exec -z max-page-size=0x100000
-# RUN: lld -flavor 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
- Content: '64000000'
- - 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/elf/X86_64/mergesimilarstrings.test b/test/elf/X86_64/mergesimilarstrings.test
deleted file mode 100644
index 3836f0b50758..000000000000
--- a/test/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 gnu -target x86_64 %t.o --noinhibit-exec -o %t1.out
-# RUN: llvm-readobj -sections %t1.out | FileCheck %s
-# RUN: lld -flavor 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/elf/X86_64/multi-weak-layout.test b/test/elf/X86_64/multi-weak-layout.test
deleted file mode 100644
index 4bbf1dfc7e90..000000000000
--- a/test/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 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: 2^3
-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: 2^3
-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: 2^3
-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: 2^3
-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: 2^3
-WEAKSYMS: references:
-WEAKSYMS: - kind: R_X86_64_64
-WEAKSYMS: offset: 0
-WEAKSYMS: target: test
diff --git a/test/elf/X86_64/multi-weak-override.test b/test/elf/X86_64/multi-weak-override.test
deleted file mode 100644
index f2d0e0c2f77b..000000000000
--- a/test/elf/X86_64/multi-weak-override.test
+++ /dev/null
@@ -1,16 +0,0 @@
-# Test for weak symbol getting overridden
-RUN: lld -flavor 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 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/elf/X86_64/multi-weak-syms-order.test b/test/elf/X86_64/multi-weak-syms-order.test
deleted file mode 100644
index 2b414593fed4..000000000000
--- a/test/elf/X86_64/multi-weak-syms-order.test
+++ /dev/null
@@ -1,13 +0,0 @@
-# Test for weak symbol getting overridden
-RUN: lld -flavor 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 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/elf/X86_64/nmagic.test b/test/elf/X86_64/nmagic.test
deleted file mode 100644
index b313c1f051ba..000000000000
--- a/test/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 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/elf/X86_64/noalignsegments.test b/test/elf/X86_64/noalignsegments.test
deleted file mode 100644
index 8432bda51f00..000000000000
--- a/test/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 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
- Content: '64000000'
- - 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/elf/X86_64/note-sections-ro_plus_rw.test b/test/elf/X86_64/note-sections-ro_plus_rw.test
deleted file mode 100644
index ddeeaa41a758..000000000000
--- a/test/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 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/elf/X86_64/note-sections.test b/test/elf/X86_64/note-sections.test
deleted file mode 100644
index a49f95cf4a27..000000000000
--- a/test/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 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/elf/X86_64/omagic.test b/test/elf/X86_64/omagic.test
deleted file mode 100644
index 437d2e2a9f98..000000000000
--- a/test/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 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: 2
-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/elf/X86_64/outputsegments.test b/test/elf/X86_64/outputsegments.test
deleted file mode 100644
index ab6ba8deb47d..000000000000
--- a/test/elf/X86_64/outputsegments.test
+++ /dev/null
@@ -1,189 +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 gnu -target x86_64 %t.o -o %t1.exe -static \
-# RUN: --no-align-segments --noinhibit-exec
-# RUN: lld -flavor 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
- Content: ''
- - 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/elf/X86_64/reloc_r_x86_64_16.test b/test/elf/X86_64/reloc_r_x86_64_16.test
deleted file mode 100644
index 7cca839eb623..000000000000
--- a/test/elf/X86_64/reloc_r_x86_64_16.test
+++ /dev/null
@@ -1,60 +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 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
- Content: ''
-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/elf/X86_64/reloc_r_x86_64_pc16.test b/test/elf/X86_64/reloc_r_x86_64_pc16.test
deleted file mode 100644
index 6e43e5fade61..000000000000
--- a/test/elf/X86_64/reloc_r_x86_64_pc16.test
+++ /dev/null
@@ -1,61 +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 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
- Content: ''
-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/elf/X86_64/reloc_r_x86_64_pc64.test b/test/elf/X86_64/reloc_r_x86_64_pc64.test
deleted file mode 100644
index 75744390be91..000000000000
--- a/test/elf/X86_64/reloc_r_x86_64_pc64.test
+++ /dev/null
@@ -1,61 +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 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
- Content: ''
-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/elf/X86_64/rodata.test b/test/elf/X86_64/rodata.test
deleted file mode 100644
index 61af99f65cfc..000000000000
--- a/test/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 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/elf/X86_64/sectionchoice.test b/test/elf/X86_64/sectionchoice.test
deleted file mode 100644
index 4034d8b1111a..000000000000
--- a/test/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 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/elf/X86_64/sectionmap.test b/test/elf/X86_64/sectionmap.test
deleted file mode 100644
index a38f23e32b95..000000000000
--- a/test/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 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/elf/X86_64/startGroupEndGroup.test b/test/elf/X86_64/startGroupEndGroup.test
deleted file mode 100644
index ce1897683b34..000000000000
--- a/test/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 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 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 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 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 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 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 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 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/elf/X86_64/startGroupEndGroupWithDynlib.test b/test/elf/X86_64/startGroupEndGroupWithDynlib.test
deleted file mode 100644
index 3e40997db384..000000000000
--- a/test/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 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/elf/X86_64/staticlib-search.test b/test/elf/X86_64/staticlib-search.test
deleted file mode 100644
index 9c512571932d..000000000000
--- a/test/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 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/elf/X86_64/undef.test b/test/elf/X86_64/undef.test
deleted file mode 100644
index 8f0039a14693..000000000000
--- a/test/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 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 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/elf/X86_64/underscore-end.test b/test/elf/X86_64/underscore-end.test
deleted file mode 100644
index 337aa197f812..000000000000
--- a/test/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 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 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/elf/X86_64/weak-override.test b/test/elf/X86_64/weak-override.test
deleted file mode 100644
index b68b449a6649..000000000000
--- a/test/elf/X86_64/weak-override.test
+++ /dev/null
@@ -1,45 +0,0 @@
-# Test for weak symbol getting overridden
-RUN: lld -flavor 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 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/elf/X86_64/weak-zero-sized.test b/test/elf/X86_64/weak-zero-sized.test
deleted file mode 100644
index 76e051064b9d..000000000000
--- a/test/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 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 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: 2^2
-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: 2^2
-WEAKATOMSORDER: references:
-WEAKATOMSORDER: - kind: layout-after
-WEAKATOMSORDER: offset: 0
-WEAKATOMSORDER: target: [[TARGETC]]
-WEAKATOMSORDER: - ref-name: [[TARGETC]]
-WEAKATOMSORDER: scope: global
-WEAKATOMSORDER: content: [ C3 ]
-WEAKATOMSORDER: alignment: 2^2
diff --git a/test/elf/X86_64/weaksym.test b/test/elf/X86_64/weaksym.test
deleted file mode 100644
index d44ca8a36968..000000000000
--- a/test/elf/X86_64/weaksym.test
+++ /dev/null
@@ -1,78 +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 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
- Content: ''
-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/elf/X86_64/yamlinput.test b/test/elf/X86_64/yamlinput.test
deleted file mode 100644
index 6e529b41b7a6..000000000000
--- a/test/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 gnu -target x86_64-linux %p/Inputs/initfini.o \
-RUN: --noinhibit-exec --output-filetype=yaml -o %t.objtxt
-RUN: lld -flavor 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/elf/abs-dup.objtxt b/test/elf/abs-dup.objtxt
deleted file mode 100644
index 7340a29b0f00..000000000000
--- a/test/elf/abs-dup.objtxt
+++ /dev/null
@@ -1,19 +0,0 @@
-# Tests handling an absolute symbol with no name
-# RUN: lld -flavor 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/elf/abs.test b/test/elf/abs.test
deleted file mode 100644
index bad74f10d194..000000000000
--- a/test/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 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/elf/allowduplicates.objtxt b/test/elf/allowduplicates.objtxt
deleted file mode 100644
index dbad3bd312ed..000000000000
--- a/test/elf/allowduplicates.objtxt
+++ /dev/null
@@ -1,51 +0,0 @@
-# RUN: lld -flavor gnu -target x86_64 --allow-multiple-definition %s \
-# RUN: --output-filetype=yaml --noinhibit-exec | FileCheck %s
-#
-# RUN: not lld -flavor gnu -target x86_64 %s --output-filetype=yaml \
-# RUN: --noinhibit-exec 2>&1 | FileCheck -check-prefix=ERROR %s
-#
-# RUN: lld -flavor gnu -target x86_64 -z muldefs %s \
-# RUN: --noinhibit-exec --output-filetype=yaml | FileCheck %s
-
----
-defined-atoms:
- - name: .text
- alignment: 2^4
- 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: 2^4
- section-choice: custom-required
- section-name: .text
----
-defined-atoms:
- - name: .text
- alignment: 2^4
- 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: 2^4
- section-choice: custom-required
- section-name: .text
----
-
-# CHECK: defined-atoms:
-# CHECK: - name: .text
-# CHECK: alignment: 2^4
-# 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: 2^4
-# CHECK: section-choice: custom-required
-# CHECK: section-name: .text
-
-# ERROR: duplicate symbol error
diff --git a/test/elf/archive-elf-forceload.test b/test/elf/archive-elf-forceload.test
deleted file mode 100644
index a0d115094815..000000000000
--- a/test/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 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/elf/archive-elf.test b/test/elf/archive-elf.test
deleted file mode 100644
index ba6774644cbd..000000000000
--- a/test/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 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/elf/as-needed.test b/test/elf/as-needed.test
deleted file mode 100644
index 4477f0fe0ca6..000000000000
--- a/test/elf/as-needed.test
+++ /dev/null
@@ -1,15 +0,0 @@
-RUN: lld -flavor 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 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/elf/branch.test b/test/elf/branch.test
deleted file mode 100644
index 5e0b4a5aabf1..000000000000
--- a/test/elf/branch.test
+++ /dev/null
@@ -1,34 +0,0 @@
-RUN: lld -flavor 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 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/elf/check.test b/test/elf/check.test
deleted file mode 100644
index 336b7fc1335c..000000000000
--- a/test/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 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 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/elf/checkrodata.test b/test/elf/checkrodata.test
deleted file mode 100644
index fc75657b4afb..000000000000
--- a/test/elf/checkrodata.test
+++ /dev/null
@@ -1,9 +0,0 @@
-
-RUN: lld -flavor 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 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/elf/common.test b/test/elf/common.test
deleted file mode 100644
index 46fcfe39d486..000000000000
--- a/test/elf/common.test
+++ /dev/null
@@ -1,10 +0,0 @@
-RUN: lld -flavor 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/elf/consecutive-weak-sym-defs.test b/test/elf/consecutive-weak-sym-defs.test
deleted file mode 100644
index 095fabb17ab8..000000000000
--- a/test/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 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/elf/defsym.objtxt b/test/elf/defsym.objtxt
deleted file mode 100644
index e9c3922d5994..000000000000
--- a/test/elf/defsym.objtxt
+++ /dev/null
@@ -1,28 +0,0 @@
-# RUN: lld -flavor gnu -target x86_64 --defsym=foo=0x1234 -r %s \
-# RUN: --output-filetype=yaml | FileCheck -check-prefix=ABS %s
-
-# RUN: lld -flavor 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: 2^4
- 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/elf/dynamic-segorder.test b/test/elf/dynamic-segorder.test
deleted file mode 100644
index 1fdccec9921b..000000000000
--- a/test/elf/dynamic-segorder.test
+++ /dev/null
@@ -1,17 +0,0 @@
-RUN: lld -flavor 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/elf/dynamic-undef.test b/test/elf/dynamic-undef.test
deleted file mode 100644
index 7506b21b3ca7..000000000000
--- a/test/elf/dynamic-undef.test
+++ /dev/null
@@ -1,34 +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 not passing --allow-shlib-undefined
-RUN: not lld -flavor gnu -target x86_64-linux %p/Inputs/tls.x86-64 \
-RUN: %p/Inputs/shared.so-x86-64 -o %t -e main 2> %t1
-RUN: FileCheck -check-prefix=EXEC %s < %t1
-# This test will pass because of --allow-shlib-undefined
-RUN: lld -flavor 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
-# 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 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 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/elf/dynamic.test b/test/elf/dynamic.test
deleted file mode 100644
index 59269612cf8e..000000000000
--- a/test/elf/dynamic.test
+++ /dev/null
@@ -1,80 +0,0 @@
-# Checks functionality of dynamic executables
-RUN: lld -flavor 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 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/elf/eh_frame_hdr.test b/test/elf/eh_frame_hdr.test
deleted file mode 100644
index 31429857ec69..000000000000
--- a/test/elf/eh_frame_hdr.test
+++ /dev/null
@@ -1,30 +0,0 @@
-#RUN: yaml2obj -format=elf %s > %t
-#RUN: lld -flavor 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/elf/entry.objtxt b/test/elf/entry.objtxt
deleted file mode 100644
index 7e0c1623565a..000000000000
--- a/test/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 gnu -target x86_64 %s -e _entrypoint --noinhibit-exec -o %t1
-# RUN: llvm-nm -n %t1 | FileCheck %s
-#
-# CHECK: 004001e0 T main
-# CHECK: 00401000 D _DYNAMIC
-# CHECK: 00401060 A _end
-# CHECK: 00401060 A end
-# CHECK: U _entrypoint
-
-defined-atoms:
- - name: .text
- alignment: 2^4
- 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: 2^4
- section-choice: custom-required
- section-name: .text
- - name: .data
- type: data
- alignment: 2^2
- section-choice: custom-required
- section-name: .data
- - name: .bss
- type: zero-fill
- alignment: 2^2
- 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: 2^3
- section-choice: custom-required
- section-name: .eh_frame
- permissions: r--
- references:
- - kind: R_X86_64_PC32
- offset: 32
- target: .text
diff --git a/test/elf/export-dynamic.test b/test/elf/export-dynamic.test
deleted file mode 100644
index 37876a47c840..000000000000
--- a/test/elf/export-dynamic.test
+++ /dev/null
@@ -1,99 +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 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
- Content: ''
-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/elf/filenotfound.test b/test/elf/filenotfound.test
deleted file mode 100644
index d64568f2ea53..000000000000
--- a/test/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 gnu -target x86_64 %p/Inputs/nofile.o 2>&1 | FileCheck %s
-#CHECK: lld: cannot find file {{.+[\\/]}}nofile.o
diff --git a/test/elf/gnulinkonce/gnulinkonce-report-discarded-reference.test b/test/elf/gnulinkonce/gnulinkonce-report-discarded-reference.test
deleted file mode 100644
index e1d0f8e7b55e..000000000000
--- a/test/elf/gnulinkonce/gnulinkonce-report-discarded-reference.test
+++ /dev/null
@@ -1,147 +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 gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \
-#RUN: --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
-#RUN: lld -flavor 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
- Content: ''
- - 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
- Content: ''
- - 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/elf/gnulinkonce/gnulinkonce-report-undef.test b/test/elf/gnulinkonce/gnulinkonce-report-undef.test
deleted file mode 100644
index c6d050dcd63a..000000000000
--- a/test/elf/gnulinkonce/gnulinkonce-report-undef.test
+++ /dev/null
@@ -1,129 +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 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 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
- Content: ''
- - 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
- Content: ''
- - 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/elf/gnulinkonce/gnulinkonce.test b/test/elf/gnulinkonce/gnulinkonce.test
deleted file mode 100644
index 17559f656328..000000000000
--- a/test/elf/gnulinkonce/gnulinkonce.test
+++ /dev/null
@@ -1,151 +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 gnu -target x86_64 %t.linkonce1a.o %t.linkonce1b.o \
-#RUN: --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
-#RUN: lld -flavor 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
- Content: ''
- - 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
- Content: ''
- - 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/elf/gotpcrel.test b/test/elf/gotpcrel.test
deleted file mode 100644
index b6f83c16676d..000000000000
--- a/test/elf/gotpcrel.test
+++ /dev/null
@@ -1,21 +0,0 @@
-# This test checks that GOTPCREL entries are being handled properly
-RUN: lld -flavor 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/elf/gottpoff.test b/test/elf/gottpoff.test
deleted file mode 100644
index 9841ee1453d0..000000000000
--- a/test/elf/gottpoff.test
+++ /dev/null
@@ -1,120 +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 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 - 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
- Content: ''
- - Name: .tbss
- Type: SHT_NOBITS
- Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
- AddressAlign: 0x0000000000000004
- Content: '01000000002E7265'
- - 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/elf/group-cmd-search.test b/test/elf/group-cmd-search.test
deleted file mode 100644
index 5e153c1ac1ad..000000000000
--- a/test/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 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 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 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 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 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 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 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 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 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 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/elf/hexagon-quickdata-sort.test b/test/elf/hexagon-quickdata-sort.test
deleted file mode 100644
index efdf9480923d..000000000000
--- a/test/elf/hexagon-quickdata-sort.test
+++ /dev/null
@@ -1,12 +0,0 @@
-RUN: lld -flavor 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/elf/hexagon-quickdata-sortcommon.test b/test/elf/hexagon-quickdata-sortcommon.test
deleted file mode 100644
index 5b4690b43cb9..000000000000
--- a/test/elf/hexagon-quickdata-sortcommon.test
+++ /dev/null
@@ -1,16 +0,0 @@
-RUN: lld -flavor 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/elf/ifunc.test b/test/elf/ifunc.test
deleted file mode 100644
index c567c554cbbb..000000000000
--- a/test/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 gnu -target x86_64-linux --output-filetype=yaml -r \
-RUN: %p/Inputs/ifunc.x86-64 | FileCheck %s
-
-RUN: lld -flavor 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 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 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/elf/ignore-unknownoption.test b/test/elf/ignore-unknownoption.test
deleted file mode 100644
index 56856ed9f2e4..000000000000
--- a/test/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 gnu -target x86_64 --gc-sections 2> %t
-RUN: FileCheck %s < %t
-CHECK: warning: ignoring unknown argument: --gc-sections
diff --git a/test/elf/init_array-order.test b/test/elf/init_array-order.test
deleted file mode 100644
index b57b3807b69c..000000000000
--- a/test/elf/init_array-order.test
+++ /dev/null
@@ -1,67 +0,0 @@
-#RUN: yaml2obj -format=elf %s > %t
-#RUN: lld -flavor 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/elf/init_array.test b/test/elf/init_array.test
deleted file mode 100644
index 1acf4a7e7a28..000000000000
--- a/test/elf/init_array.test
+++ /dev/null
@@ -1,6 +0,0 @@
-RUN: lld -flavor gnu -target x86_64-linux -o %t %p/Inputs/init_array.x86-64 \
-RUN: -e __init_array_start
-RUN: llvm-objdump -t -section-headers %t | FileCheck %s
-
-CHECK: .init_array {{[0-9]+}} [[ADDR:[0-9]+]]
-CHECK: [[ADDR]] g *ABS* {{[0-9]+}} __init_array_start
diff --git a/test/elf/initfini-options.test-1.test b/test/elf/initfini-options.test-1.test
deleted file mode 100644
index 2fc1c3e32bda..000000000000
--- a/test/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 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/elf/initfini-options.test-2.test b/test/elf/initfini-options.test-2.test
deleted file mode 100644
index 4742084c513b..000000000000
--- a/test/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 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/elf/initfini-options.test-3.test b/test/elf/initfini-options.test-3.test
deleted file mode 100644
index bf8b216775d9..000000000000
--- a/test/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 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/elf/librarynotfound.test b/test/elf/librarynotfound.test
deleted file mode 100644
index faa1728b478b..000000000000
--- a/test/elf/librarynotfound.test
+++ /dev/null
@@ -1,5 +0,0 @@
-# Tests the functionality of library not found
-RUN: not lld -flavor gnu -lfn 2> %t1
-RUN: FileCheck %s < %t1
-
-CHECK: Unable to find library -lfn
diff --git a/test/elf/linker-as-ld.test b/test/elf/linker-as-ld.test
deleted file mode 100644
index 8ac75275f996..000000000000
--- a/test/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 -target x86_64-linux -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/elf/linkerscript/Inputs/prog1.o.yaml b/test/elf/linkerscript/Inputs/prog1.o.yaml
deleted file mode 100644
index ded590e395d4..000000000000
--- a/test/elf/linkerscript/Inputs/prog1.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: 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
- Content: ''
- - 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/elf/linkerscript/Inputs/prog2.o.yaml b/test/elf/linkerscript/Inputs/prog2.o.yaml
deleted file mode 100644
index f88b0ddc96b2..000000000000
--- a/test/elf/linkerscript/Inputs/prog2.o.yaml
+++ /dev/null
@@ -1,89 +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
- Content: ''
- - 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/elf/linkerscript/Inputs/prog3.o.yaml b/test/elf/linkerscript/Inputs/prog3.o.yaml
deleted file mode 100644
index 76aa22267f0b..000000000000
--- a/test/elf/linkerscript/Inputs/prog3.o.yaml
+++ /dev/null
@@ -1,52 +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
- Content: ''
-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/elf/linkerscript/Inputs/simple.o.yaml b/test/elf/linkerscript/Inputs/simple.o.yaml
deleted file mode 100644
index 91d4e1b57786..000000000000
--- a/test/elf/linkerscript/Inputs/simple.o.yaml
+++ /dev/null
@@ -1,52 +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
- Content: ''
-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/elf/linkerscript/externs.objtxt b/test/elf/linkerscript/externs.objtxt
deleted file mode 100644
index 154891eaf710..000000000000
--- a/test/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 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: 2^4
- 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/elf/linkerscript/invalid-script-cli-1.test b/test/elf/linkerscript/invalid-script-cli-1.test
deleted file mode 100644
index 904ba17557c0..000000000000
--- a/test/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 gnu -target x86_64 -T idonotexist.ls 2> %t.err
-RUN: FileCheck %s < %t.err
-
-RUN: not lld -flavor 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/elf/linkerscript/invalid-script-cli-2.test b/test/elf/linkerscript/invalid-script-cli-2.test
deleted file mode 100644
index 6e0e42adc71d..000000000000
--- a/test/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 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/elf/linkerscript/invalid.test b/test/elf/linkerscript/invalid.test
deleted file mode 100644
index 42833a6664ff..000000000000
--- a/test/elf/linkerscript/invalid.test
+++ /dev/null
@@ -1,5 +0,0 @@
-# Check for errors from invalid linker scripts
-RUN: not lld -flavor 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/elf/linkerscript/sections-order.test b/test/elf/linkerscript/sections-order.test
deleted file mode 100644
index 85a172cb07ad..000000000000
--- a/test/elf/linkerscript/sections-order.test
+++ /dev/null
@@ -1,97 +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 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
-*/
diff --git a/test/elf/linkerscript/sections-with-wildcards.test b/test/elf/linkerscript/sections-with-wildcards.test
deleted file mode 100644
index 6af80d0883de..000000000000
--- a/test/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 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/elf/linkerscript/symbol-definition.test b/test/elf/linkerscript/symbol-definition.test
deleted file mode 100644
index fc595bbe1f10..000000000000
--- a/test/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 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/elf/linkerscript/valid-script-cli.objtxt b/test/elf/linkerscript/valid-script-cli.objtxt
deleted file mode 100644
index b68d430fd98e..000000000000
--- a/test/elf/linkerscript/valid-script-cli.objtxt
+++ /dev/null
@@ -1,23 +0,0 @@
-# Check that the linker script inputs are accepted properly.
-
-# RUN: lld -flavor gnu -target x86_64 %p/Inputs/valid.ls -r %s \
-# RUN: --output-filetype=yaml | FileCheck %s
-
-# RUN: lld -flavor gnu -target x86_64 -T %p/Inputs/valid.ls -r %s \
-# RUN: --output-filetype=yaml | FileCheck %s
-
-# RUN: lld -flavor gnu -target x86_64 --script=%p/Inputs/valid.ls -r %s \
-# RUN: --output-filetype=yaml | FileCheck %s
-
-# RUN: lld -flavor 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: 2^4
- section-choice: custom-required
- section-name: .text
-
-# CHECK: _entry_point
diff --git a/test/elf/loginputfiles.test b/test/elf/loginputfiles.test
deleted file mode 100644
index 850570d8085e..000000000000
--- a/test/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 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/elf/mergeatoms.test b/test/elf/mergeatoms.test
deleted file mode 100644
index 521eb5a12c3c..000000000000
--- a/test/elf/mergeatoms.test
+++ /dev/null
@@ -1,6 +0,0 @@
-# Tests that atoms are merged by testing it with --merge-strings option
-RUN: lld -flavor 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/elf/mergeconstants.test b/test/elf/mergeconstants.test
deleted file mode 100644
index 3d06d2c94438..000000000000
--- a/test/elf/mergeconstants.test
+++ /dev/null
@@ -1,20 +0,0 @@
-# The test checks for mergeable strings that appear in the object file
-RUN: lld -flavor 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: 2^3
-mergeAtoms: references:
-mergeAtoms: - kind: R_X86_64_64
-mergeAtoms: offset: 3
-mergeAtoms: target: [[CONSTANT]]
diff --git a/test/elf/mergeglobalatoms.test b/test/elf/mergeglobalatoms.test
deleted file mode 100644
index e71dca539915..000000000000
--- a/test/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 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/elf/note.test b/test/elf/note.test
deleted file mode 100644
index f0e9c6b2f8d9..000000000000
--- a/test/elf/note.test
+++ /dev/null
@@ -1,49 +0,0 @@
-# Check that the linker is not ignoring input sections.
-# RUN: yaml2obj -format=elf %s > %t.obj
-# RUN: lld -flavor gnu -target x86_64 %t.obj -o %t.exe --noinhibit-exec
-# RUN: llvm-objdump -h %t.exe | FileCheck %s
-
-# CHECK: {{[0-9]+}} .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
- Content: ''
- - 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/elf/options/dynamic-linker.test b/test/elf/options/dynamic-linker.test
deleted file mode 100644
index 3d8feeb6e307..000000000000
--- a/test/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 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 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 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/elf/phdr.test b/test/elf/phdr.test
deleted file mode 100644
index c8ab73d31464..000000000000
--- a/test/elf/phdr.test
+++ /dev/null
@@ -1,99 +0,0 @@
-# This test checks emission for program header for ELF binaries
-RUN: lld -flavor 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 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/elf/quickdata.test b/test/elf/quickdata.test
deleted file mode 100644
index a07771517226..000000000000
--- a/test/elf/quickdata.test
+++ /dev/null
@@ -1,15 +0,0 @@
-RUN: lld -flavor 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/elf/reloc.test b/test/elf/reloc.test
deleted file mode 100644
index 0ecf0b174fe8..000000000000
--- a/test/elf/reloc.test
+++ /dev/null
@@ -1,38 +0,0 @@
-RUN: lld -flavor 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: 2^4
-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: 2^4
-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/elf/responsefile.test b/test/elf/responsefile.test
deleted file mode 100644
index 5957471bb661..000000000000
--- a/test/elf/responsefile.test
+++ /dev/null
@@ -1,6 +0,0 @@
-# RUN: not lld -flavor 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/elf/rodata.test b/test/elf/rodata.test
deleted file mode 100644
index dfe6985c0733..000000000000
--- a/test/elf/rodata.test
+++ /dev/null
@@ -1,5 +0,0 @@
-RUN: lld -flavor 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/elf/rosegment.test b/test/elf/rosegment.test
deleted file mode 100644
index 32638d8fce6f..000000000000
--- a/test/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 gnu -target x86_64 %p/Inputs/rodata.o -o %t1.elf \
-RUN: --noinhibit-exec
-RUN: lld -flavor 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/elf/sectionGroups/sectiongroup-new-members.test b/test/elf/sectionGroups/sectiongroup-new-members.test
deleted file mode 100644
index d270c5fec94a..000000000000
--- a/test/elf/sectionGroups/sectiongroup-new-members.test
+++ /dev/null
@@ -1,153 +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 gnu -target x86_64 %t.group1a.o %t.group1b.o \
-#RUN: --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
-#RUN: lld -flavor 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
- Content: ''
- - 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
- Content: ''
- - 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/elf/sectionGroups/sectiongroup-simple.test b/test/elf/sectionGroups/sectiongroup-simple.test
deleted file mode 100644
index 25be6033b0ef..000000000000
--- a/test/elf/sectionGroups/sectiongroup-simple.test
+++ /dev/null
@@ -1,146 +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 gnu -target x86_64 %t.group1a.o %t.group1b.o \
-#RUN: --noinhibit-exec --output-filetype=yaml -o %t2.out.yaml
-#RUN: lld -flavor 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
- Content: ''
- - 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
- Content: ''
- - 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/elf/sectionGroups/sectiongroup-undef-member-other.test b/test/elf/sectionGroups/sectiongroup-undef-member-other.test
deleted file mode 100644
index 78a5f276a4ca..000000000000
--- a/test/elf/sectionGroups/sectiongroup-undef-member-other.test
+++ /dev/null
@@ -1,158 +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 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
- Content: ''
- - 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
- Content: ''
- - 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/elf/sectionGroups/sectiongroup-undef-member.test b/test/elf/sectionGroups/sectiongroup-undef-member.test
deleted file mode 100644
index 2f6804d254d8..000000000000
--- a/test/elf/sectionGroups/sectiongroup-undef-member.test
+++ /dev/null
@@ -1,144 +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 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
- Content: ''
- - 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
- Content: ''
- - 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/elf/sectionGroups/sectiongroup-with-globalsymbols.test b/test/elf/sectionGroups/sectiongroup-with-globalsymbols.test
deleted file mode 100644
index 0a28e3c98907..000000000000
--- a/test/elf/sectionGroups/sectiongroup-with-globalsymbols.test
+++ /dev/null
@@ -1,253 +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 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 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: 2^4
-#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
- Content: ''
- - 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
- Content: ''
- - 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
- Content: ''
- - 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/elf/sectionGroups/sectiongroup-with-undef-external-reference.test b/test/elf/sectionGroups/sectiongroup-with-undef-external-reference.test
deleted file mode 100644
index a90034ae6d21..000000000000
--- a/test/elf/sectionGroups/sectiongroup-with-undef-external-reference.test
+++ /dev/null
@@ -1,239 +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 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 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
- Content: ''
- - 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
- Content: ''
- - 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
- Content: ''
- - 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/elf/sectionGroups/sectiongroup-with-undef-signature.test b/test/elf/sectionGroups/sectiongroup-with-undef-signature.test
deleted file mode 100644
index 11cb5de40a63..000000000000
--- a/test/elf/sectionGroups/sectiongroup-with-undef-signature.test
+++ /dev/null
@@ -1,222 +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 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 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
- Content: ''
- - 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
- Content: ''
- - 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
- Content: ''
- - 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/elf/sections.test b/test/elf/sections.test
deleted file mode 100644
index 8839aa6d4e8a..000000000000
--- a/test/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 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/elf/sh_addralign.test b/test/elf/sh_addralign.test
deleted file mode 100644
index 9c7a050f565c..000000000000
--- a/test/elf/sh_addralign.test
+++ /dev/null
@@ -1,38 +0,0 @@
-# Check handling of section alignment.
-# RUN: yaml2obj -format=elf %s > %t-obj
-# RUN: lld -flavor 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
- Content: ''
- 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/elf/soname.test b/test/elf/soname.test
deleted file mode 100644
index 79c089ec607c..000000000000
--- a/test/elf/soname.test
+++ /dev/null
@@ -1,6 +0,0 @@
-RUN: lld -flavor 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/elf/strip-all.test b/test/elf/strip-all.test
deleted file mode 100644
index 44a41c2a0d9f..000000000000
--- a/test/elf/strip-all.test
+++ /dev/null
@@ -1,107 +0,0 @@
-# Tests the --strip-all (-s) flag. We expect the symbol table to not contain
-# any symbol in the output file.
-#
-# 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 gnu -target x86_64 %t.o -e=main --strip-all -o %t1
-#RUN: llvm-readobj -dt %t1 | FileCheck -check-prefix CHECKSYMS %s
-
-#CHECKSYMS: @
-
----
-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
- Content: ''
- - 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/elf/stripped-empty.test b/test/elf/stripped-empty.test
deleted file mode 100644
index 0403808db2eb..000000000000
--- a/test/elf/stripped-empty.test
+++ /dev/null
@@ -1,4 +0,0 @@
-RUN: lld -flavor 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/elf/symbols.test b/test/elf/symbols.test
deleted file mode 100644
index 7f6bbdbc8c1d..000000000000
--- a/test/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 gnu -target i386 -e main %p/Inputs/writersyms.o -o %t1
-RUN: llvm-nm -n %t1 | FileCheck -check-prefix CHECKSYMS %s
-RUN: lld -flavor 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/elf/tls.test b/test/elf/tls.test
deleted file mode 100644
index 038889406b67..000000000000
--- a/test/elf/tls.test
+++ /dev/null
@@ -1,43 +0,0 @@
-# REQUIRES: x86
-
-# This tests verifies that TLS variables have correct offsets
-RUN: lld -flavor 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 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_PC32
-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/elf/tlsAddr.test b/test/elf/tlsAddr.test
deleted file mode 100644
index 6bc5e3e9bf78..000000000000
--- a/test/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 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/elf/undef-from-dso-to-main.test b/test/elf/undef-from-dso-to-main.test
deleted file mode 100644
index 71d0b51499dd..000000000000
--- a/test/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 gnu -target x86_64 -shared %t.o.so -o %T/libundef2.so
-#RUN: yaml2obj -format=elf %s -o=%t.o
-#RUN: lld -flavor 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
- Content: '002E7379'
-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/elf/undef-from-main-dso.test b/test/elf/undef-from-main-dso.test
deleted file mode 100644
index 43faef0e74c4..000000000000
--- a/test/elf/undef-from-main-dso.test
+++ /dev/null
@@ -1,43 +0,0 @@
-RUN: lld -flavor 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 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/elf/weaksym.test b/test/elf/weaksym.test
deleted file mode 100644
index 0e265028e5ed..000000000000
--- a/test/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 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/elf/wrap.test b/test/elf/wrap.test
deleted file mode 100644
index 997439f8f5b4..000000000000
--- a/test/elf/wrap.test
+++ /dev/null
@@ -1,279 +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 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 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
- Content: ''
- - 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
- Content: ''
- - 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
- Content: ''
- - 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/elf/x86-64-dynamic-relocs.test b/test/elf/x86-64-dynamic-relocs.test
deleted file mode 100644
index 325693e3f714..000000000000
--- a/test/elf/x86-64-dynamic-relocs.test
+++ /dev/null
@@ -1,26 +0,0 @@
-RUN: lld -flavor 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: 2^4
- 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 2^4
- 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/elf/x86-64-dynamic.test b/test/elf/x86-64-dynamic.test
deleted file mode 100644
index 4e24e954a20e..000000000000
--- a/test/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 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 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: 2^4
-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: 2^4
-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/elf/x86.test b/test/elf/x86.test
deleted file mode 100644
index 6b68837193e6..000000000000
--- a/test/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 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/elf/x86_64-kinds.test b/test/elf/x86_64-kinds.test
deleted file mode 100644
index 49586059d953..000000000000
--- a/test/elf/x86_64-kinds.test
+++ /dev/null
@@ -1,23 +0,0 @@
-REQUIRES: x86
-
-RUN: lld -flavor 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 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/lit.cfg b/test/lit.cfg
index 5b49765f7894..54e8c7f546f8 100644
--- a/test/lit.cfg
+++ b/test/lit.cfg
@@ -14,16 +14,43 @@ import lit.util
# name: The name of this test suite.
config.name = 'lld'
+# Tweak PATH for Win32
+if sys.platform in ['win32']:
+ # Seek sane tools in directories and set to $PATH.
+ path = getattr(config, 'lit_tools_dir', None)
+ path = lit_config.getToolsPath(path,
+ config.environment['PATH'],
+ ['cmp.exe', 'grep.exe', 'sed.exe'])
+ if path is not None:
+ path = os.path.pathsep.join((path,
+ config.environment['PATH']))
+ config.environment['PATH'] = path
+
+# Choose between lit's internal shell pipeline runner and a real shell. If
+# LIT_USE_INTERNAL_SHELL is in the environment, we use that as an override.
+use_lit_shell = os.environ.get("LIT_USE_INTERNAL_SHELL")
+if use_lit_shell:
+ # 0 is external, "" is default, and everything else is internal.
+ execute_external = (use_lit_shell == "0")
+else:
+ # Otherwise we default to internal on Windows and external elsewhere, as
+ # bash on Windows is usually very slow.
+ execute_external = (not sys.platform in ['win32'])
+
+
# testFormat: The test format to use to interpret tests.
#
# For now we require '&&' between commands, until they get globally killed and
# the test runner updated.
-execute_external = (platform.system() != 'Windows'
- or lit_config.getBashPath() not in [None, ""])
config.test_format = lit.formats.ShTest(execute_external)
# suffixes: A list of file extensions to treat as test files.
-config.suffixes = ['.objtxt', '.test']
+config.suffixes = ['.ll', '.objtxt', '.test']
+
+# excludes: A list of directories to exclude from the testsuite. The 'Inputs'
+# subdirectories contain auxiliary inputs for various tests in their parent
+# directories.
+config.excludes = ['Inputs']
# test_source_root: The root path where tests are located.
config.test_source_root = os.path.dirname(__file__)
@@ -112,6 +139,46 @@ if config.test_exec_root is None:
lit_config.load_config(config, site_cfg)
raise SystemExit
+# For each occurrence of a lld tool name as its own word, replace it
+# with the full path to the build directory holding that tool. This
+# ensures that we are testing the tools just built and not some random
+# tools that might happen to be in the user's PATH.
+
+# Regex assertions to reject neighbor hyphens/dots (seen in some tests).
+# For example, we want to prefix 'lld' and 'ld.lld' but not the 'lld' inside
+# of 'ld.lld'.
+NoPreJunk = r"(?<!(-|\.|/))"
+NoPostJunk = r"(?!(-|\.))"
+
+tool_patterns = [r"\bFileCheck\b",
+ r"\bnot\b",
+ NoPreJunk + r"\blld\b" + NoPostJunk,
+ r"\bld.lld\b",
+ r"\blld-link\b",
+ r"\bllvm-mc\b",
+ r"\bllvm-nm\b",
+ r"\bllvm-objdump\b",
+ r"\bllvm-readobj\b",
+ r"\byaml2obj\b"]
+
+for pattern in tool_patterns:
+ # Extract the tool name from the pattern. This relies on the tool
+ # name being surrounded by \b word match operators. If the
+ # pattern starts with "| ", include it in the string to be
+ # substituted.
+ tool_match = re.match(r"^(\\)?((\| )?)\W+b([0-9A-Za-z-_\.]+)\\b\W*$",
+ pattern)
+ tool_pipe = tool_match.group(2)
+ tool_name = tool_match.group(4)
+ tool_path = lit.util.which(tool_name, llvm_tools_dir)
+ if not tool_path:
+ # Warn, but still provide a substitution.
+ lit_config.note('Did not find ' + tool_name + ' in ' + llvm_tools_dir)
+ tool_path = llvm_tools_dir + '/' + tool_name
+ config.substitutions.append((pattern, tool_pipe + tool_path))
+
+###
+
# When running under valgrind, we mangle '-vg' onto the end of the triple so we
# can check it with XFAIL and XTARGET.
if lit_config.useValgrind:
@@ -148,12 +215,18 @@ if re.search(r'DEBUG', llvm_config_output_list[0]):
config.available_features.add('debug')
if re.search(r'ON', llvm_config_output_list[1]):
config.available_features.add('asserts')
-if re.search(r'ARM', llvm_config_output_list[2]):
+
+archs = llvm_config_output_list[2]
+if re.search(r'AArch64', archs):
+ config.available_features.add('aarch64')
+if re.search(r'ARM', archs):
config.available_features.add('arm')
-if re.search(r'Mips', llvm_config_output_list[2]):
+if re.search(r'Mips', archs):
config.available_features.add('mips')
-if re.search(r'X86', llvm_config_output_list[2]):
+if re.search(r'X86', archs):
config.available_features.add('x86')
+if re.search(r'PowerPC', archs):
+ config.available_features.add('ppc')
llvm_config_cmd.wait()
# Check if Windows resource file compiler exists.
@@ -163,5 +236,5 @@ if cvtres and rc:
config.available_features.add('winres')
# Check if "lib.exe" command exists.
-if lit.util.which('lib.exe', config.environment['PATH']):
+if lit.util.which('lib', config.environment['PATH']):
config.available_features.add('winlib')
diff --git a/test/mach-o/Inputs/PIE.yaml b/test/mach-o/Inputs/PIE.yaml
new file mode 100644
index 000000000000..0463154fcf28
--- /dev/null
+++ b/test/mach-o/Inputs/PIE.yaml
@@ -0,0 +1,6 @@
+--- !mach-o
+arch: x86_64
+file-type: MH_DYLIB
+install-name: /usr/lib/libSystem.B.dylib
+exports:
+ - name: dyld_stub_binder
diff --git a/test/mach-o/Inputs/arm-interworking.yaml b/test/mach-o/Inputs/arm-interworking.yaml
new file mode 100644
index 000000000000..d78a2997fe33
--- /dev/null
+++ b/test/mach-o/Inputs/arm-interworking.yaml
@@ -0,0 +1,83 @@
+--- !mach-o
+arch: armv7
+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 ]
+ alignment: 2
+ address: 0x0000000000000000
+ content: [ 0xFE, 0xFF, 0xFF, 0xEB, 0x02, 0x00, 0x00, 0xFA,
+ 0xFC, 0xFF, 0xFF, 0xEB, 0xFB, 0xFF, 0xFF, 0xFA,
+ 0x1E, 0xFF, 0x2F, 0xE1, 0x1E, 0xFF, 0x2F, 0xE1 ]
+ relocations:
+ - offset: 0x0000000C
+ type: ARM_RELOC_BR24
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 4
+ - offset: 0x00000008
+ type: ARM_RELOC_BR24
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 3
+ - offset: 0x00000004
+ type: ARM_RELOC_BR24
+ length: 2
+ pc-rel: true
+ extern: false
+ symbol: 1
+ - offset: 0x00000000
+ type: ARM_RELOC_BR24
+ length: 2
+ pc-rel: true
+ extern: false
+ symbol: 1
+ - segment: __DATA
+ section: __data
+ type: S_REGULAR
+ attributes: [ ]
+ address: 0x0000000000000018
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+ relocations:
+ - offset: 0x00000004
+ type: ARM_RELOC_VANILLA
+ length: 2
+ pc-rel: false
+ extern: false
+ symbol: 1
+ - offset: 0x00000000
+ type: ARM_RELOC_VANILLA
+ length: 2
+ pc-rel: false
+ extern: true
+ symbol: 3
+local-symbols:
+ - name: _d2
+ type: N_SECT
+ sect: 2
+ value: 0x0000000000000018
+global-symbols:
+ - name: _a1
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+ - name: _a2
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000014
+undefined-symbols:
+ - name: _t1
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+ - name: _t2
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
diff --git a/test/mach-o/Inputs/arm-shims.yaml b/test/mach-o/Inputs/arm-shims.yaml
new file mode 100644
index 000000000000..8baebef17d86
--- /dev/null
+++ b/test/mach-o/Inputs/arm-shims.yaml
@@ -0,0 +1,60 @@
+--- !mach-o
+arch: armv7
+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 ]
+ alignment: 2
+ address: 0x0000000000000000
+ content: [ 0x00, 0xBF, 0xFF, 0xF7, 0xFE, 0xEF, 0xFF, 0xF7,
+ 0xFB, 0xBF, 0x00, 0x00, 0x00, 0xF0, 0x20, 0xE3,
+ 0xFA, 0xFF, 0xFF, 0xFA, 0xF9, 0xFF, 0xFF, 0xEA ]
+ relocations:
+ - offset: 0x00000014
+ type: ARM_RELOC_BR24
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 3
+ - offset: 0x00000010
+ type: ARM_RELOC_BR24
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 3
+ - offset: 0x00000006
+ type: ARM_THUMB_RELOC_BR22
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 2
+ - offset: 0x00000002
+ type: ARM_THUMB_RELOC_BR22
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 2
+global-symbols:
+ - name: _a2
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x000000000000000C
+ - name: _t2
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ desc: [ N_ARM_THUMB_DEF ]
+ value: 0x0000000000000000
+undefined-symbols:
+ - name: _a1
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+ - name: _t1
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
diff --git a/test/mach-o/Inputs/cstring-sections.yaml b/test/mach-o/Inputs/cstring-sections.yaml
new file mode 100644
index 000000000000..eb227f29f8f5
--- /dev/null
+++ b/test/mach-o/Inputs/cstring-sections.yaml
@@ -0,0 +1,25 @@
+--- !mach-o
+arch: x86_64
+file-type: MH_OBJECT
+flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+has-UUID: false
+OS: unknown
+sections:
+ - segment: __TEXT
+ section: __objc_methname
+ type: S_CSTRING_LITERALS
+ attributes: [ ]
+ address: 0x0000000000000000
+ content: [ 0x61, 0x62, 0x63, 0x00 ]
+ - segment: __TEXT
+ section: __objc_classname
+ type: S_CSTRING_LITERALS
+ attributes: [ ]
+ address: 0x0000000000000006
+ content: [ 0x61, 0x62, 0x63, 0x00 ]
+ - segment: __TEXT
+ section: __cstring
+ type: S_CSTRING_LITERALS
+ attributes: [ ]
+ address: 0x000000000000000A
+ content: [ 0x61, 0x62, 0x63, 0x00 ]
diff --git a/test/mach-o/Inputs/got-order.yaml b/test/mach-o/Inputs/got-order.yaml
new file mode 100644
index 000000000000..d256e9d7d463
--- /dev/null
+++ b/test/mach-o/Inputs/got-order.yaml
@@ -0,0 +1,53 @@
+--- !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: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x8B, 0x0D, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x8B, 0x05, 0x00, 0x00,
+ 0x00, 0x00, 0x8B, 0x00, 0x03, 0x01, 0x48, 0x8B,
+ 0x0D, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x5D,
+ 0xC3 ]
+ relocations:
+ - offset: 0x00000019
+ type: X86_64_RELOC_GOT_LOAD
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 2
+ - offset: 0x0000000E
+ type: X86_64_RELOC_GOT_LOAD
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 1
+ - offset: 0x00000007
+ type: X86_64_RELOC_GOT_LOAD
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 3
+global-symbols:
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+undefined-symbols:
+ - name: _bar
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+ - name: _foo
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+ - name: _zazzle
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
diff --git a/test/mach-o/Inputs/got-order2.yaml b/test/mach-o/Inputs/got-order2.yaml
new file mode 100644
index 000000000000..faddeda924db
--- /dev/null
+++ b/test/mach-o/Inputs/got-order2.yaml
@@ -0,0 +1,11 @@
+--- !mach-o
+arch: x86_64
+file-type: MH_DYLIB
+install-name: /usr/lib/libfoobar.dylib
+exports:
+ - name: _bar
+ - name: _zazzle
+ - name: _foo
+ - name: _aaa
+ - name: _fff
+ - name: _zzz
diff --git a/test/mach-o/Inputs/hello-world-arm64.yaml b/test/mach-o/Inputs/hello-world-arm64.yaml
new file mode 100644
index 000000000000..31de71ef4941
--- /dev/null
+++ b/test/mach-o/Inputs/hello-world-arm64.yaml
@@ -0,0 +1,8 @@
+--- !mach-o
+arch: arm64
+file-type: MH_DYLIB
+install-name: /usr/lib/libSystem.B.dylib
+exports:
+ - name: _fprintf
+ - name: ___stdoutp
+ - name: dyld_stub_binder
diff --git a/test/mach-o/Inputs/hello-world-armv6.yaml b/test/mach-o/Inputs/hello-world-armv6.yaml
new file mode 100644
index 000000000000..0b29f65ab126
--- /dev/null
+++ b/test/mach-o/Inputs/hello-world-armv6.yaml
@@ -0,0 +1,7 @@
+--- !mach-o
+arch: armv6
+file-type: MH_DYLIB
+install-name: /usr/lib/libSystem.B.dylib
+exports:
+ - name: _printf
+ - name: dyld_stub_binder
diff --git a/test/mach-o/Inputs/hello-world-armv7.yaml b/test/mach-o/Inputs/hello-world-armv7.yaml
new file mode 100644
index 000000000000..4e26120fe216
--- /dev/null
+++ b/test/mach-o/Inputs/hello-world-armv7.yaml
@@ -0,0 +1,7 @@
+--- !mach-o
+arch: armv7
+file-type: MH_DYLIB
+install-name: /usr/lib/libSystem.B.dylib
+exports:
+ - name: _printf
+ - name: dyld_stub_binder
diff --git a/test/mach-o/Inputs/hello-world-x86.yaml b/test/mach-o/Inputs/hello-world-x86.yaml
new file mode 100644
index 000000000000..dbec62b77f3b
--- /dev/null
+++ b/test/mach-o/Inputs/hello-world-x86.yaml
@@ -0,0 +1,7 @@
+--- !mach-o
+arch: x86
+file-type: MH_DYLIB
+install-name: /usr/lib/libSystem.B.dylib
+exports:
+ - name: _printf
+ - name: dyld_stub_binder
diff --git a/test/mach-o/Inputs/hello-world-x86_64.yaml b/test/mach-o/Inputs/hello-world-x86_64.yaml
new file mode 100644
index 000000000000..7840d5c1932e
--- /dev/null
+++ b/test/mach-o/Inputs/hello-world-x86_64.yaml
@@ -0,0 +1,8 @@
+--- !mach-o
+arch: x86_64
+file-type: MH_DYLIB
+install-name: /usr/lib/libSystem.B.dylib
+exports:
+ - name: _fprintf
+ - name: dyld_stub_binder
+ - name: ___stdoutp
diff --git a/test/mach-o/Inputs/hw.raw_bytes b/test/mach-o/Inputs/hw.raw_bytes
new file mode 100644
index 000000000000..ce013625030b
--- /dev/null
+++ b/test/mach-o/Inputs/hw.raw_bytes
@@ -0,0 +1 @@
+hello
diff --git a/test/mach-o/Inputs/interposing-section.yaml b/test/mach-o/Inputs/interposing-section.yaml
new file mode 100644
index 000000000000..45966b6870cc
--- /dev/null
+++ b/test/mach-o/Inputs/interposing-section.yaml
@@ -0,0 +1,6 @@
+--- !mach-o
+arch: x86_64
+file-type: MH_DYLIB
+install-name: /usr/lib/libSystem.B.dylib
+exports:
+ - name: _open
diff --git a/test/mach-o/Inputs/lazy-bind-x86_64-2.yaml b/test/mach-o/Inputs/lazy-bind-x86_64-2.yaml
new file mode 100644
index 000000000000..50a97bc9c09b
--- /dev/null
+++ b/test/mach-o/Inputs/lazy-bind-x86_64-2.yaml
@@ -0,0 +1,8 @@
+--- !mach-o
+arch: x86_64
+file-type: MH_DYLIB
+install-name: /usr/lib/libfoo.dylib
+compat-version: 2.0
+current-version: 3.4
+exports:
+ - name: _foo
diff --git a/test/mach-o/Inputs/lazy-bind-x86_64-3.yaml b/test/mach-o/Inputs/lazy-bind-x86_64-3.yaml
new file mode 100644
index 000000000000..2f61cc0cda1a
--- /dev/null
+++ b/test/mach-o/Inputs/lazy-bind-x86_64-3.yaml
@@ -0,0 +1,8 @@
+--- !mach-o
+arch: x86_64
+file-type: MH_DYLIB
+install-name: /usr/lib/libbaz.dylib
+compat-version: 3.0
+current-version: 4.5
+exports:
+ - name: _baz
diff --git a/test/mach-o/Inputs/lazy-bind-x86_64.yaml b/test/mach-o/Inputs/lazy-bind-x86_64.yaml
new file mode 100644
index 000000000000..7e6cd9007bf3
--- /dev/null
+++ b/test/mach-o/Inputs/lazy-bind-x86_64.yaml
@@ -0,0 +1,8 @@
+--- !mach-o
+arch: x86_64
+file-type: MH_DYLIB
+install-name: /usr/lib/libbar.dylib
+compat-version: 1.0
+current-version: 2.3
+exports:
+ - name: _bar
diff --git a/test/mach-o/Inputs/linker-as-ld.yaml b/test/mach-o/Inputs/linker-as-ld.yaml
new file mode 100644
index 000000000000..0463154fcf28
--- /dev/null
+++ b/test/mach-o/Inputs/linker-as-ld.yaml
@@ -0,0 +1,6 @@
+--- !mach-o
+arch: x86_64
+file-type: MH_DYLIB
+install-name: /usr/lib/libSystem.B.dylib
+exports:
+ - name: dyld_stub_binder
diff --git a/test/mach-o/Inputs/re-exported-dylib-ordinal.yaml b/test/mach-o/Inputs/re-exported-dylib-ordinal.yaml
new file mode 100644
index 000000000000..1941b407de26
--- /dev/null
+++ b/test/mach-o/Inputs/re-exported-dylib-ordinal.yaml
@@ -0,0 +1,21 @@
+--- !mach-o
+arch: x86_64
+file-type: MH_DYLIB
+flags: [ MH_TWOLEVEL ]
+install-name: /junk/libfoo.dylib
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000F9A
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3 ]
+global-symbols:
+ - name: _foo
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000F9A
+dependents:
+ - path: /junk/libbar.dylib
+ kind: LC_REEXPORT_DYLIB
diff --git a/test/mach-o/Inputs/re-exported-dylib-ordinal2.yaml b/test/mach-o/Inputs/re-exported-dylib-ordinal2.yaml
new file mode 100644
index 000000000000..5aaf8c1b1bca
--- /dev/null
+++ b/test/mach-o/Inputs/re-exported-dylib-ordinal2.yaml
@@ -0,0 +1,18 @@
+--- !mach-o
+arch: x86_64
+file-type: MH_DYLIB
+flags: [ MH_TWOLEVEL ]
+install-name: /junk/libbar.dylib
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000F9A
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3 ]
+global-symbols:
+ - name: _bar
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000F9A
diff --git a/test/mach-o/Inputs/re-exported-dylib-ordinal3.yaml b/test/mach-o/Inputs/re-exported-dylib-ordinal3.yaml
new file mode 100644
index 000000000000..43ba07c73a7b
--- /dev/null
+++ b/test/mach-o/Inputs/re-exported-dylib-ordinal3.yaml
@@ -0,0 +1,19 @@
+--- !mach-o
+arch: x86_64
+file-type: MH_DYLIB
+flags: [ MH_TWOLEVEL ]
+install-name: /usr/lib/libSystem.B.dylib
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x55 ]
+
+global-symbols:
+ - name: dyld_stub_binder
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
diff --git a/test/mach-o/Inputs/unwind-info-simple-arm64.yaml b/test/mach-o/Inputs/unwind-info-simple-arm64.yaml
new file mode 100644
index 000000000000..5f7ae50717ba
--- /dev/null
+++ b/test/mach-o/Inputs/unwind-info-simple-arm64.yaml
@@ -0,0 +1,13 @@
+--- !mach-o
+arch: arm64
+file-type: MH_DYLIB
+install-name: /usr/lib/libc++.dylib
+exports:
+ - name: __Unwind_Resume
+ - name: __ZTIl
+ - name: __ZTIi
+ - name: ___cxa_end_catch
+ - name: ___cxa_begin_catch
+ - name: ___cxa_allocate_exception
+ - name: ___cxa_throw
+ - name: ___gxx_personality_v0
diff --git a/test/mach-o/Inputs/use-simple-dylib.yaml b/test/mach-o/Inputs/use-simple-dylib.yaml
new file mode 100644
index 000000000000..9081bcf76932
--- /dev/null
+++ b/test/mach-o/Inputs/use-simple-dylib.yaml
@@ -0,0 +1,58 @@
+--- !mach-o
+arch: x86_64
+file-type: MH_DYLIB
+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 ]
+ alignment: 4
+ address: 0x0000000000000000
+ content: [ 0xCC, 0xC3, 0x90, 0xC3, 0x90, 0x90, 0xC3, 0x90,
+ 0x90, 0x90, 0xC3, 0x90, 0x90, 0x90, 0x90, 0xC3,
+ 0x31, 0xC0, 0xC3 ]
+local-symbols:
+ - name: _myStatic
+ type: N_SECT
+ sect: 1
+ value: 0x000000000000000B
+ - name: _myVariablePreviouslyKnownAsPrivateExtern
+ type: N_SECT
+ scope: [ N_PEXT ]
+ sect: 1
+ desc: [ N_SYMBOL_RESOLVER ]
+ value: 0x0000000000000011
+global-symbols:
+ - name: _myGlobal
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000001
+ - name: _myGlobalWeak
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ desc: [ N_WEAK_DEF ]
+ value: 0x0000000000000002
+ - name: _myHidden
+ type: N_SECT
+ scope: [ N_EXT, N_PEXT ]
+ sect: 1
+ value: 0x0000000000000004
+ - name: _myHiddenWeak
+ type: N_SECT
+ scope: [ N_EXT, N_PEXT ]
+ sect: 1
+ desc: [ N_WEAK_DEF ]
+ value: 0x0000000000000007
+ - name: _myResolver
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ desc: [ N_SYMBOL_RESOLVER ]
+ value: 0x0000000000000010
+
+install-name: libspecial.dylib
diff --git a/test/mach-o/Inputs/write-final-sections.yaml b/test/mach-o/Inputs/write-final-sections.yaml
new file mode 100644
index 000000000000..ed434917f2cf
--- /dev/null
+++ b/test/mach-o/Inputs/write-final-sections.yaml
@@ -0,0 +1,20 @@
+--- !mach-o
+arch: x86_64
+file-type: MH_DYLIB
+flags: [ ]
+install-name: /usr/lib/libSystem.B.dylib
+sections:
+ - segment: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ address: 0x0000000000000000
+ content: [ 0x55 ]
+
+global-symbols:
+ - name: dyld_stub_binder
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+
diff --git a/test/mach-o/Inputs/wrong-arch-error.yaml b/test/mach-o/Inputs/wrong-arch-error.yaml
new file mode 100644
index 000000000000..304c872375e4
--- /dev/null
+++ b/test/mach-o/Inputs/wrong-arch-error.yaml
@@ -0,0 +1,24 @@
+# RUN: not lld -flavor darwin -arch x86_64 -r %s 2> %t.err
+# RUN: FileCheck %s < %t.err
+
+--- !mach-o
+arch: x86
+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 ]
+ alignment: 4
+ address: 0x0000000000000000
+ content: [ 0xC3 ]
+
+global-symbols:
+ - name: _bar
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
diff --git a/test/mach-o/PIE.yaml b/test/mach-o/PIE.yaml
index 2e50951a4544..24f8773cbd23 100644
--- a/test/mach-o/PIE.yaml
+++ b/test/mach-o/PIE.yaml
@@ -1,10 +1,13 @@
-# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t && \
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s \
+# RUN: %p/Inputs/PIE.yaml -o %t && \
# RUN: llvm-objdump -macho -private-headers %t | FileCheck %s
#
-# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -pie -o %t\
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s \
+# RUN: %p/Inputs/PIE.yaml -pie -o %t\
# RUN: && llvm-objdump -macho -private-headers %t | FileCheck %s
#
-# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -no_pie -o %t\
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s \
+# RUN: %p/Inputs/PIE.yaml -no_pie -o %t\
# RUN: && llvm-objdump -macho -private-headers %t \
# RUN: | FileCheck --check-prefix=CHECK_NO_PIE %s
#
@@ -31,13 +34,6 @@ global-symbols:
sect: 1
value: 0x0000000000000000
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: dyld_stub_binder
-
...
# CHECK: MH_MAGIC_64 {{[0-9a-zA-Z _]+}} TWOLEVEL PIE
diff --git a/test/mach-o/align_text.yaml b/test/mach-o/align_text.yaml
index 5ddbf911b9e5..66b5afb5ff30 100644
--- a/test/mach-o/align_text.yaml
+++ b/test/mach-o/align_text.yaml
@@ -13,7 +13,7 @@ sections:
section: __text
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- alignment: 4
+ alignment: 16
address: 0x0000000000000000
content: [ 0x90, 0x90, 0x90, 0xC3, 0xC3, 0xC3 ]
local-symbols:
@@ -33,13 +33,13 @@ local-symbols:
# CHECK: defined-atoms:
# CHECK: - content: [ 90, 90, 90 ]
-# CHECK: alignment: 2^4
+# CHECK: alignment: 16
# CHECK: - name: _f1
# CHECK: content: [ C3 ]
-# CHECK: alignment: 3 mod 2^4
+# CHECK: alignment: 3 mod 16
# CHECK: - name: _f2
# CHECK: content: [ C3 ]
-# CHECK: alignment: 4 mod 2^4
+# CHECK: alignment: 4 mod 16
# CHECK: - name: _f3
# CHECK: content: [ C3 ]
-# CHECK: alignment: 5 mod 2^4
+# CHECK: alignment: 5 mod 16
diff --git a/test/mach-o/arm-interworking-movw.yaml b/test/mach-o/arm-interworking-movw.yaml
index 59d2f0ddd3d9..7e4a2e00ae6e 100644
--- a/test/mach-o/arm-interworking-movw.yaml
+++ b/test/mach-o/arm-interworking-movw.yaml
@@ -20,16 +20,16 @@ sections:
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
alignment: 2
address: 0x0000000000000000
- content: [ 0x40, 0xF2, 0x25, 0x00, 0xC0, 0xF2, 0x00, 0x00,
- 0x40, 0xF2, 0x01, 0x01, 0xC0, 0xF2, 0x00, 0x01,
- 0x40, 0xF2, 0x4E, 0x02, 0xC0, 0xF2, 0x00, 0x02,
- 0x40, 0xF2, 0x2A, 0x03, 0xC0, 0xF2, 0x00, 0x03,
- 0x78, 0x44, 0x70, 0x47, 0x70, 0x47, 0x25, 0x00,
- 0x00, 0xE3, 0x00, 0x00, 0x40, 0xE3, 0xD7, 0x1F,
- 0x0F, 0xE3, 0xFF, 0x1F, 0x4F, 0xE3, 0x4E, 0x20,
- 0x00, 0xE3, 0x00, 0x20, 0x40, 0xE3, 0x00, 0x30,
- 0x00, 0xE3, 0x00, 0x30, 0x40, 0xE3, 0x0F, 0x00,
- 0x80, 0xE0, 0x1E, 0xFF, 0x2F, 0xE1, 0x1E, 0xFF,
+ content: [ 0x40, 0xF2, 0x25, 0x00, 0xC0, 0xF2, 0x00, 0x00,
+ 0x40, 0xF2, 0x01, 0x01, 0xC0, 0xF2, 0x00, 0x01,
+ 0x40, 0xF2, 0x4E, 0x02, 0xC0, 0xF2, 0x00, 0x02,
+ 0x40, 0xF2, 0x2A, 0x03, 0xC0, 0xF2, 0x00, 0x03,
+ 0x78, 0x44, 0x70, 0x47, 0x70, 0x47, 0x25, 0x00,
+ 0x00, 0xE3, 0x00, 0x00, 0x40, 0xE3, 0xD7, 0x1F,
+ 0x0F, 0xE3, 0xFF, 0x1F, 0x4F, 0xE3, 0x4E, 0x20,
+ 0x00, 0xE3, 0x00, 0x20, 0x40, 0xE3, 0x00, 0x30,
+ 0x00, 0xE3, 0x00, 0x30, 0x40, 0xE3, 0x0F, 0x00,
+ 0x80, 0xE0, 0x1E, 0xFF, 0x2F, 0xE1, 0x1E, 0xFF,
0x2F, 0xE1 ]
relocations:
- offset: 0x00000042
diff --git a/test/mach-o/arm-interworking.yaml b/test/mach-o/arm-interworking.yaml
index f7e04e65c9f0..59c46050fab5 100644
--- a/test/mach-o/arm-interworking.yaml
+++ b/test/mach-o/arm-interworking.yaml
@@ -1,7 +1,8 @@
-# RUN: lld -flavor darwin -arch armv7 -r -print_atoms %s -o %t | FileCheck %s \
+# RUN: lld -flavor darwin -arch armv7 -r -print_atoms %s \
+# RUN: %p/Inputs/arm-interworking.yaml -o %t | FileCheck %s \
# RUN: && lld -flavor darwin -arch armv7 -dylib -print_atoms \
# RUN: %p/Inputs/libSystem.yaml %t -o %t2 | FileCheck %s \
-# RUN: && macho-dump --dump-section-data %t2 | FileCheck -check-prefix=CODE %s
+# RUN: && llvm-readobj -s -sd %t2 | FileCheck -check-prefix=CODE %s
#
# Test thumb and arm branches round trip through -r.
# Test bl/blx instructions are fixed up properly.
@@ -12,20 +13,20 @@
arch: armv7
file-type: MH_OBJECT
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
+sections:
- segment: __TEXT
section: __text
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
alignment: 2
address: 0x0000000000000000
- content: [ 0xFF, 0xF7, 0xFE, 0xFF, 0xC0, 0x46, 0xFF, 0xF7,
- 0xFC, 0xEF, 0xC0, 0x46, 0xFF, 0xF7, 0xF8, 0xEF,
- 0xFF, 0xF7, 0xF6, 0xFF, 0xC0, 0x46, 0xFF, 0xF7,
- 0xF3, 0xFF, 0xC0, 0x46, 0x00, 0xF0, 0x06, 0xE8,
- 0xC0, 0x46, 0x00, 0xF0, 0x03, 0xF8, 0x00, 0xF0,
+ content: [ 0xFF, 0xF7, 0xFE, 0xFF, 0xC0, 0x46, 0xFF, 0xF7,
+ 0xFC, 0xEF, 0xC0, 0x46, 0xFF, 0xF7, 0xF8, 0xEF,
+ 0xFF, 0xF7, 0xF6, 0xFF, 0xC0, 0x46, 0xFF, 0xF7,
+ 0xF3, 0xFF, 0xC0, 0x46, 0x00, 0xF0, 0x06, 0xE8,
+ 0xC0, 0x46, 0x00, 0xF0, 0x03, 0xF8, 0x00, 0xF0,
0x02, 0xF8, 0x70, 0x47, 0x70, 0x47, 0x70, 0x47 ]
- relocations:
+ relocations:
- offset: 0x00000026
type: ARM_THUMB_RELOC_BR22
length: 2
@@ -80,7 +81,7 @@ sections:
attributes: [ ]
address: 0x0000000000000030
content: [ 0x2D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
+ relocations:
- offset: 0x00000004
type: ARM_RELOC_VANILLA
length: 2
@@ -93,7 +94,7 @@ sections:
pc-rel: false
extern: false
symbol: 1
-local-symbols:
+local-symbols:
- name: _t3
type: N_SECT
sect: 1
@@ -103,7 +104,7 @@ local-symbols:
type: N_SECT
sect: 2
value: 0x0000000000000030
-global-symbols:
+global-symbols:
- name: _t1
type: N_SECT
scope: [ N_EXT ]
@@ -116,7 +117,7 @@ global-symbols:
sect: 1
desc: [ N_ARM_THUMB_DEF ]
value: 0x000000000000002C
-undefined-symbols:
+undefined-symbols:
- name: _a1
type: N_UNDF
scope: [ N_EXT ]
@@ -126,96 +127,13 @@ undefined-symbols:
scope: [ N_EXT ]
value: 0x0000000000000000
---- !mach-o
-arch: armv7
-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 ]
- alignment: 2
- address: 0x0000000000000000
- content: [ 0xFE, 0xFF, 0xFF, 0xEB, 0x02, 0x00, 0x00, 0xFA,
- 0xFC, 0xFF, 0xFF, 0xEB, 0xFB, 0xFF, 0xFF, 0xFA,
- 0x1E, 0xFF, 0x2F, 0xE1, 0x1E, 0xFF, 0x2F, 0xE1 ]
- relocations:
- - offset: 0x0000000C
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: true
- symbol: 4
- - offset: 0x00000008
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: true
- symbol: 3
- - offset: 0x00000004
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: false
- symbol: 1
- - offset: 0x00000000
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: false
- symbol: 1
- - segment: __DATA
- section: __data
- type: S_REGULAR
- attributes: [ ]
- address: 0x0000000000000018
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
- - offset: 0x00000004
- type: ARM_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: false
- symbol: 1
- - offset: 0x00000000
- type: ARM_RELOC_VANILLA
- length: 2
- pc-rel: false
- extern: true
- symbol: 3
-local-symbols:
- - name: _d2
- type: N_SECT
- sect: 2
- value: 0x0000000000000018
-global-symbols:
- - name: _a1
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
- - name: _a2
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000014
-undefined-symbols:
- - name: _t1
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _t2
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
...
-# CHECK: defined-atoms:
+# CHECK: defined-atoms:
# CHECK: - name: _d1
# CHECK: type: data
-# CHECK: references:
+# CHECK: references:
# CHECK: - kind: pointer32
# CHECK: offset: 0
# CHECK: target: _t2
@@ -224,7 +142,7 @@ undefined-symbols:
# CHECK: target: _a1
# CHECK: - name: _d2
# CHECK: type: data
-# CHECK: references:
+# CHECK: references:
# CHECK: - kind: pointer32
# CHECK: offset: 0
# CHECK: target: _t1
@@ -233,7 +151,7 @@ undefined-symbols:
# CHECK: target: _a1
# CHECK: - name: _t1
# CHECK: scope: global
-# CHECK: references:
+# CHECK: references:
# CHECK: - kind: modeThumbCode
# CHECK: offset: 0
# CHECK: target: _t1
@@ -264,19 +182,19 @@ undefined-symbols:
# CHECK: - name: _t2
# CHECK: scope: global
# CHECK: content: [ 70, 47 ]
-# CHECK: references:
+# CHECK: references:
# CHECK: - kind: modeThumbCode
# CHECK: offset: 0
# CHECK: target: _t2
# CHECK: - name: _t3
# CHECK: content: [ 70, 47 ]
-# CHECK: references:
+# CHECK: references:
# CHECK: - kind: modeThumbCode
# CHECK: offset: 0
# CHECK: target: _t3
# CHECK: - name: _a1
# CHECK: scope: global
-# CHECK: references:
+# CHECK: references:
# CHECK: - kind: arm_bl24
# CHECK: offset: 0
# CHECK: target: _a1
@@ -292,15 +210,23 @@ undefined-symbols:
# CHECK: - name: _a2
# CHECK: scope: global
+# CODE: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00)
+# CODE: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00)
+# CODE: SectionData (
+# CODE: 0000: 00F016E8 C04600F0 1EE8C046 00F01AE8
+# CODE: 0010: FFF7F6FF C046FFF7 F3FFC046 00F006F8
+# CODE: 0020: C04600F0 03F800F0 02F87047 70477047
+# CODE: 0030: FEFFFFEB 020000EB F0FFFFFA FAFFFFFA
+# CODE: 0040: 1EFF2FE1 1EFF2FE1
+# CODE: )
-# CODE: (('section_name', '__text\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
-# CODE: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
-# CODE: ('_section_data', '00f016e8 c04600f0 1ee8c046 00f01ae8 fff7f6ff c046fff7 f3ffc046 00f006f8 c04600f0 03f800f0 02f87047 70477047 feffffeb 020000eb f0fffffa fafffffa 1eff2fe1 1eff2fe1')
-# When we get a good mach-o disassembler the above __text section content check can be change to be symbolic.
+# CODE: Name: __data (5F 5F 64 61 74 61 00 00 00 00 00 00 00 00 00 00)
+# CODE: Segment: __DATA (5F 5F 44 41 54 41 00 00 00 00 00 00 00 00 00 00)
+# CODE: SectionData (
+# CODE: 0000: E50F0000 E80F0000 B90F0000 E80F0000
+# CODE: )
-# CODE: (('section_name', '__data\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
-# CODE: ('segment_name', '__DATA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
-# CODE: ('_section_data', '{{[0-9a-f]}}{{[13579bdf]}}{{[0-9a-f]+}} {{[0-9a-f]}}{{[02468ade]}}{{[0-9a-f]+}} {{[0-9a-f]}}{{[13579bdf]}}{{[0-9a-f]+}} {{[0-9a-f]}}{{[02468ade]}}{{[0-9a-f]+}}')
+# When we get a good mach-o disassembler the above __text section content check can be change to be symbolic.
# Verify the low (thumb) bit is set on the first and third pointers but not the second and fourth.
@@ -325,18 +251,18 @@ undefined-symbols:
# nop
# blx _t2
# bx lr
-#
+#
# .globl _t2
# .thumb_func _t2
#_t2:
# bx lr
-#
+#
# .data
#_d1: .long _t2
# .long _a1
-
-
+
+
# Input file two:
#
# .align 2
@@ -348,15 +274,15 @@ undefined-symbols:
# bl _t1
# blx _t2
# bx lr
-#
+#
# .globl _a2
#_a2:
# bx lr
-#
+#
# .data
#_d2: .long _t1
# .long _a1
- \ No newline at end of file
+
diff --git a/test/mach-o/arm-shims.yaml b/test/mach-o/arm-shims.yaml
index 68a401ca78e8..62739c967ab1 100644
--- a/test/mach-o/arm-shims.yaml
+++ b/test/mach-o/arm-shims.yaml
@@ -1,5 +1,6 @@
-# RUN: lld -flavor darwin -arch armv7 %s -dylib %p/Inputs/libSystem.yaml -o %t
-# RUN: macho-dump --dump-section-data %t | FileCheck %s
+# RUN: lld -flavor darwin -arch armv7 %s %p/Inputs/arm-shims.yaml \
+# RUN: -dylib %p/Inputs/libSystem.yaml -o %t
+# RUN: llvm-readobj -s -sd %t | FileCheck %s
#
# Test b from arm to thumb or vice versa has shims added.s
#
@@ -66,74 +67,20 @@ undefined-symbols:
scope: [ N_EXT ]
value: 0x0000000000000000
-
---- !mach-o
-arch: armv7
-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 ]
- alignment: 2
- address: 0x0000000000000000
- content: [ 0x00, 0xBF, 0xFF, 0xF7, 0xFE, 0xEF, 0xFF, 0xF7,
- 0xFB, 0xBF, 0x00, 0x00, 0x00, 0xF0, 0x20, 0xE3,
- 0xFA, 0xFF, 0xFF, 0xFA, 0xF9, 0xFF, 0xFF, 0xEA ]
- relocations:
- - offset: 0x00000014
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: true
- symbol: 3
- - offset: 0x00000010
- type: ARM_RELOC_BR24
- length: 2
- pc-rel: true
- extern: true
- symbol: 3
- - offset: 0x00000006
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
- - offset: 0x00000002
- type: ARM_THUMB_RELOC_BR22
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
-global-symbols:
- - name: _a2
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x000000000000000C
- - name: _t2
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ N_ARM_THUMB_DEF ]
- value: 0x0000000000000000
-undefined-symbols:
- - name: _a1
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _t1
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-
...
-
-# CHECK: (('section_name', '__text\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
-# CHECK: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
-# CHECK: ('_section_data', '00bf00f0 10e800f0 19b80000 00f020e3 000000fa 0f0000ea 00bffff7 f8ef00f0 07b80000 00f020e3 f4fffffa 050000ea dff804c0 ff446047 d4ffffff dff804c0 ff446047 e0ffffff 04c09fe5 0cc08fe0 1cff2fe1 adffffff 04c09fe5 0cc08fe0 1cff2fe1 b5ffffff')
+# CHECK: Section {
+# CHECK: Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00)
+# CHECK: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00)
+# CHECK: SectionData (
+# CHECK: 0000: 00BF00F0 10E800F0 19B80000 00F020E3
+# CHECK: 0010: 000000FA 0F0000EA 00BFFFF7 F8EF00F0
+# CHECK: 0020: 07B80000 00F020E3 F4FFFFFA 050000EA
+# CHECK: 0030: DFF804C0 FF446047 D4FFFFFF DFF804C0
+# CHECK: 0040: FF446047 E0FFFFFF 04C09FE5 0CC08FE0
+# CHECK: 0050: 1CFF2FE1 ADFFFFFF 04C09FE5 0CC08FE0
+# CHECK: 0060: 1CFF2FE1 B5FFFFFF
+# CHECK: )
# When we get a good mach-o disassembler the above __text section content check can be change to be symbolic.
diff --git a/test/mach-o/arm-subsections-via-symbols.yaml b/test/mach-o/arm-subsections-via-symbols.yaml
index b704568f37b1..23c2847e6c77 100644
--- a/test/mach-o/arm-subsections-via-symbols.yaml
+++ b/test/mach-o/arm-subsections-via-symbols.yaml
@@ -18,8 +18,8 @@ sections:
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
alignment: 2
address: 0x0000000000000000
- content: [ 0x04, 0x10, 0x9F, 0xE5, 0x04, 0x20, 0x9F, 0xE5,
- 0x1E, 0xFF, 0x2F, 0xE1, 0x78, 0x56, 0x34, 0x12,
+ content: [ 0x04, 0x10, 0x9F, 0xE5, 0x04, 0x20, 0x9F, 0xE5,
+ 0x1E, 0xFF, 0x2F, 0xE1, 0x78, 0x56, 0x34, 0x12,
0x21, 0x43, 0x65, 0x87 ]
local-symbols:
- name: constants1
diff --git a/test/mach-o/arm64-reloc-negDelta32-fixup.yaml b/test/mach-o/arm64-reloc-negDelta32-fixup.yaml
new file mode 100644
index 000000000000..87708a0db12b
--- /dev/null
+++ b/test/mach-o/arm64-reloc-negDelta32-fixup.yaml
@@ -0,0 +1,124 @@
+# RUN: lld -flavor darwin -arch arm64 -r %s -o %t
+# RUN: lld -flavor darwin -arch arm64 -r %t -o %t2
+# RUN: llvm-objdump -s -section="__eh_frame" %t | FileCheck %s
+# RUN: llvm-objdump -s -section="__eh_frame" %t2 | FileCheck %s
+
+# The reference from FDE->CIE is implicitly created as a negDelta32.
+# We don't emit these in to the binary as relocations, so we need to
+# make sure that the offset in the FDE to the CIE is the correct value.
+# CHECK: 0010 10000000 00000000 017a5200 01781e01
+# CHECK: 0020 100c1f00 20000000 18000000 e4ffffff
+# Note, this one that matters ^~~~~~~~
+# It needs to be 0x18 as that is the offset back to 0 where the CIE is.
+# CHECK: 0030 ffffffff 20000000 00000000 00480e10
+# CHECK: 0040 9e019d02 00000000
+
+--- !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: [ 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91,
+ 0x00, 0x00, 0x00, 0x90, 0x00, 0x00, 0x00, 0x91,
+ 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x80, 0x52,
+ 0xFD, 0x7B, 0xC1, 0xA8, 0xC0, 0x03, 0x5F, 0xD6 ]
+ relocations:
+ - offset: 0x00000010
+ type: ARM64_RELOC_BRANCH26
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 6
+ - offset: 0x0000000C
+ type: ARM64_RELOC_PAGEOFF12
+ length: 2
+ pc-rel: false
+ extern: true
+ symbol: 1
+ - offset: 0x00000008
+ type: ARM64_RELOC_PAGE21
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 1
+ - segment: __TEXT
+ section: __cstring
+ type: S_CSTRING_LITERALS
+ attributes: [ ]
+ address: 0x0000000000000020
+ content: [ 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x77, 0x6F,
+ 0x72, 0x6C, 0x64, 0x00 ]
+ - segment: __LD
+ section: __compact_unwind
+ type: S_REGULAR
+ attributes: [ ]
+ alignment: 8
+ address: 0x0000000000000030
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 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: 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: 0x0000000000000050
+ content: [ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x7A, 0x52, 0x00, 0x01, 0x78, 0x1E, 0x01,
+ 0x10, 0x0C, 0x1F, 0x00, 0x20, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0xE4, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0xFF, 0xFF, 0xFF, 0x20, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x48, 0x0E, 0x10,
+ 0x9E, 0x01, 0x9D, 0x02, 0x00, 0x00, 0x00, 0x00 ]
+local-symbols:
+ - name: ltmp0
+ type: N_SECT
+ sect: 1
+ value: 0x0000000000000000
+ - name: L_str
+ type: N_SECT
+ sect: 2
+ value: 0x0000000000000020
+ - name: ltmp1
+ type: N_SECT
+ sect: 2
+ value: 0x0000000000000020
+ - name: ltmp2
+ type: N_SECT
+ sect: 3
+ value: 0x0000000000000030
+ - name: ltmp3
+ type: N_SECT
+ sect: 4
+ value: 0x0000000000000050
+global-symbols:
+ - name: __Z3fooi
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+undefined-symbols:
+ - name: _puts
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+page-size: 0x00000000
+...
diff --git a/test/mach-o/arm64-relocs-errors-delta64-offset.yaml b/test/mach-o/arm64-relocs-errors-delta64-offset.yaml
new file mode 100644
index 000000000000..09c596124893
--- /dev/null
+++ b/test/mach-o/arm64-relocs-errors-delta64-offset.yaml
@@ -0,0 +1,65 @@
+# RUN: not lld -flavor darwin -arch arm64 %s -r \
+# RUN: 2> %t.err
+# RUN: FileCheck %s < %t.err
+
+
+--- !mach-o
+arch: arm64
+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 ]
+ alignment: 4
+ address: 0x0000000000000000
+ content: [ 0xFF, 0x83, 0x00, 0xD1, 0xE0, 0x0B, 0x00, 0xF9,
+ 0x08, 0x00, 0x40, 0xB9, 0x08, 0x0D, 0x00, 0x71,
+ 0x08, 0x09, 0x00, 0x71, 0xE8, 0x0F, 0x00, 0xB9,
+ 0xC8, 0x00, 0x00, 0x54, 0x01, 0x00, 0x00, 0x14,
+ 0xE8, 0x03, 0x00, 0x32, 0x08, 0x01, 0x00, 0x12,
+ 0xE8, 0x7F, 0x00, 0x39, 0x02, 0x00, 0x00, 0x14 ]
+ - segment: __DATA
+ section: __data
+ type: S_REGULAR
+ attributes: [ ]
+ alignment: 3
+ address: 0x000000000001C348
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x10, 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:
+
+# Make sure that the offsets of the subtractor and unsigned both match.
+# CHECK: bad relocation (paired relocs must have the same offset) in section __DATA/__data (r1_address=1, r1_type=1, r1_extern=1, r1_length=3, r1_pcrel=0, r1_symbolnum=1), (r2_address=0, r2_type=0, r2_extern=1, r2_length=3, r2_pcrel=0, r2_symbolnum=1)
+ - offset: 0x00000001
+ type: ARM64_RELOC_SUBTRACTOR
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 1
+ - offset: 0x00000000
+ type: ARM64_RELOC_UNSIGNED
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 1
+global-symbols:
+ - name: _f1
+ type: N_SECT
+ sect: 2
+ value: 0x000000000001C348
+ - name: _f2
+ type: N_SECT
+ sect: 1
+ value: 0x0000000000000010
+ - name: _f3
+ type: N_SECT
+ sect: 1
+ value: 0x0000000000000020
diff --git a/test/mach-o/cstring-sections.yaml b/test/mach-o/cstring-sections.yaml
index 940f048b5c6c..433dffcf62d9 100644
--- a/test/mach-o/cstring-sections.yaml
+++ b/test/mach-o/cstring-sections.yaml
@@ -27,32 +27,6 @@ sections:
address: 0x000000000000000A
content: [ 0x61, 0x62, 0x63, 0x00, 0x6A, 0x6B, 0x6C, 0x00 ]
---- !mach-o
-arch: x86_64
-file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-has-UUID: false
-OS: unknown
-sections:
- - segment: __TEXT
- section: __objc_methname
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x0000000000000000
- content: [ 0x61, 0x62, 0x63, 0x00 ]
- - segment: __TEXT
- section: __objc_classname
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x0000000000000006
- content: [ 0x61, 0x62, 0x63, 0x00 ]
- - segment: __TEXT
- section: __cstring
- type: S_CSTRING_LITERALS
- attributes: [ ]
- address: 0x000000000000000A
- content: [ 0x61, 0x62, 0x63, 0x00 ]
-
...
diff --git a/test/mach-o/data-only-dylib.yaml b/test/mach-o/data-only-dylib.yaml
index c285066ad778..8d2143047452 100644
--- a/test/mach-o/data-only-dylib.yaml
+++ b/test/mach-o/data-only-dylib.yaml
@@ -16,7 +16,7 @@ sections:
alignment: 2
address: 0x0000000000000000
content: [ 0x00, 0x00, 0x00, 0x00 ]
-global-symbols:
+global-symbols:
- name: _myData
type: N_SECT
scope: [ N_EXT ]
diff --git a/test/mach-o/demangle.yaml b/test/mach-o/demangle.yaml
index 640545808477..f8a76cddd29f 100644
--- a/test/mach-o/demangle.yaml
+++ b/test/mach-o/demangle.yaml
@@ -21,7 +21,7 @@ sections:
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
- content: [ 0xE8, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00,
+ content: [ 0xE8, 0x00, 0x00, 0x00, 0x00, 0xE8, 0x00, 0x00,
0x00, 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00 ]
relocations:
- offset: 0x0000000B
diff --git a/test/mach-o/dylib-exports.yaml b/test/mach-o/dylib-exports.yaml
deleted file mode 100644
index 0a00dfe1e952..000000000000
--- a/test/mach-o/dylib-exports.yaml
+++ /dev/null
@@ -1,41 +0,0 @@
-# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 -dylib \
-# RUN: %s %p/Inputs/libSystem.yaml -o %t && \
-# RUN: llvm-objdump -exports-trie %t | FileCheck %s
-#
-#
-# Tests that exports trie builds properly.
-#
-
---- !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: [ 0xC3, 0xC3, 0xC3 ]
-global-symbols:
- - name: _myHidden
- type: N_SECT
- scope: [ N_EXT, N_PEXT ]
- sect: 1
- value: 0x0000000000000000
- - name: _myRegular
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000001
- - name: _myWeak
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ N_WEAK_DEF ]
- value: 0x0000000000000002
-...
-
-# CHECK-NOT: _myHidden
-# CHECK: _myRegular
-# CHECK: _myWeak [weak_def]
diff --git a/test/mach-o/executable-exports.yaml b/test/mach-o/executable-exports.yaml
new file mode 100644
index 000000000000..b14e2d229296
--- /dev/null
+++ b/test/mach-o/executable-exports.yaml
@@ -0,0 +1,46 @@
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 \
+# RUN: %s %p/Inputs/libSystem.yaml -o %t && \
+# RUN: llvm-objdump -exports-trie %t | FileCheck %s
+#
+#
+# Tests that exports trie builds properly.
+#
+
+--- !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: [ 0xC3, 0xC3, 0xC3, 0xC3 ]
+global-symbols:
+ - name: _myHidden
+ type: N_SECT
+ scope: [ N_EXT, N_PEXT ]
+ sect: 1
+ value: 0x0000000000000000
+ - name: _myRegular
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000001
+ - name: _myWeak
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ desc: [ N_WEAK_DEF ]
+ value: 0x0000000000000002
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000003
+...
+
+# CHECK-NOT: _myHidden
+# CHECK: 0x00000FFD _myRegular
+# CHECK: 0x00000FFE _myWeak [weak_def]
diff --git a/test/mach-o/exported_symbols_list-dylib.yaml b/test/mach-o/exported_symbols_list-dylib.yaml
index 71121d7400f6..f52614038ca4 100644
--- a/test/mach-o/exported_symbols_list-dylib.yaml
+++ b/test/mach-o/exported_symbols_list-dylib.yaml
@@ -31,7 +31,7 @@ sections:
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
0x89, 0xE5, 0x5D, 0xC3 ]
- segment: __DATA
section: __data
diff --git a/test/mach-o/exported_symbols_list-obj.yaml b/test/mach-o/exported_symbols_list-obj.yaml
index 735162dfedc8..31b325c7387b 100644
--- a/test/mach-o/exported_symbols_list-obj.yaml
+++ b/test/mach-o/exported_symbols_list-obj.yaml
@@ -21,7 +21,7 @@ sections:
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
0x89, 0xE5, 0x5D, 0xC3 ]
- segment: __DATA
section: __data
diff --git a/test/mach-o/exported_symbols_list-undef.yaml b/test/mach-o/exported_symbols_list-undef.yaml
index c6a8d8f4022f..1e2fc821c365 100644
--- a/test/mach-o/exported_symbols_list-undef.yaml
+++ b/test/mach-o/exported_symbols_list-undef.yaml
@@ -14,7 +14,7 @@ sections:
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
0x89, 0xE5, 0x5D, 0xC3 ]
- segment: __DATA
section: __data
diff --git a/test/mach-o/fat-archive.yaml b/test/mach-o/fat-archive.yaml
index 5db7fd96ff0e..86828d6a12b7 100644
--- a/test/mach-o/fat-archive.yaml
+++ b/test/mach-o/fat-archive.yaml
@@ -16,11 +16,11 @@ sections:
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
alignment: 4
address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x10,
- 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xB0,
- 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x31, 0xC0,
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x10,
+ 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xB0,
+ 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x31, 0xC0,
0x48, 0x83, 0xC4, 0x10, 0x5D, 0xC3 ]
- relocations:
+ relocations:
- offset: 0x00000012
type: X86_64_RELOC_BRANCH
length: 2
diff --git a/test/mach-o/flat_namespace_undef_error.yaml b/test/mach-o/flat_namespace_undef_error.yaml
new file mode 100644
index 000000000000..904b9c776e59
--- /dev/null
+++ b/test/mach-o/flat_namespace_undef_error.yaml
@@ -0,0 +1,17 @@
+# RUN: not lld -flavor darwin -arch x86_64 -macosx_version_min 10.9 -flat_namespace -undefined error %s -o %t %p/Inputs/libSystem.yaml 2>&1 | FileCheck %s
+
+--- !native
+defined-atoms:
+ - name: _main
+ scope: global
+ content: [ E9, 00, 00, 00, 00 ]
+ alignment: 16
+ references:
+ - kind: branch32
+ offset: 1
+ target: _bar
+undefined-atoms:
+ - name: _bar
+
+# Make sure we error out for -flat_namespace -undefined error.
+# CHECK: Undefined symbol: : _bar
diff --git a/test/mach-o/flat_namespace_undef_suppress.yaml b/test/mach-o/flat_namespace_undef_suppress.yaml
new file mode 100644
index 000000000000..5152a1cd985c
--- /dev/null
+++ b/test/mach-o/flat_namespace_undef_suppress.yaml
@@ -0,0 +1,17 @@
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.9 -flat_namespace -undefined suppress %s -o %t %p/Inputs/libSystem.yaml
+#
+# Sanity check '-flat_namespace -undefined suppress'.
+# This should pass without error, even though '_bar' is undefined.
+
+--- !native
+defined-atoms:
+ - name: _main
+ scope: global
+ content: [ E9, 00, 00, 00, 00 ]
+ alignment: 16
+ references:
+ - kind: branch32
+ offset: 1
+ target: _bar
+undefined-atoms:
+ - name: _bar
diff --git a/test/mach-o/force_load-dylib.yaml b/test/mach-o/force_load-dylib.yaml
index 0b932e159882..c8f559bedd79 100644
--- a/test/mach-o/force_load-dylib.yaml
+++ b/test/mach-o/force_load-dylib.yaml
@@ -1,7 +1,7 @@
# RUN: lld -flavor darwin -arch x86_64 -dylib %p/Inputs/bar.yaml \
# RUN: -install_name /usr/lib/libbar.dylib %p/Inputs/libSystem.yaml -o %t1.dylib
# RUN: lld -flavor darwin -arch x86_64 -dylib %s -all_load %t1.dylib \
-# RUN: -install_name /usr/lib/libfoo.dylib %p/Inputs/libSystem.yaml -o %t
+# RUN: -install_name /usr/lib/libfoo.dylib %p/Inputs/libSystem.yaml -o %t
# RUN: llvm-nm -m %t | FileCheck %s
#
#
@@ -18,7 +18,7 @@ sections:
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0x5D, 0xE9,
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0x5D, 0xE9,
0x00, 0x00, 0x00, 0x00 ]
relocations:
- offset: 0x00000008
diff --git a/test/mach-o/force_load-x86_64.yaml b/test/mach-o/force_load-x86_64.yaml
index 35905effd2c4..1be216ca3a74 100644
--- a/test/mach-o/force_load-x86_64.yaml
+++ b/test/mach-o/force_load-x86_64.yaml
@@ -15,14 +15,14 @@ file-type: MH_OBJECT
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
has-UUID: false
OS: unknown
-sections:
+sections:
- segment: __TEXT
section: __text
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
content: [ 0xC3 ]
-global-symbols:
+global-symbols:
- name: _main
type: N_SECT
scope: [ N_EXT ]
diff --git a/test/mach-o/framework-user-paths.yaml b/test/mach-o/framework-user-paths.yaml
index f6ac64779a71..80d6e3b5868b 100644
--- a/test/mach-o/framework-user-paths.yaml
+++ b/test/mach-o/framework-user-paths.yaml
@@ -1,5 +1,5 @@
#
-# Test framework and SDK search paths.
+# Test framework and SDK search paths.
# myFrameworks is not an absolute path, so it should not by found in SDK
# /Custom/Frameworks should be found in SDK
# /opt/Frameworks should not be found in SDK
diff --git a/test/mach-o/gcc_except_tab-got-arm64.yaml b/test/mach-o/gcc_except_tab-got-arm64.yaml
new file mode 100644
index 000000000000..7d105ec17847
--- /dev/null
+++ b/test/mach-o/gcc_except_tab-got-arm64.yaml
@@ -0,0 +1,53 @@
+# RUN: lld -flavor darwin -arch arm64 %s \
+# RUN: -dylib %p/Inputs/libSystem.yaml -o %t
+# RUN: llvm-objdump -section-headers %t | FileCheck %s
+
+# Make sure that the GOT relocation from gcc_except_tab to the data
+# is not removed.
+
+--- !native
+defined-atoms:
+ - name: _main
+ scope: global
+ content: [ FD, 7B, BF, A9, FD, 03, 00, 91, FF, 43, 00, D1,
+ BF, C3, 1F, B8, 00, 00, 00, 94, BF, 03, 00, 91,
+ FD, 7B, C1, A8, C0, 03, 5F, D6 ]
+ alignment: 4
+ - name: __ZTSP1A
+ scope: hidden
+ type: constant
+ content: [ 50, 31, 41, 00 ]
+ merge: as-weak
+ - name: GCC_except_table0
+ type: unwind-lsda
+ content: [ FF, 9B, E7, 80, 00, 03, 5B, 00, 00, 00, 00, 1C,
+ 00, 00, 00, 00, 00, 00, 00, 00, 1C, 00, 00, 00,
+ 18, 00, 00, 00, 84, 00, 00, 00, 03, 40, 00, 00,
+ 00, 10, 00, 00, 00, 94, 00, 00, 00, 03, 60, 00,
+ 00, 00, 20, 00, 00, 00, B4, 00, 00, 00, 05, 80,
+ 00, 00, 00, 68, 00, 00, 00, 00, 00, 00, 00, 00,
+ E8, 00, 00, 00, 08, 00, 00, 00, 28, 01, 00, 00,
+ 00, F0, 00, 00, 00, 74, 00, 00, 00, 00, 00, 00,
+ 00, 00, 00, 00, 01, 7D, 01, 00, A8, FF, FF, FF ]
+ alignment: 4
+ references:
+ - kind: delta32ToGOT
+ offset: 104
+ target: __ZTIP1A
+ - name: __ZTIP1A
+ scope: hidden
+ type: data
+ content: [ 10, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
+ 00, 00, 00, 80, 00, 00, 00, 00, 00, 00, 00, 00,
+ 00, 00, 00, 00, 00, 00, 00, 00 ]
+ merge: as-weak
+ alignment: 16
+shared-library-atoms:
+ - name: dyld_stub_binder
+ load-name: /usr/lib/libSystem.B.dylib
+ type: unknown
+...
+
+# Make sure we have a GOT relocation.
+# This could only have come from __gcc_except_tab to __ZTIP1A
+# CHECK: __got \ No newline at end of file
diff --git a/test/mach-o/got-order.yaml b/test/mach-o/got-order.yaml
index fbbc4e0397f2..b69877ecdc39 100644
--- a/test/mach-o/got-order.yaml
+++ b/test/mach-o/got-order.yaml
@@ -1,4 +1,5 @@
-# RUN: lld -flavor darwin -arch x86_64 %s -o %t %p/Inputs/libSystem.yaml
+# RUN: lld -flavor darwin -arch x86_64 %s %p/Inputs/got-order.yaml \
+# RUN: %p/Inputs/got-order2.yaml -o %t %p/Inputs/libSystem.yaml
# RUN: llvm-objdump -bind %t | FileCheck %s
#
# Test that GOT slots are sorted by name
@@ -8,18 +9,18 @@
arch: x86_64
file-type: MH_OBJECT
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
+sections:
- segment: __TEXT
section: __text
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x8B, 0x0D, 0x00,
- 0x00, 0x00, 0x00, 0x48, 0x8B, 0x05, 0x00, 0x00,
- 0x00, 0x00, 0x8B, 0x00, 0x03, 0x01, 0x48, 0x8B,
- 0x0D, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x5D,
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x8B, 0x0D, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x8B, 0x05, 0x00, 0x00,
+ 0x00, 0x00, 0x8B, 0x00, 0x03, 0x01, 0x48, 0x8B,
+ 0x0D, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x5D,
0xC3 ]
- relocations:
+ relocations:
- offset: 0x00000019
type: X86_64_RELOC_GOT_LOAD
length: 2
@@ -38,13 +39,13 @@ sections:
pc-rel: true
extern: true
symbol: 3
-global-symbols:
+global-symbols:
- name: _func
type: N_SECT
scope: [ N_EXT ]
sect: 1
value: 0x0000000000000000
-undefined-symbols:
+undefined-symbols:
- name: _aaa
type: N_UNDF
scope: [ N_EXT ]
@@ -57,72 +58,6 @@ undefined-symbols:
type: N_UNDF
scope: [ N_EXT ]
value: 0x0000000000000000
-
---- !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: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x8B, 0x0D, 0x00,
- 0x00, 0x00, 0x00, 0x48, 0x8B, 0x05, 0x00, 0x00,
- 0x00, 0x00, 0x8B, 0x00, 0x03, 0x01, 0x48, 0x8B,
- 0x0D, 0x00, 0x00, 0x00, 0x00, 0x03, 0x01, 0x5D,
- 0xC3 ]
- relocations:
- - offset: 0x00000019
- type: X86_64_RELOC_GOT_LOAD
- length: 2
- pc-rel: true
- extern: true
- symbol: 2
- - offset: 0x0000000E
- type: X86_64_RELOC_GOT_LOAD
- length: 2
- pc-rel: true
- extern: true
- symbol: 1
- - offset: 0x00000007
- type: X86_64_RELOC_GOT_LOAD
- length: 2
- pc-rel: true
- extern: true
- symbol: 3
-global-symbols:
- - name: _main
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-undefined-symbols:
- - name: _bar
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _foo
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
- - name: _zazzle
- type: N_UNDF
- scope: [ N_EXT ]
- value: 0x0000000000000000
-
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-install-name: /usr/lib/libfoobar.dylib
-exports:
- - name: _bar
- - name: _zazzle
- - name: _foo
- - name: _aaa
- - name: _fff
- - name: _zzz
...
diff --git a/test/mach-o/hello-world-arm64.yaml b/test/mach-o/hello-world-arm64.yaml
index a0555e9cc426..75ac4f747795 100644
--- a/test/mach-o/hello-world-arm64.yaml
+++ b/test/mach-o/hello-world-arm64.yaml
@@ -1,4 +1,4 @@
-# RUN: lld -flavor darwin -arch arm64 %s -o %t
+# RUN: lld -flavor darwin -arch arm64 %s %p/Inputs/hello-world-arm64.yaml -o %t
# RUN: llvm-nm -m -n %t | FileCheck %s
#
# Test that arm64 hello-world can be linked into a mach-o executable
@@ -88,17 +88,7 @@ undefined-symbols:
value: 0x0000000000000000
...
---- !mach-o
-arch: arm64
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: _fprintf
- - name: ___stdoutp
- - name: dyld_stub_binder
-...
-
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _main
# 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) external _main
diff --git a/test/mach-o/hello-world-armv6.yaml b/test/mach-o/hello-world-armv6.yaml
index 746ee094da68..8a9edeeddbac 100644
--- a/test/mach-o/hello-world-armv6.yaml
+++ b/test/mach-o/hello-world-armv6.yaml
@@ -1,4 +1,4 @@
-# RUN: lld -flavor darwin -arch armv6 %s -o %t
+# RUN: lld -flavor darwin -arch armv6 %s %p/Inputs/hello-world-armv6.yaml -o %t
# RUN: llvm-nm -m %t | FileCheck %s
#
# Test that armv6 (arm) hello-world can be linked into a mach-o executable
@@ -57,14 +57,6 @@ undefined-symbols:
type: N_UNDF
scope: [ N_EXT ]
value: 0x0000000000000000
-
---- !mach-o
-arch: armv6
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: _printf
- - name: dyld_stub_binder
...
# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _main
diff --git a/test/mach-o/hello-world-armv7.yaml b/test/mach-o/hello-world-armv7.yaml
index bfc03c382a05..1871d68f6b92 100644
--- a/test/mach-o/hello-world-armv7.yaml
+++ b/test/mach-o/hello-world-armv7.yaml
@@ -1,4 +1,4 @@
-# RUN: lld -flavor darwin -arch armv7 %s -o %t
+# RUN: lld -flavor darwin -arch armv7 %s %p/Inputs/hello-world-armv7.yaml -o %t
# RUN: llvm-nm -m -n %t | FileCheck %s
#
# Test that armv7 (thumb) hello-world can be linked into a mach-o executable
@@ -10,17 +10,17 @@ file-type: MH_OBJECT
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
has-UUID: false
OS: unknown
-sections:
+sections:
- segment: __TEXT
section: __text
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
alignment: 2
address: 0x0000000000000000
- content: [ 0x80, 0xB5, 0x40, 0xF2, 0x06, 0x00, 0x6F, 0x46,
- 0xC0, 0xF2, 0x00, 0x00, 0x78, 0x44, 0xFF, 0xF7,
+ content: [ 0x80, 0xB5, 0x40, 0xF2, 0x06, 0x00, 0x6F, 0x46,
+ 0xC0, 0xF2, 0x00, 0x00, 0x78, 0x44, 0xFF, 0xF7,
0xF8, 0xEF, 0x00, 0x20, 0x80, 0xBD ]
- relocations:
+ relocations:
- offset: 0x0000000E
type: ARM_THUMB_RELOC_BR22
length: 2
@@ -57,29 +57,20 @@ sections:
attributes: [ ]
address: 0x0000000000000016
content: [ 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x0A, 0x00 ]
-global-symbols:
+global-symbols:
- name: _main
type: N_SECT
scope: [ N_EXT ]
sect: 1
desc: [ N_ARM_THUMB_DEF ]
value: 0x0000000000000000
-undefined-symbols:
+undefined-symbols:
- name: _printf
type: N_UNDF
scope: [ N_EXT ]
value: 0x0000000000000000
...
---- !mach-o
-arch: armv7
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: _printf
- - name: dyld_stub_binder
-...
-
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external [Thumb] _main
# CHECK: (undefined) external _printf (from libSystem)
# CHECK: (undefined) external dyld_stub_binder (from libSystem)
+# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external [Thumb] _main
diff --git a/test/mach-o/hello-world-x86.yaml b/test/mach-o/hello-world-x86.yaml
index de453ed1ac45..779b6811e080 100644
--- a/test/mach-o/hello-world-x86.yaml
+++ b/test/mach-o/hello-world-x86.yaml
@@ -1,4 +1,4 @@
-# RUN: lld -flavor darwin -arch i386 %s -o %t
+# RUN: lld -flavor darwin -arch i386 %s %p/Inputs/hello-world-x86.yaml -o %t
# RUN: llvm-nm -m %t | FileCheck %s
#
# Test that i386 hello-world can be linked into a mach-o executable
@@ -14,10 +14,10 @@ sections:
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
- content: [ 0x55, 0x89, 0xE5, 0x83, 0xEC, 0x08, 0xE8, 0x00,
- 0x00, 0x00, 0x00, 0x58, 0x8D, 0x80, 0x16, 0x00,
- 0x00, 0x00, 0x89, 0x04, 0x24, 0xE8, 0xE6, 0xFF,
- 0xFF, 0xFF, 0x31, 0xC0, 0x83, 0xC4, 0x08, 0x5D,
+ content: [ 0x55, 0x89, 0xE5, 0x83, 0xEC, 0x08, 0xE8, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x8D, 0x80, 0x16, 0x00,
+ 0x00, 0x00, 0x89, 0x04, 0x24, 0xE8, 0xE6, 0xFF,
+ 0xFF, 0xFF, 0x31, 0xC0, 0x83, 0xC4, 0x08, 0x5D,
0xC3 ]
relocations:
- offset: 0x00000016
@@ -55,15 +55,6 @@ undefined-symbols:
type: N_UNDF
scope: [ N_EXT ]
value: 0x0000000000000000
-
---- !mach-o
-arch: x86
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: _printf
- - name: dyld_stub_binder
-
...
# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _main
diff --git a/test/mach-o/hello-world-x86_64.yaml b/test/mach-o/hello-world-x86_64.yaml
index 83d4fcb32601..340ceefbe7cb 100644
--- a/test/mach-o/hello-world-x86_64.yaml
+++ b/test/mach-o/hello-world-x86_64.yaml
@@ -1,7 +1,9 @@
-# RUN: lld -flavor darwin -arch x86_64 %s -o %t
+# RUN: lld -flavor darwin -arch x86_64 %s %p/Inputs/hello-world-x86_64.yaml \
+# RUN: -o %t
# RUN: llvm-nm -m -n %t | FileCheck %s
#
-# RUN: lld -flavor darwin -arch x86_64 %s -dead_strip -o %t2
+# RUN: lld -flavor darwin -arch x86_64 %s %p/Inputs/hello-world-x86_64.yaml \
+# RUN: -dead_strip -o %t2
# RUN: llvm-nm -m -n %t2 | FileCheck %s
#
# Test that x86_64 hello-world can be linked into a mach-o executable
@@ -13,17 +15,17 @@ file-type: MH_OBJECT
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
has-UUID: false
OS: unknown
-sections:
+sections:
- segment: __TEXT
section: __text
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x8B, 0x05, 0x00,
- 0x00, 0x00, 0x00, 0x48, 0x8B, 0x38, 0x48, 0x8D,
- 0x35, 0x00, 0x00, 0x00, 0x00, 0x31, 0xC0, 0xE8,
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x8B, 0x05, 0x00,
+ 0x00, 0x00, 0x00, 0x48, 0x8B, 0x38, 0x48, 0x8D,
+ 0x35, 0x00, 0x00, 0x00, 0x00, 0x31, 0xC0, 0xE8,
0x00, 0x00, 0x00, 0x00, 0x31, 0xC0, 0x5D, 0xC3 ]
- relocations:
+ relocations:
- offset: 0x00000018
type: X86_64_RELOC_BRANCH
length: 2
@@ -54,11 +56,11 @@ sections:
attributes: [ ]
alignment: 3
address: 0x0000000000000028
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
+ relocations:
- offset: 0x00000000
type: X86_64_RELOC_UNSIGNED
length: 3
@@ -71,15 +73,15 @@ sections:
attributes: [ ]
alignment: 3
address: 0x0000000000000048
- content: [ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x7A, 0x52, 0x00, 0x01, 0x78, 0x10, 0x01,
- 0x10, 0x0C, 0x07, 0x08, 0x90, 0x01, 0x00, 0x00,
- 0x24, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
- 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x41, 0x0E, 0x10, 0x86, 0x02, 0x43, 0x0D,
+ content: [ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x7A, 0x52, 0x00, 0x01, 0x78, 0x10, 0x01,
+ 0x10, 0x0C, 0x07, 0x08, 0x90, 0x01, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
+ 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x41, 0x0E, 0x10, 0x86, 0x02, 0x43, 0x0D,
0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
-local-symbols:
+local-symbols:
- name: L1
type: N_SECT
sect: 2
@@ -88,7 +90,7 @@ local-symbols:
type: N_SECT
sect: 4
value: 0x0000000000000048
-global-symbols:
+global-symbols:
- name: _main
type: N_SECT
scope: [ N_EXT ]
@@ -99,7 +101,7 @@ global-symbols:
scope: [ N_EXT ]
sect: 4
value: 0x0000000000000060
-undefined-symbols:
+undefined-symbols:
- name: ___stdoutp
type: N_UNDF
scope: [ N_EXT ]
@@ -109,18 +111,9 @@ undefined-symbols:
scope: [ N_EXT ]
value: 0x0000000000000000
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: _fprintf
- - name: dyld_stub_binder
- - name: ___stdoutp
-
...
-# CHECK: {{[0-9a-f]+}} (__TEXT,__text) external _main
# 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) external _main
diff --git a/test/mach-o/image-base.yaml b/test/mach-o/image-base.yaml
index cc272491bc55..d274621f8dd3 100644
--- a/test/mach-o/image-base.yaml
+++ b/test/mach-o/image-base.yaml
@@ -1,5 +1,5 @@
# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.9 %s -o %t -image_base 31415926000 %p/Inputs/libSystem.yaml
-# RUN: macho-dump %t | FileCheck %s
+# RUN: llvm-readobj -macho-segment %t | FileCheck %s
# RUN: not lld -flavor darwin -arch x86_64 -image_base 0x31415926530 %s >/dev/null 2> %t
# RUN: FileCheck < %t %s --check-prefix=CHECK-ERROR-MISPAGED
# RUN: not lld -flavor darwin -arch x86_64 -image_base 1000 %s >/dev/null 2> %t
@@ -13,11 +13,12 @@ defined-atoms:
scope: global
content: []
- # Unfortunately, llvm-objdump and llvm-readobj are too generic and don't give
- # us easy access to the MachO segment model, so we have to check the uglier
- # macho-dump output.
-# CHECK: 'segment_name', '__TEXT
-# CHECK-NEXT: 'vm_addr', 3384796143616
+# CHECK: Segment {
+# CHECK: Cmd: LC_SEGMENT_64
+# CHECK: Name: __TEXT
+# CHECK-NEXT: Size: 152
+# CHECK-NEXT: vmaddr: 0x31415926000
+# CHECK-NEXT: vmsize: 0x1000
# CHECK-ERROR-MISPAGED: error: image_base must be a multiple of page size (0x1000)
diff --git a/test/mach-o/infer-arch.yaml b/test/mach-o/infer-arch.yaml
index 94f8543bd72e..c09c94dd1b70 100644
--- a/test/mach-o/infer-arch.yaml
+++ b/test/mach-o/infer-arch.yaml
@@ -25,5 +25,5 @@ global-symbols:
...
-# CHECK: defined-atoms:
+# CHECK: defined-atoms:
# CHECK: - name: _foo
diff --git a/test/mach-o/interposing-section.yaml b/test/mach-o/interposing-section.yaml
index 856d4b91f3d2..76e33904d113 100644
--- a/test/mach-o/interposing-section.yaml
+++ b/test/mach-o/interposing-section.yaml
@@ -1,4 +1,5 @@
-# RUN: lld -flavor darwin -arch x86_64 %s -dylib -o %t %p/Inputs/libSystem.yaml
+# RUN: lld -flavor darwin -arch x86_64 %s %p/Inputs/interposing-section.yaml \
+# RUN: -dylib -o %t %p/Inputs/libSystem.yaml
# RUN: llvm-objdump -private-headers %t | FileCheck %s
#
# RUN: lld -flavor darwin -arch x86_64 %s -r -o %t1
@@ -11,15 +12,15 @@
arch: x86_64
file-type: MH_OBJECT
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
-sections:
+sections:
- segment: __TEXT
section: __text
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0x5D, 0xE9,
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0x5D, 0xE9,
0x00, 0x00, 0x00, 0x00 ]
- relocations:
+ relocations:
- offset: 0x00000008
type: X86_64_RELOC_BRANCH
length: 2
@@ -32,9 +33,9 @@ sections:
attributes: [ ]
alignment: 3
address: 0x0000000000000010
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
+ relocations:
- offset: 0x00000008
type: X86_64_RELOC_UNSIGNED
length: 3
@@ -47,7 +48,7 @@ sections:
pc-rel: false
extern: true
symbol: 0
-local-symbols:
+local-symbols:
- name: _my_open
type: N_SECT
sect: 1
@@ -57,19 +58,11 @@ local-symbols:
sect: 2
desc: [ N_NO_DEAD_STRIP ]
value: 0x0000000000000010
-undefined-symbols:
+undefined-symbols:
- name: _open
type: N_UNDF
scope: [ N_EXT ]
value: 0x0000000000000000
-
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: _open
-
...
diff --git a/test/mach-o/keep_private_externs.yaml b/test/mach-o/keep_private_externs.yaml
index d67941a1c8eb..e7adf180fc7b 100644
--- a/test/mach-o/keep_private_externs.yaml
+++ b/test/mach-o/keep_private_externs.yaml
@@ -17,7 +17,7 @@ sections:
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x55, 0x48,
0x89, 0xE5, 0x5D, 0xC3 ]
- segment: __DATA
section: __data
diff --git a/test/mach-o/lazy-bind-x86_64.yaml b/test/mach-o/lazy-bind-x86_64.yaml
index 54d787ce91be..1b4699feed35 100644
--- a/test/mach-o/lazy-bind-x86_64.yaml
+++ b/test/mach-o/lazy-bind-x86_64.yaml
@@ -1,6 +1,8 @@
# REQUIRES: x86
-# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -o %t \
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s \
+# RUN: %p/Inputs/lazy-bind-x86_64.yaml %p/Inputs/lazy-bind-x86_64-2.yaml \
+# RUN: %p/Inputs/lazy-bind-x86_64-3.yaml -o %t \
# RUN: %p/Inputs/libSystem.yaml
# RUN: llvm-objdump -lazy-bind %t | FileCheck %s
# RUN: llvm-nm -m %t | FileCheck --check-prefix=CHECK-NM %s
@@ -63,33 +65,6 @@ undefined-symbols:
scope: [ N_EXT ]
value: 0x0000000000000000
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-install-name: /usr/lib/libbar.dylib
-compat-version: 1.0
-current-version: 2.3
-exports:
- - name: _bar
-
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-install-name: /usr/lib/libfoo.dylib
-compat-version: 2.0
-current-version: 3.4
-exports:
- - name: _foo
-
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-install-name: /usr/lib/libbaz.dylib
-compat-version: 3.0
-current-version: 4.5
-exports:
- - name: _baz
-
...
diff --git a/test/mach-o/library-order.yaml b/test/mach-o/library-order.yaml
index 23e9f6873134..f9cd5a6c44d2 100644
--- a/test/mach-o/library-order.yaml
+++ b/test/mach-o/library-order.yaml
@@ -16,9 +16,9 @@ sections:
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
alignment: 4
address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x10,
- 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xB0,
- 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x31, 0xC0,
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x10,
+ 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xB0,
+ 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x31, 0xC0,
0x48, 0x83, 0xC4, 0x10, 0x5D, 0xC3 ]
relocations:
- offset: 0x00000012
diff --git a/test/mach-o/library-rescan.yaml b/test/mach-o/library-rescan.yaml
index a58d763fff00..a8a0ca8968b3 100644
--- a/test/mach-o/library-rescan.yaml
+++ b/test/mach-o/library-rescan.yaml
@@ -16,9 +16,9 @@ sections:
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
alignment: 4
address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x10,
- 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xB0,
- 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x31, 0xC0,
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x83, 0xEC, 0x10,
+ 0xC7, 0x45, 0xFC, 0x00, 0x00, 0x00, 0x00, 0xB0,
+ 0x00, 0xE8, 0x00, 0x00, 0x00, 0x00, 0x31, 0xC0,
0x48, 0x83, 0xC4, 0x10, 0x5D, 0xC3 ]
relocations:
- offset: 0x00000012
diff --git a/test/mach-o/linker-as-ld.yaml b/test/mach-o/linker-as-ld.yaml
index 2dd1f79818e1..f0bf189876a6 100644
--- a/test/mach-o/linker-as-ld.yaml
+++ b/test/mach-o/linker-as-ld.yaml
@@ -1,7 +1,8 @@
# REQUIRES: system-linker-mach-o
#
# RUN: mkdir -p %t.dir && cp `which lld` %t.dir/ld \
-# RUN: && %t.dir/ld -arch x86_64 -macosx_version_min 10.8 %s -o %t \
+# RUN: && %t.dir/ld -arch x86_64 -macosx_version_min 10.8 %s \
+# RUN: %p/Inputs/linker-as-ld.yaml -o %t \
# RUN: && llvm-nm %t | FileCheck %s
#
# Test linker run as "ld" on darwin works as darwin linker.
@@ -26,14 +27,6 @@ global-symbols:
scope: [ N_EXT ]
sect: 1
value: 0x0000000000000000
-
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-install-name: /usr/lib/libSystem.B.dylib
-exports:
- - name: dyld_stub_binder
-
...
# CHECK: T _main
diff --git a/test/mach-o/objc_export_list.yaml b/test/mach-o/objc_export_list.yaml
index 5844812295be..9eb0af77726e 100644
--- a/test/mach-o/objc_export_list.yaml
+++ b/test/mach-o/objc_export_list.yaml
@@ -17,15 +17,15 @@ sections:
attributes: [ ]
alignment: 3
address: 0x0000000000000000
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
relocations:
- offset: 0x00000030
diff --git a/test/mach-o/parse-aliases.yaml b/test/mach-o/parse-aliases.yaml
index 457ea58133b9..54da2d64e63a 100644
--- a/test/mach-o/parse-aliases.yaml
+++ b/test/mach-o/parse-aliases.yaml
@@ -68,7 +68,7 @@ global-symbols:
value: 0x0000000000000001
...
-# CHECK: defined-atoms:
+# CHECK: defined-atoms:
# CHECK: - name: _pad
# CHECK: scope: global
# CHECK: content: [ CC ]
diff --git a/test/mach-o/parse-arm-relocs.yaml b/test/mach-o/parse-arm-relocs.yaml
index c87c2a99b215..abeb3ddeb9d1 100644
--- a/test/mach-o/parse-arm-relocs.yaml
+++ b/test/mach-o/parse-arm-relocs.yaml
@@ -438,10 +438,10 @@ sections:
type: S_REGULAR
attributes: [ ]
address: 0x00000000000000A0
- content: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
- 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0xA4, 0xFF, 0xFF, 0xFF,
- 0xA4, 0xFF, 0xFF, 0xFF, 0x45, 0xFF, 0xFF, 0xFF,
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x04, 0x00, 0x00, 0x00, 0xA4, 0xFF, 0xFF, 0xFF,
+ 0xA4, 0xFF, 0xFF, 0xFF, 0x45, 0xFF, 0xFF, 0xFF,
0x45, 0xFF, 0xFF, 0xFF ]
relocations:
- offset: 0x00000020
@@ -742,7 +742,7 @@ undefined-symbols:
# CHECK: offset: 68
# CHECK: target: _undef
# CHECK: addend: 8
-# CHECK: undefined-atoms:
+# CHECK: undefined-atoms:
# CHECK: - name: _undef
@@ -782,7 +782,7 @@ undefined-symbols:
#
#
# .code 32
-# .align 2
+# .align 2
#_foo_arm:
# bl _x
# bl _x+4
@@ -803,7 +803,7 @@ undefined-symbols:
# movt r5, :upper16:_undef
# movw r6, :lower16:_undef+8
# movt r6, :upper16:_undef+8
-#
+#
#
# .data
#_x: .long 0
diff --git a/test/mach-o/parse-cfstring64.yaml b/test/mach-o/parse-cfstring64.yaml
index fbd674d90d99..b90277f056e5 100644
--- a/test/mach-o/parse-cfstring64.yaml
+++ b/test/mach-o/parse-cfstring64.yaml
@@ -72,7 +72,7 @@ undefined-symbols:
value: 0x0000000000000000
...
-# CHECK:defined-atoms:
+# CHECK:defined-atoms:
# CHECK: - ref-name: L000
# CHECK: scope: hidden
# CHECK: type: c-string
@@ -86,7 +86,7 @@ undefined-symbols:
# CHECK: - scope: hidden
# CHECK: type: cfstring
# CHECK: merge: by-content
-# CHECK: references:
+# CHECK: references:
# CHECK: - kind: pointer64
# CHECK: offset: 0
# CHECK: target: ___CFConstantStringClassReference
@@ -96,13 +96,13 @@ undefined-symbols:
# CHECK: - scope: hidden
# CHECK: type: cfstring
# CHECK: merge: by-content
-# CHECK: references:
+# CHECK: references:
# CHECK: - kind: pointer64
# CHECK: offset: 0
# CHECK: target: ___CFConstantStringClassReference
# CHECK: - kind: pointer64
# CHECK: offset: 16
# CHECK: target: L001
-# CHECK:undefined-atoms:
+# CHECK:undefined-atoms:
# CHECK: - name: ___CFConstantStringClassReference
diff --git a/test/mach-o/parse-data-in-code-armv7.yaml b/test/mach-o/parse-data-in-code-armv7.yaml
index 29b483e7d723..720f24d7b47f 100644
--- a/test/mach-o/parse-data-in-code-armv7.yaml
+++ b/test/mach-o/parse-data-in-code-armv7.yaml
@@ -18,11 +18,11 @@ sections:
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
alignment: 2
address: 0x0000000000000000
- content: [ 0x00, 0xBF, 0x00, 0xBF, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
- 0x03, 0x00, 0x00, 0x00, 0x00, 0xBF, 0x00, 0xBF,
- 0x00, 0xF0, 0x20, 0xE3, 0x0A, 0x00, 0x00, 0x00,
- 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
+ content: [ 0x00, 0xBF, 0x00, 0xBF, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x03, 0x00, 0x00, 0x00, 0x00, 0xBF, 0x00, 0xBF,
+ 0x00, 0xF0, 0x20, 0xE3, 0x0A, 0x00, 0x00, 0x00,
+ 0x0B, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00,
0x0D, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x20, 0xE3 ]
local-symbols:
- name: _foo_thumb
@@ -133,7 +133,7 @@ dataInCode:
#
#
# .code 32
-# .align 2
+# .align 2
#_foo_arm:
# nop
#
diff --git a/test/mach-o/parse-data-relocs-x86_64.yaml b/test/mach-o/parse-data-relocs-x86_64.yaml
index ae93c1bb75d9..b6f38f5d10e4 100644
--- a/test/mach-o/parse-data-relocs-x86_64.yaml
+++ b/test/mach-o/parse-data-relocs-x86_64.yaml
@@ -2,7 +2,7 @@
# RUN: lld -flavor darwin -arch x86_64 -r %s -o %t -print_atoms | FileCheck %s \
# RUN: && lld -flavor darwin -arch x86_64 %t -r -print_atoms -o %t2 | FileCheck %s
#
-# Test parsing and writing of x86_64 text relocations.
+# Test parsing and writing of x86_64 data relocations.
#
# The first step tests if the supplied mach-o file is parsed into the correct
# set of references. The second step verifies relocations can be round-tripped
@@ -14,11 +14,11 @@
#
#_bar:
# ret
-#
+#
# .section __DATA,__custom
#L1:
# .quad 0
-#
+#
# .data
#_d:
# .quad _foo
@@ -37,10 +37,12 @@
--- !mach-o
arch: x86_64
file-type: MH_OBJECT
-flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
+flags: [ ]
+compat-version: 0.0
+current-version: 0.0
has-UUID: false
OS: unknown
-sections:
+sections:
- segment: __TEXT
section: __text
type: S_REGULAR
@@ -52,107 +54,186 @@ sections:
type: S_REGULAR
attributes: [ ]
address: 0x0000000000000002
- content: [ 0x00, 0x00, 0x00, 0x00 ]
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- segment: __DATA
section: __data
type: S_REGULAR
attributes: [ ]
- alignment: 3
- address: 0x0000000000000008
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0xE0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xDC, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xD2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
- 0xC8, 0xFF, 0xFF, 0xFF, 0xC8, 0xFF, 0xFF, 0xFF,
- 0xC2, 0xFF, 0xFF, 0xFF ]
- relocations:
- - offset: 0x00000040
+ address: 0x000000000000000A
+ content: [
+# .quad _foo
+# No addend is needed here as we are referencing _foo directly and that is
+# encoded entirely in the X86_64_RELOC_UNSIGNED
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+# .quad _foo+4
+# Addend of 4 is needed here as we are referencing _foo from the
+# X86_64_RELOC_UNSIGNED, then the addend gives us 4 more.
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+# .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.
+ 0xF0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+# .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
+# the addend here is the absolute address of the location in that section
+# we want to reference.
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+# .quad L1 + 2
+# This is a X86_64_RELOC_UNSIGNED without extern set.
+# In this case, we encode the section number for L1 in the relocation, and
+# the addend here is the absolute address of the location in that section
+# we want to reference. We have a 4 because the section is at address 2
+# and we want an offset of 2 from there.
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+# .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 -40 because that is the offset from here back
+# to _d.
+ 0xD8, 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
+# 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,
+# .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
+# this location from _d. The remaining 2 is the absolute address
+# of L1.
+ 0xCA, 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
+# to _d.
+ 0xC0, 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
+# 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,
+# .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
+# this location from _d. The remaining 2 is the absolute address
+# of L1.
+ 0xBA, 0xFF, 0xFF, 0xFF ]
+ relocations:
+ - 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: false
symbol: 2
- - offset: 0x0000003C
+ - offset: 0x00000044
type: X86_64_RELOC_SUBTRACTOR
length: 2
pc-rel: false
extern: true
symbol: 2
- - offset: 0x0000003C
+ - offset: 0x00000044
type: X86_64_RELOC_UNSIGNED
length: 2
pc-rel: false
extern: true
symbol: 0
- - offset: 0x00000038
+ - offset: 0x00000040
type: X86_64_RELOC_SUBTRACTOR
length: 2
pc-rel: false
extern: true
symbol: 2
- - offset: 0x00000038
+ - offset: 0x00000040
type: X86_64_RELOC_UNSIGNED
length: 2
pc-rel: false
extern: true
symbol: 0
- - 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: false
symbol: 2
- - 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: 0x00000020
+ - offset: 0x00000028
type: X86_64_RELOC_SUBTRACTOR
length: 3
pc-rel: false
extern: true
symbol: 2
- - offset: 0x00000020
+ - offset: 0x00000028
type: X86_64_RELOC_UNSIGNED
length: 3
pc-rel: false
extern: true
symbol: 0
- - offset: 0x00000018
+ - offset: 0x00000020
type: X86_64_RELOC_UNSIGNED
length: 3
pc-rel: false
extern: false
symbol: 2
- - offset: 0x00000010
+ - offset: 0x00000018
type: X86_64_RELOC_UNSIGNED
length: 3
pc-rel: false
extern: false
symbol: 2
+ - offset: 0x00000010
+ type: X86_64_RELOC_SUBTRACTOR
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 2
+ - offset: 0x00000010
+ type: X86_64_RELOC_UNSIGNED
+ length: 3
+ pc-rel: false
+ extern: true
+ symbol: 0
- offset: 0x00000008
type: X86_64_RELOC_UNSIGNED
length: 3
@@ -165,7 +246,7 @@ sections:
pc-rel: false
extern: true
symbol: 0
-local-symbols:
+local-symbols:
- name: _foo
type: N_SECT
sect: 1
@@ -177,13 +258,22 @@ local-symbols:
- name: _d
type: N_SECT
sect: 3
- value: 0x0000000000000008
+ value: 0x000000000000000A
+page-size: 0x00000000
...
-# CHECK: defined-atoms:
+# 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, 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: {{..}}, {{..}}, {{..}}, {{..}} ]
+# CHECK: dead-strip: never
# CHECK: references:
# CHECK: - kind: pointer64
# CHECK: offset: 0
@@ -192,39 +282,45 @@ local-symbols:
# CHECK: offset: 8
# CHECK: target: _foo
# CHECK: addend: 4
-# CHECK: - kind: pointer64Anon
+# CHECK: - kind: delta64
# CHECK: offset: 16
-# CHECK: target: L003
+# CHECK: target: _foo
# CHECK: - kind: pointer64Anon
# CHECK: offset: 24
# CHECK: target: L003
+# CHECK: - kind: pointer64Anon
+# CHECK: offset: 32
+# CHECK: target: L003
# CHECK: addend: 2
# CHECK: - kind: delta64
-# CHECK: offset: 32
+# CHECK: offset: 40
# CHECK: target: _foo
# CHECK: - kind: delta64
-# CHECK: offset: 40
+# CHECK: offset: 48
# CHECK: target: _foo
# CHECK: addend: 4
# CHECK: - kind: delta64Anon
-# CHECK: offset: 48
+# CHECK: offset: 56
# CHECK: target: L003
# CHECK: - kind: delta32
-# CHECK: offset: 56
+# CHECK: offset: 64
# CHECK: target: _foo
# CHECK: - kind: delta32
-# CHECK: offset: 60
+# CHECK: offset: 68
# CHECK: target: _foo
# CHECK: addend: 4
# CHECK: - kind: delta32Anon
-# CHECK: offset: 64
+# CHECK: offset: 72
# CHECK: target: L003
# CHECK: - name: _foo
# CHECK: content: [ C3 ]
+# CHECK: dead-strip: never
# CHECK: - name: _bar
# CHECK: content: [ C3 ]
+# CHECK: dead-strip: never
# CHECK: - ref-name: L003
# CHECK: type: unknown
-# CHECK: content: [ 00, 00, 00, 00 ]
+# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
# CHECK: section-choice: custom-required
# CHECK: section-name: __DATA/__custom
+
diff --git a/test/mach-o/parse-eh-frame-relocs-x86_64.yaml b/test/mach-o/parse-eh-frame-relocs-x86_64.yaml
new file mode 100644
index 000000000000..b009cbcea139
--- /dev/null
+++ b/test/mach-o/parse-eh-frame-relocs-x86_64.yaml
@@ -0,0 +1,176 @@
+# RUN: lld -flavor darwin -arch x86_64 -r -print_atoms %s -o %t | FileCheck %s
+#
+# Test parsing of x86_64 __eh_frame (dwarf unwind) relocations.
+
+--- !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: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ alignment: 16
+ address: 0x0000000000000000
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0xE8, 0x00, 0x00, 0x00,
+ 0x00, 0x5D, 0xC3, 0x48, 0x89, 0xC7, 0xE8, 0x00,
+ 0x00, 0x00, 0x00, 0x5D, 0xE9, 0x00, 0x00, 0x00,
+ 0x00, 0x0F, 0x1F, 0x80, 0x00, 0x00, 0x00, 0x00,
+ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3, 0x66, 0x2E,
+ 0x0F, 0x1F, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x55, 0x48, 0x89, 0xE5, 0xE8, 0x00, 0x00, 0x00,
+ 0x00, 0x5D, 0xC3, 0x48, 0x89, 0xC7, 0xE8, 0x00,
+ 0x00, 0x00, 0x00, 0x5D, 0xE9, 0x00, 0x00, 0x00,
+ 0x00 ]
+ - segment: __TEXT
+ section: __gcc_except_tab
+ type: S_REGULAR
+ attributes: [ ]
+ alignment: 4
+ address: 0x000000000000004C
+ content: [ 0xFF, 0x9B, 0xA2, 0x80, 0x80, 0x00, 0x03, 0x1A,
+ 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x0B, 0x00, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0xFF, 0x9B, 0xA2, 0x80, 0x80, 0x00, 0x03, 0x1A,
+ 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00,
+ 0x0B, 0x00, 0x00, 0x00, 0x01, 0x09, 0x00, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+ - segment: __TEXT
+ section: __eh_frame
+ type: S_COALESCED
+ attributes: [ ]
+ alignment: 8
+ address: 0x0000000000000100
+ content: [ 0x1C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x7A, 0x50, 0x4C, 0x52, 0x00, 0x01, 0x78,
+ 0x10, 0x07, 0x9B, 0x04, 0x00, 0x00, 0x00, 0x10,
+ 0x10, 0x0C, 0x07, 0x08, 0x90, 0x01, 0x00, 0x00,
+ 0x2C, 0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00,
+ 0xD8, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0x13, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x41, 0x0E, 0x10, 0x86, 0x02, 0x43, 0x0D,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0x7A, 0x52, 0x00, 0x01, 0x78, 0x10, 0x01,
+ 0x10, 0x0C, 0x07, 0x08, 0x90, 0x01, 0x00, 0x00,
+ 0x24, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
+ 0xB0, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x41, 0x0E, 0x10, 0x86, 0x02, 0x43, 0x0D,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x2C, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00,
+ 0x98, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x08, 0xCB, 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+ 0xFF, 0x41, 0x0E, 0x10, 0x86, 0x02, 0x43, 0x0D,
+ 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+ relocations:
+ - offset: 0x00000013
+ type: X86_64_RELOC_GOT
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 8
+local-symbols:
+ - name: GCC_except_table0
+ type: N_SECT
+ sect: 2
+ value: 0x000000000000004C
+ - name: GCC_except_table2
+ type: N_SECT
+ sect: 2
+ value: 0x0000000000000074
+global-symbols:
+ - name: _catchMyException1
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+ - name: _catchMyException2
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000030
+ - name: _bar
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000020
+undefined-symbols:
+ - name: _foo
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+ - name: ___cxa_begin_catch
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+ - name: ___cxa_end_catch
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+ - name: ___gxx_personality_v0
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+page-size: 0x00000000
+...
+
+# Check that LSDA fields are fixed up correctly, even when there are multiple
+# CIEs involved.
+#
+# (1) Check that we can relocate an LSDA at all. Requires correct interpretation
+# of augmentation data strings in CIEs and augmentation data fields of FDEs.
+#
+# CHECK: - type: unwind-cfi
+# CHECK-NOT: - type:
+# CHECK: references:
+# CHECK-NEXT: - kind: negDelta32
+# CHECK-NEXT: offset: 4
+# CHECK-NEXT: target: L002
+# CHECK-NEXT: - kind: unwindFDEToFunction
+# CHECK-NEXT: offset: 8
+# CHECK-NEXT: target: _catchMyException1
+# CHECK-NEXT: - kind: unwindFDEToFunction
+# CHECK-NEXT: offset: 25
+# CHECK-NEXT: target: GCC_except_table0
+#
+# (2) Check that we have an intervening FDE with a different CIE.
+# If the test fails here then test (3) probably isn't testing what it
+# should, and this test-case should be updated.
+#
+# CHECK: - type: unwind-cfi
+# CHECK-NOT: - type:
+# CHECK: references:
+# CHECK-NEXT: - kind: negDelta32
+# CHECK-NEXT: offset: 4
+# CHECK-NEXT: target: L001
+# CHECK-NEXT: - kind: unwindFDEToFunction
+# CHECK-NEXT: offset: 8
+# CHECK-NEXT: target: _bar
+#
+# (3) Check that we can relocate the LSDA on a second FDE that references the
+# original CIE from (1). Requires us to match this FDE up with the correct
+# CIE.
+#
+# CHECK-NEXT: - type: unwind-cfi
+# CHECK-NOT: - type:
+# CHECK: references:
+# CHECK-NEXT: - kind: negDelta32
+# CHECK-NEXT: offset: 4
+# CHECK-NEXT: target: L002
+# CHECK-NEXT: - kind: unwindFDEToFunction
+# CHECK-NEXT: offset: 8
+# CHECK-NEXT: target: _catchMyException2
+# CHECK-NEXT: - kind: unwindFDEToFunction
+# CHECK-NEXT: offset: 25
+# CHECK-NEXT: target: GCC_except_table2
diff --git a/test/mach-o/parse-eh-frame-x86-anon.yaml b/test/mach-o/parse-eh-frame-x86-anon.yaml
index 9e3adaea1849..09b6ba37c09a 100644
--- a/test/mach-o/parse-eh-frame-x86-anon.yaml
+++ b/test/mach-o/parse-eh-frame-x86-anon.yaml
@@ -9,22 +9,22 @@ arch: x86
file-type: MH_OBJECT
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
OS: unknown
-sections:
+sections:
- segment: __TEXT
section: __text
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
- content: [ 0x55, 0x89, 0xE5, 0x56, 0x83, 0xEC, 0x14, 0xE8,
- 0x00, 0x00, 0x00, 0x00, 0x5E, 0xC7, 0x04, 0x24,
- 0x04, 0x00, 0x00, 0x00, 0xE8, 0xE7, 0xFF, 0xFF,
- 0xFF, 0xC7, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x8B,
- 0x8E, 0x38, 0x00, 0x00, 0x00, 0x89, 0x4C, 0x24,
- 0x04, 0x89, 0x04, 0x24, 0xC7, 0x44, 0x24, 0x08,
- 0x00, 0x00, 0x00, 0x00, 0xE8, 0xC7, 0xFF, 0xFF,
- 0xFF, 0x55, 0x89, 0xE5, 0x83, 0xEC, 0x08, 0xE8,
+ content: [ 0x55, 0x89, 0xE5, 0x56, 0x83, 0xEC, 0x14, 0xE8,
+ 0x00, 0x00, 0x00, 0x00, 0x5E, 0xC7, 0x04, 0x24,
+ 0x04, 0x00, 0x00, 0x00, 0xE8, 0xE7, 0xFF, 0xFF,
+ 0xFF, 0xC7, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x8B,
+ 0x8E, 0x38, 0x00, 0x00, 0x00, 0x89, 0x4C, 0x24,
+ 0x04, 0x89, 0x04, 0x24, 0xC7, 0x44, 0x24, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0xE8, 0xC7, 0xFF, 0xFF,
+ 0xFF, 0x55, 0x89, 0xE5, 0x83, 0xEC, 0x08, 0xE8,
0xBC, 0xFF, 0xFF, 0xFF ]
- relocations:
+ relocations:
- offset: 0x00000040
type: GENERIC_RELOC_VANILLA
length: 2
@@ -68,17 +68,17 @@ sections:
attributes: [ ]
alignment: 2
address: 0x0000000000000048
- content: [ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x7A, 0x52, 0x00, 0x01, 0x7C, 0x08, 0x01,
- 0x10, 0x0C, 0x05, 0x04, 0x88, 0x01, 0x00, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
- 0x98, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x00, 0x00,
- 0x00, 0x41, 0x0E, 0x08, 0x84, 0x02, 0x42, 0x0D,
- 0x04, 0x44, 0x86, 0x03, 0x18, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0xB5, 0xFF, 0xFF, 0xFF,
- 0x0B, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0E, 0x08,
+ content: [ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x7A, 0x52, 0x00, 0x01, 0x7C, 0x08, 0x01,
+ 0x10, 0x0C, 0x05, 0x04, 0x88, 0x01, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
+ 0x98, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x00, 0x00,
+ 0x00, 0x41, 0x0E, 0x08, 0x84, 0x02, 0x42, 0x0D,
+ 0x04, 0x44, 0x86, 0x03, 0x18, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0xB5, 0xFF, 0xFF, 0xFF,
+ 0x0B, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0E, 0x08,
0x84, 0x02, 0x42, 0x0D, 0x04, 0x00, 0x00, 0x00 ]
-global-symbols:
+global-symbols:
- name: __Z3barv
type: N_SECT
scope: [ N_EXT ]
@@ -89,7 +89,7 @@ global-symbols:
scope: [ N_EXT ]
sect: 1
value: 0x0000000000000000
-undefined-symbols:
+undefined-symbols:
- name: __ZTIi
type: N_UNDF
scope: [ N_EXT ]
@@ -104,12 +104,12 @@ undefined-symbols:
value: 0x0000000000000000
...
-# CHECK: defined-atoms:
+# CHECK: defined-atoms:
# CHECK: - ref-name: [[CIE:L[L0-9]+]]
# CHECK: type: unwind-cfi
-# CHECK: content:
+# CHECK: content:
# CHECK: - type: unwind-cfi
-# CHECK: content:
+# CHECK: content:
# CHECK: references:
# CHECK: - kind: negDelta32
# CHECK: offset: 4
@@ -118,7 +118,7 @@ undefined-symbols:
# CHECK: offset: 8
# CHECK: target: __Z3foov
# CHECK: - type: unwind-cfi
-# CHECK: content:
+# CHECK: content:
# CHECK: references:
# CHECK: - kind: negDelta32
# CHECK: offset: 4
diff --git a/test/mach-o/parse-eh-frame-x86-labeled.yaml b/test/mach-o/parse-eh-frame-x86-labeled.yaml
index b07a534e6493..5be5abcc4a0e 100644
--- a/test/mach-o/parse-eh-frame-x86-labeled.yaml
+++ b/test/mach-o/parse-eh-frame-x86-labeled.yaml
@@ -9,22 +9,22 @@ arch: x86
file-type: MH_OBJECT
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
OS: unknown
-sections:
+sections:
- segment: __TEXT
section: __text
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
- content: [ 0x55, 0x89, 0xE5, 0x56, 0x83, 0xEC, 0x14, 0xE8,
- 0x00, 0x00, 0x00, 0x00, 0x5E, 0xC7, 0x04, 0x24,
- 0x04, 0x00, 0x00, 0x00, 0xE8, 0xE7, 0xFF, 0xFF,
- 0xFF, 0xC7, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x8B,
- 0x8E, 0x38, 0x00, 0x00, 0x00, 0x89, 0x4C, 0x24,
- 0x04, 0x89, 0x04, 0x24, 0xC7, 0x44, 0x24, 0x08,
- 0x00, 0x00, 0x00, 0x00, 0xE8, 0xC7, 0xFF, 0xFF,
- 0xFF, 0x55, 0x89, 0xE5, 0x83, 0xEC, 0x08, 0xE8,
+ content: [ 0x55, 0x89, 0xE5, 0x56, 0x83, 0xEC, 0x14, 0xE8,
+ 0x00, 0x00, 0x00, 0x00, 0x5E, 0xC7, 0x04, 0x24,
+ 0x04, 0x00, 0x00, 0x00, 0xE8, 0xE7, 0xFF, 0xFF,
+ 0xFF, 0xC7, 0x00, 0x0A, 0x00, 0x00, 0x00, 0x8B,
+ 0x8E, 0x38, 0x00, 0x00, 0x00, 0x89, 0x4C, 0x24,
+ 0x04, 0x89, 0x04, 0x24, 0xC7, 0x44, 0x24, 0x08,
+ 0x00, 0x00, 0x00, 0x00, 0xE8, 0xC7, 0xFF, 0xFF,
+ 0xFF, 0x55, 0x89, 0xE5, 0x83, 0xEC, 0x08, 0xE8,
0xBC, 0xFF, 0xFF, 0xFF ]
- relocations:
+ relocations:
- offset: 0x00000040
type: GENERIC_RELOC_VANILLA
length: 2
@@ -68,17 +68,17 @@ sections:
attributes: [ ]
alignment: 2
address: 0x0000000000000048
- content: [ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x01, 0x7A, 0x52, 0x00, 0x01, 0x7C, 0x08, 0x01,
- 0x10, 0x0C, 0x05, 0x04, 0x88, 0x01, 0x00, 0x00,
- 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
- 0x98, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x00, 0x00,
- 0x00, 0x41, 0x0E, 0x08, 0x84, 0x02, 0x42, 0x0D,
- 0x04, 0x44, 0x86, 0x03, 0x18, 0x00, 0x00, 0x00,
- 0x38, 0x00, 0x00, 0x00, 0xB5, 0xFF, 0xFF, 0xFF,
- 0x0B, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0E, 0x08,
+ content: [ 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0x7A, 0x52, 0x00, 0x01, 0x7C, 0x08, 0x01,
+ 0x10, 0x0C, 0x05, 0x04, 0x88, 0x01, 0x00, 0x00,
+ 0x18, 0x00, 0x00, 0x00, 0x1C, 0x00, 0x00, 0x00,
+ 0x98, 0xFF, 0xFF, 0xFF, 0x39, 0x00, 0x00, 0x00,
+ 0x00, 0x41, 0x0E, 0x08, 0x84, 0x02, 0x42, 0x0D,
+ 0x04, 0x44, 0x86, 0x03, 0x18, 0x00, 0x00, 0x00,
+ 0x38, 0x00, 0x00, 0x00, 0xB5, 0xFF, 0xFF, 0xFF,
+ 0x0B, 0x00, 0x00, 0x00, 0x00, 0x41, 0x0E, 0x08,
0x84, 0x02, 0x42, 0x0D, 0x04, 0x00, 0x00, 0x00 ]
- relocations:
+ relocations:
- offset: 0x0000001C
scattered: true
type: GENERIC_RELOC_LOCAL_SECTDIFF
@@ -127,12 +127,12 @@ sections:
length: 2
pc-rel: false
value: 0x00000084
-local-symbols:
+local-symbols:
- name: EH_frame0
type: N_SECT
sect: 3
value: 0x0000000000000048
-global-symbols:
+global-symbols:
- name: __Z3barv
type: N_SECT
scope: [ N_EXT ]
@@ -153,7 +153,7 @@ global-symbols:
scope: [ N_EXT ]
sect: 3
value: 0x0000000000000060
-undefined-symbols:
+undefined-symbols:
- name: __ZTIi
type: N_UNDF
scope: [ N_EXT ]
@@ -168,13 +168,13 @@ undefined-symbols:
value: 0x0000000000000000
...
-# CHECK: defined-atoms:
+# CHECK: defined-atoms:
# CHECK: - ref-name: [[CIE:L[L0-9]+]]
# CHECK: type: unwind-cfi
-# CHECK: content:
+# CHECK: content:
# CHECK: - type: unwind-cfi
-# CHECK: content:
-# CHECK: references:
+# CHECK: content:
+# CHECK: references:
# CHECK: - kind: negDelta32
# CHECK: offset: 4
# CHECK: target: [[CIE]]
@@ -182,8 +182,8 @@ undefined-symbols:
# CHECK: offset: 8
# CHECK: target: __Z3foov
# CHECK: - type: unwind-cfi
-# CHECK: content:
-# CHECK: references:
+# CHECK: content:
+# CHECK: references:
# CHECK: - kind: negDelta32
# CHECK: offset: 4
# CHECK: target: [[CIE]]
diff --git a/test/mach-o/parse-function.yaml b/test/mach-o/parse-function.yaml
index 1bc9878c7087..bfd8e5c815f4 100644
--- a/test/mach-o/parse-function.yaml
+++ b/test/mach-o/parse-function.yaml
@@ -1,4 +1,4 @@
-# RUN: lld -flavor darwin -arch x86_64 -r %s -o %t
+# RUN: lld -flavor darwin -arch x86_64 -r %s -o %t
# RUN: lld -flavor darwin -arch x86_64 -r %t -print_atoms -o %t2 | FileCheck %s
#
# Test parsing of mach-o functions.
@@ -17,7 +17,7 @@ sections:
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
alignment: 4
address: 0x0000000000000000
- content: [ 0xCC, 0xC3, 0x90, 0xC3, 0x90, 0x90, 0xC3, 0x90,
+ content: [ 0xCC, 0xC3, 0x90, 0xC3, 0x90, 0x90, 0xC3, 0x90,
0x90, 0x90, 0xC3, 0x90, 0x90, 0x90, 0x90, 0xC3,
0xCC, 0x31, 0xC0, 0xC3 ]
local-symbols:
@@ -62,7 +62,7 @@ global-symbols:
value: 0x0000000000000011
...
-# CHECK-NOT: name:
+# CHECK-NOT: name:
# CHECK: content: [ CC ]
# CHECK: name: _myGlobal
diff --git a/test/mach-o/parse-initializers64.yaml b/test/mach-o/parse-initializers64.yaml
index 5ebd8dafd7ce..c55a0ea0a5fa 100644
--- a/test/mach-o/parse-initializers64.yaml
+++ b/test/mach-o/parse-initializers64.yaml
@@ -22,7 +22,7 @@ sections:
section: __mod_init_func
type: S_MOD_INIT_FUNC_POINTERS
attributes: [ ]
- alignment: 0
+ alignment: 1
address: 0x0000000000000100
content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
@@ -43,7 +43,7 @@ sections:
section: __mod_term_func
type: S_MOD_TERM_FUNC_POINTERS
attributes: [ ]
- alignment: 3
+ alignment: 8
address: 0x0000000000000108
content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
relocations:
@@ -76,21 +76,21 @@ global-symbols:
# CHECK: - type: initializer-pointer
# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
# CHECK: dead-strip: never
-# CHECK: references:
+# CHECK: references:
# CHECK: - kind: pointer64
# CHECK: offset: 0
# CHECK: target: _init
# CHECK: - type: initializer-pointer
# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
# CHECK: dead-strip: never
-# CHECK: references:
+# CHECK: references:
# CHECK: - kind: pointer64
# CHECK: offset: 0
# CHECK: target: _init2
# CHECK: - type: terminator-pointer
# CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
# CHECK: dead-strip: never
-# CHECK: references:
+# CHECK: references:
# CHECK: - kind: pointer64
# CHECK: offset: 0
# CHECK: target: _term
diff --git a/test/mach-o/parse-literals-error.yaml b/test/mach-o/parse-literals-error.yaml
index be21d6efffa3..8daeeca5f654 100644
--- a/test/mach-o/parse-literals-error.yaml
+++ b/test/mach-o/parse-literals-error.yaml
@@ -21,5 +21,5 @@ sections:
0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D ]
...
-# CHECK: error:
+# CHECK: error:
diff --git a/test/mach-o/parse-literals.yaml b/test/mach-o/parse-literals.yaml
index 24568ea0fd4f..7f80ba5212b8 100644
--- a/test/mach-o/parse-literals.yaml
+++ b/test/mach-o/parse-literals.yaml
@@ -14,16 +14,16 @@ sections:
section: __cstring
type: S_CSTRING_LITERALS
attributes: [ ]
- alignment: 0
+ alignment: 1
address: 0x0000000000000100
- content: [ 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x00, 0x74, 0x68,
- 0x65, 0x72, 0x65, 0x00, 0x77, 0x6F, 0x72, 0x6C,
+ content: [ 0x68, 0x65, 0x6C, 0x6C, 0x6F, 0x00, 0x74, 0x68,
+ 0x65, 0x72, 0x65, 0x00, 0x77, 0x6F, 0x72, 0x6C,
0x00 ]
- segment: __TEXT
section: __literal4
type: S_4BYTE_LITERALS
attributes: [ ]
- alignment: 0
+ alignment: 1
address: 0x0000000000000114
content: [ 0x01, 0x02, 0x03, 0x04, 0x11, 0x12, 0x13, 0x14,
0x28, 0x29, 0x2A, 0x2B ]
@@ -31,7 +31,7 @@ sections:
section: __literal8
type: S_8BYTE_LITERALS
attributes: [ ]
- alignment: 0
+ alignment: 1
address: 0x0000000000000120
content: [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F ]
@@ -39,7 +39,7 @@ sections:
section: __literal16
type: S_16BYTE_LITERALS
attributes: [ ]
- alignment: 0
+ alignment: 1
address: 0x0000000000000130
content: [ 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x00 ]
@@ -47,15 +47,15 @@ sections:
section: __ustring
type: S_REGULAR
attributes: [ ]
- alignment: 0
+ alignment: 1
address: 0x0000000000000100
- content: [ 0x68, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x6C, 0x00,
- 0x6F, 0x00, 0x00, 0x00, 0x74, 0x00, 0x68, 0x00,
+ content: [ 0x68, 0x00, 0x65, 0x00, 0x6C, 0x00, 0x6C, 0x00,
+ 0x6F, 0x00, 0x00, 0x00, 0x74, 0x00, 0x68, 0x00,
0x65, 0x00, 0x72, 0x00, 0x00, 0x00 ]
...
-# CHECK:defined-atoms:
+# CHECK:defined-atoms:
# CHECK: - scope: hidden
# CHECK: type: c-string
# CHECK: content: [ 68, 65, 6C, 6C, 6F, 00 ]
@@ -88,6 +88,6 @@ sections:
# CHECK: content: [ 28, 29, 2A, 2B, 2C, 2D, 2E, 2F ]
# CHECK: - scope: hidden
# CHECK: type: const-16-byte
-# CHECK: content: [ 01, 02, 03, 04, 05, 06, 07, 08, 09, 0A, 0B, 0C,
+# CHECK: content: [ 01, 02, 03, 04, 05, 06, 07, 08, 09, 0A, 0B, 0C,
# CHECK: 0D, 0E, 0F, 00 ]
diff --git a/test/mach-o/parse-relocs-x86.yaml b/test/mach-o/parse-relocs-x86.yaml
index 3fc22ae71bfc..c7ce80bb42a1 100644
--- a/test/mach-o/parse-relocs-x86.yaml
+++ b/test/mach-o/parse-relocs-x86.yaml
@@ -28,7 +28,7 @@
# ret
#
# .data
-#_x:
+#_x:
# .long _undef
# .long _undef+7
# .long _foo
@@ -42,21 +42,21 @@ arch: x86
file-type: MH_OBJECT
flags: [ MH_SUBSECTIONS_VIA_SYMBOLS ]
OS: unknown
-sections:
+sections:
- segment: __TEXT
section: __text
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
- content: [ 0xE8, 0xFB, 0xFF, 0xFF, 0xFF, 0xE8, 0xF8, 0xFF,
- 0xFF, 0xFF, 0xE8, 0x2C, 0x00, 0x00, 0x00, 0xE8,
- 0x29, 0x00, 0x00, 0x00, 0x66, 0xE8, 0xE8, 0xFF,
- 0x66, 0xE8, 0x1F, 0x00, 0x66, 0xE8, 0x1D, 0x00,
- 0xA1, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x3C, 0x00,
- 0x00, 0x00, 0xA1, 0x40, 0x00, 0x00, 0x00, 0x8B,
- 0x80, 0x1C, 0x00, 0x00, 0x00, 0x8B, 0x80, 0x20,
+ content: [ 0xE8, 0xFB, 0xFF, 0xFF, 0xFF, 0xE8, 0xF8, 0xFF,
+ 0xFF, 0xFF, 0xE8, 0x2C, 0x00, 0x00, 0x00, 0xE8,
+ 0x29, 0x00, 0x00, 0x00, 0x66, 0xE8, 0xE8, 0xFF,
+ 0x66, 0xE8, 0x1F, 0x00, 0x66, 0xE8, 0x1D, 0x00,
+ 0xA1, 0x00, 0x00, 0x00, 0x00, 0xA1, 0x3C, 0x00,
+ 0x00, 0x00, 0xA1, 0x40, 0x00, 0x00, 0x00, 0x8B,
+ 0x80, 0x1C, 0x00, 0x00, 0x00, 0x8B, 0x80, 0x20,
0x00, 0x00, 0x00, 0xC3 ]
- relocations:
+ relocations:
- offset: 0x00000037
scattered: true
type: GENERIC_RELOC_LOCAL_SECTDIFF
@@ -146,10 +146,10 @@ sections:
type: S_REGULAR
attributes: [ ]
address: 0x000000000000003C
- content: [ 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
- 0x3B, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00,
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00,
+ 0x3B, 0x00, 0x00, 0x00, 0x3E, 0x00, 0x00, 0x00,
0xB4, 0xFF, 0xFF, 0xFF, 0xB3, 0xFF, 0xFF, 0xFF ]
- relocations:
+ relocations:
- offset: 0x00000014
scattered: true
type: GENERIC_RELOC_LOCAL_SECTDIFF
@@ -198,7 +198,7 @@ sections:
pc-rel: false
extern: true
symbol: 3
-local-symbols:
+local-symbols:
- name: _test
type: N_SECT
sect: 1
@@ -211,7 +211,7 @@ local-symbols:
type: N_SECT
sect: 2
value: 0x000000000000003C
-undefined-symbols:
+undefined-symbols:
- name: _undef
type: N_UNDF
scope: [ N_EXT ]
diff --git a/test/mach-o/parse-tentative-defs.yaml b/test/mach-o/parse-tentative-defs.yaml
index fc75167bd895..1757c8c928b6 100644
--- a/test/mach-o/parse-tentative-defs.yaml
+++ b/test/mach-o/parse-tentative-defs.yaml
@@ -57,32 +57,32 @@ undefined-symbols:
# CHECK: type: zero-fill
# CHECK: size: 4
# CHECK: merge: as-tentative
-# CHECK: alignment: 2^2
+# CHECK: alignment: 4
# CHECK: name: _tent4_16
# CHECK: scope: global
# CHECK: type: zero-fill
# CHECK: size: 4
# CHECK: merge: as-tentative
-# CHECK: alignment: 2^4
+# CHECK: alignment: 16
# CHECK: name: _tent64_32
# CHECK: scope: global
# CHECK: type: zero-fill
# CHECK: size: 64
# CHECK: merge: as-tentative
-# CHECK: alignment: 2^5
+# CHECK: alignment: 32
# CHECK: name: _tent8
# CHECK: scope: global
# CHECK: type: zero-fill
# CHECK: size: 8
# CHECK: merge: as-tentative
-# CHECK: alignment: 2^3
+# CHECK: alignment: 8
# CHECK: name: _tentHidden
# CHECK: scope: hidden
# CHECK: type: zero-fill
# CHECK: size: 4
# CHECK: merge: as-tentative
-# CHECK: alignment: 2^2
+# CHECK: alignment: 4
diff --git a/test/mach-o/parse-text-relocs-x86_64.yaml b/test/mach-o/parse-text-relocs-x86_64.yaml
index 9e58e02e3771..6d0a52f60045 100644
--- a/test/mach-o/parse-text-relocs-x86_64.yaml
+++ b/test/mach-o/parse-text-relocs-x86_64.yaml
@@ -19,6 +19,9 @@
# movw $0x1234, _foo(%rip)
# movl $0x12345678, _foo(%rip)
# movl L2(%rip), %eax
+# movb $0x12, L2(%rip)
+# movw $0x1234, L2(%rip)
+# movl $0x12345678, L2(%rip)
#
# .data
#L2: .long 0
@@ -41,9 +44,30 @@ sections:
0x00, 0x00, 0x00, 0xC6, 0x05, 0xFF, 0xFF, 0xFF,
0xFF, 0x12, 0x66, 0xC7, 0x05, 0xFE, 0xFF, 0xFF,
0xFF, 0x34, 0x12, 0xC7, 0x05, 0xFC, 0xFF, 0xFF,
- 0xFF, 0x78, 0x56, 0x34, 0x12, 0x8B, 0x05, 0x00,
- 0x00, 0x00, 0x00 ]
+ 0xFF, 0x78, 0x56, 0x34, 0x12, 0x8B, 0x05, 0x1A,
+ 0x00, 0x00, 0x00, 0xc6, 0x05, 0x13, 0x00, 0x00,
+ 0x00, 0x12, 0x66, 0xc7, 0x05, 0x0a, 0x00, 0x00,
+ 0x00, 0x34, 0x12, 0xc7, 0x05, 0x00, 0x00, 0x00,
+ 0x00, 0x78, 0x56, 0x34, 0x12 ]
relocations:
+ - offset: 0x00000055
+ type: X86_64_RELOC_SIGNED_4
+ length: 2
+ pc-rel: true
+ extern: false
+ symbol: 2
+ - offset: 0x0000004d
+ type: X86_64_RELOC_SIGNED_2
+ length: 2
+ pc-rel: true
+ extern: false
+ symbol: 2
+ - offset: 0x00000045
+ type: X86_64_RELOC_SIGNED_1
+ length: 2
+ pc-rel: true
+ extern: false
+ symbol: 2
- offset: 0x0000003F
type: X86_64_RELOC_SIGNED
length: 2
@@ -108,7 +132,7 @@ sections:
section: __data
type: S_REGULAR
attributes: [ ]
- address: 0x0000000000000043
+ address: 0x000000000000005D
content: [ 0x00, 0x00, 0x00, 0x00 ]
local-symbols:
- name: _test
@@ -166,3 +190,15 @@ undefined-symbols:
# CHECK: offset: 63
# CHECK: target: [[LABEL]]
# CHECK-NOT: addend:
+# CHECK: - kind: ripRel32Minus1Anon
+# CHECK: offset: 69
+# CHECK: target: [[LABEL]]
+# CHECK-NOT: addend:
+# CHECK: - kind: ripRel32Minus2Anon
+# CHECK: offset: 77
+# CHECK: target: [[LABEL]]
+# CHECK-NOT: addend:
+# CHECK: - kind: ripRel32Minus4Anon
+# CHECK: offset: 85
+# CHECK: target: [[LABEL]]
+# CHECK-NOT: addend:
diff --git a/test/mach-o/parse-tlv-relocs-x86-64.yaml b/test/mach-o/parse-tlv-relocs-x86-64.yaml
new file mode 100644
index 000000000000..78b17841d4e7
--- /dev/null
+++ b/test/mach-o/parse-tlv-relocs-x86-64.yaml
@@ -0,0 +1,100 @@
+# 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
+#
+# Test parsing of x86_64 tlv relocations.
+
+--- !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: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ alignment: 16
+ address: 0x0000000000000000
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x8B, 0x3D, 0x00,
+ 0x00, 0x00, 0x00, 0xFF, 0x17, 0x8B, 0x00, 0x5D,
+ 0xC3 ]
+ relocations:
+ - offset: 0x00000007
+ type: X86_64_RELOC_TLV
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 2
+ - segment: __DATA
+ section: __thread_data
+ type: S_THREAD_LOCAL_REGULAR
+ attributes: [ ]
+ alignment: 4
+ address: 0x0000000000000014
+ content: [ 0x07, 0x00, 0x00, 0x00 ]
+ - segment: __DATA
+ section: __thread_vars
+ type: S_THREAD_LOCAL_VARIABLES
+ attributes: [ ]
+ address: 0x0000000000000018
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+ relocations:
+ - offset: 0x00000010
+ 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: 3
+local-symbols:
+ - name: '_x$tlv$init'
+ type: N_SECT
+ sect: 2
+ value: 0x0000000000000014
+global-symbols:
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+ - name: _x
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 3
+ value: 0x0000000000000018
+undefined-symbols:
+ - name: __tlv_bootstrap
+ type: N_UNDF
+ scope: [ N_EXT ]
+ value: 0x0000000000000000
+page-size: 0x00000000
+...
+
+# CHECK: - name: _x
+# CHECK-NEXT: scope: global
+# CHECK-NEXT: type: tlv-thunk
+# CHECK-NOT: - name:
+# CHECK: references:
+# CHECK-NEXT: - kind: pointer64
+# CHECK-NEXT: offset: 0
+# CHECK-NEXT: target: __tlv_bootstrap
+# CHECK-NEXT: - kind: tlvInitSectionOffset
+# CHECK-NEXT: offset: 16
+# CHECK-NEXT: target: '_x$tlv$init'
+# CHECK: - name: _main
+# CHECK-NOT: - name:
+# CHECK-NEXT: scope: global
+# CHECK: references:
+# CHECK-NEXT: - kind: ripRel32Tlv
+# CHECK-NEXT: offset: 7
+# CHECK-NEXT: target: _x
diff --git a/test/mach-o/re-exported-dylib-ordinal.yaml b/test/mach-o/re-exported-dylib-ordinal.yaml
index 9d628e9af151..ff4d756338ce 100644
--- a/test/mach-o/re-exported-dylib-ordinal.yaml
+++ b/test/mach-o/re-exported-dylib-ordinal.yaml
@@ -1,4 +1,7 @@
-# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s -dylib -o %t \
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.8 %s \
+# RUN: %p/Inputs/re-exported-dylib-ordinal.yaml \
+# RUN: %p/Inputs/re-exported-dylib-ordinal2.yaml \
+# RUN: %p/Inputs/re-exported-dylib-ordinal3.yaml -dylib -o %t \
# RUN: && llvm-nm -m %t | FileCheck %s
#
# Test that when one dylib A re-exports dylib B that using a symbol from B
@@ -37,68 +40,6 @@ undefined-symbols:
type: N_UNDF
scope: [ N_EXT ]
value: 0x0000000000000000
-
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-flags: [ MH_TWOLEVEL ]
-install-name: /junk/libfoo.dylib
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000F9A
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3 ]
-global-symbols:
- - name: _foo
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000F9A
-dependents:
- - path: /junk/libbar.dylib
- kind: LC_REEXPORT_DYLIB
-
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-flags: [ MH_TWOLEVEL ]
-install-name: /junk/libbar.dylib
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000F9A
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x5D, 0xC3 ]
-global-symbols:
- - name: _bar
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000F9A
-
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-flags: [ MH_TWOLEVEL ]
-install-name: /usr/lib/libSystem.B.dylib
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55 ]
-
-global-symbols:
- - name: dyld_stub_binder
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-
...
# CHECK: (undefined) external _bar (from libfoo)
diff --git a/test/mach-o/rpath.yaml b/test/mach-o/rpath.yaml
index f0b5f718c15a..ce1234d4c78f 100644
--- a/test/mach-o/rpath.yaml
+++ b/test/mach-o/rpath.yaml
@@ -34,5 +34,5 @@ global-symbols:
# CHECK-BINARY-WRITE: cmd LC_RPATH
-# CHECK-BINARY-WRITE-NEXT: cmdsize 44
+# CHECK-BINARY-WRITE-NEXT: cmdsize 40
# CHECK-BINARY-WRITE-NEXT: path @loader_path/../Frameworks (offset 12)
diff --git a/test/mach-o/run-tlv-pass-x86-64.yaml b/test/mach-o/run-tlv-pass-x86-64.yaml
new file mode 100644
index 000000000000..0e648458645b
--- /dev/null
+++ b/test/mach-o/run-tlv-pass-x86-64.yaml
@@ -0,0 +1,144 @@
+# RUN: lld -flavor darwin -macosx_version_min 10.7 -arch x86_64 -print_atoms %s -o %t | FileCheck %s
+# RUN: not lld -flavor darwin -macosx_version_min 10.6 -arch x86_64 -o %t %s 2> %t2
+# RUN: FileCheck < %t2 %s --check-prefix=CHECK-ERROR
+# RUN: llvm-objdump -macho -private-headers %t | FileCheck %s --check-prefix=CHECK-LOADCMDS
+#
+# Test parsing of x86_64 tlv relocations.
+
+--- !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: __TEXT
+ section: __text
+ type: S_REGULAR
+ attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
+ alignment: 16
+ address: 0x0000000000000000
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x48, 0x8B, 0x3D, 0x00,
+ 0x00, 0x00, 0x00, 0xFF, 0x17, 0x8B, 0x00, 0x5D,
+ 0xC3 ]
+ relocations:
+ - offset: 0x00000007
+ type: X86_64_RELOC_TLV
+ length: 2
+ pc-rel: true
+ extern: true
+ symbol: 2
+ - segment: __DATA
+ section: __thread_bss
+ type: S_THREAD_LOCAL_ZEROFILL
+ attributes: [ ]
+ alignment: 4
+ address: 0x0000000000000014
+ size: 4
+ - segment: __DATA
+ section: __thread_vars
+ type: S_THREAD_LOCAL_VARIABLES
+ attributes: [ ]
+ address: 0x0000000000000018
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+ relocations:
+ - offset: 0x00000010
+ 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: 3
+ - segment: __DATA
+ section: __dummy
+ type: S_REGULAR
+ attributes: [ ]
+ alignment: 8
+ address: 0x00000000000000C0
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
+local-symbols:
+ - name: '_x$tlv$init'
+ type: N_SECT
+ sect: 2
+ value: 0x0000000000000014
+global-symbols:
+ - name: _main
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 1
+ value: 0x0000000000000000
+ - name: _x
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 3
+ value: 0x0000000000000018
+ - name: '__tlv_bootstrap'
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 4
+ value: 0x00000000000000C0
+ - name: 'dyld_stub_binder'
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 4
+ value: 0x00000000000000C8
+ - name: 'start'
+ type: N_SECT
+ scope: [ N_EXT ]
+ sect: 4
+ value: 0x00000000000000D0
+page-size: 0x00000000
+...
+
+# CHECK: - name: _x
+# CHECK-NEXT: scope: global
+# CHECK-NEXT: type: tlv-thunk
+# CHECK-NOT: - name:
+# CHECK: references:
+# CHECK-NEXT: - kind: pointer64
+# CHECK-NEXT: offset: 0
+# CHECK-NEXT: target: __tlv_bootstrap
+# CHECK-NEXT: - kind: tlvInitSectionOffset
+# CHECK-NEXT: offset: 16
+# CHECK-NEXT: target: '_x$tlv$init'
+# CHECK: - name: '_x$tlv$init'
+# CHECK-NEXT: type: tlv-zero-fill
+# CHECK: - name: _main
+# CHECK-NOT: - name:
+# CHECK: references:
+# CHECK-NEXT: - kind: ripRel32
+# CHECK-NEXT: offset: 7
+# CHECK-NEXT: target: L[[ID:[0-9]+]]
+# CHECK: - ref-name: L[[ID]]
+# CHECK-NEXT: scope: hidden
+# CHECK-NEXT: type: tlv-initializer-ptr
+# CHECK-NEXT: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ]
+# CHECK-NEXT: alignment: 8
+# CHECK-NEXT: permissions: rw-
+# CHECK-NEXT: references:
+# CHECK-NEXT: - kind: pointer64
+# CHECK-NEXT: offset: 0
+# CHECK-NEXT: target: _x
+
+# CHECK-ERROR: targeted OS version does not support use of thread local variables in _main for architecture x86_64
+
+# CHECK-LOADCMDS: sectname __thread_bss
+# CHECK-LOADCMDS: segname __DATA
+# CHECK-LOADCMDS: addr 0x{{[0-9A-F]*}}
+# CHECK-LOADCMDS: size 0x0000000000000004
+# CHECK-LOADCMDS: offset 0
+# CHECK-LOADCMDS: align 2^2 (4)
+# CHECK-LOADCMDS: reloff 0
+# CHECK-LOADCMDS: nreloc 0
+# CHECK-LOADCMDS: type S_THREAD_LOCAL_ZEROFILL
diff --git a/test/mach-o/sectalign.yaml b/test/mach-o/sectalign.yaml
index 3556a5ecbcfc..556fd52c96e1 100644
--- a/test/mach-o/sectalign.yaml
+++ b/test/mach-o/sectalign.yaml
@@ -16,8 +16,8 @@ sections:
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x8B, 0x05, 0x00, 0x00,
- 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00,
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x8B, 0x05, 0x00, 0x00,
+ 0x00, 0x00, 0x03, 0x05, 0x00, 0x00, 0x00, 0x00,
0x5D, 0xC3 ]
relocations:
- offset: 0x0000000C
diff --git a/test/mach-o/sectcreate.yaml b/test/mach-o/sectcreate.yaml
new file mode 100644
index 000000000000..51c59dc5f3d4
--- /dev/null
+++ b/test/mach-o/sectcreate.yaml
@@ -0,0 +1,12 @@
+# RUN: lld -flavor darwin -r -arch x86_64 -o %t -sectcreate __DATA __data \
+# RUN: %p/Inputs/hw.raw_bytes -print_atoms | FileCheck %s
+
+# CHECK: --- !native
+# CHECK: path: '<linker-internal>'
+# CHECK: defined-atoms:
+# CHECK: - scope: global
+# CHECK: type: sectcreate
+# CHECK: content: [ 68, 65, 6C, 6C, 6F, 0A ]
+# CHECK: section-choice: custom-required
+# CHECK: section-name: __DATA/__data
+# CHECK: dead-strip: never
diff --git a/test/mach-o/stack-size.yaml b/test/mach-o/stack-size.yaml
new file mode 100644
index 000000000000..0e8edb2b5498
--- /dev/null
+++ b/test/mach-o/stack-size.yaml
@@ -0,0 +1,24 @@
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.9 %s -o %t %p/Inputs/libSystem.yaml
+# RUN: llvm-objdump -private-headers %t | FileCheck --check-prefix=CHECK-DEFAULT %s
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.9 %s -o %t -stack_size 31415926000 %p/Inputs/libSystem.yaml
+# RUN: llvm-objdump -private-headers %t | FileCheck --check-prefix=CHECK-EXPLICIT %s
+# RUN: not lld -flavor darwin -arch x86_64 -stack_size 0x31415926530 %s >/dev/null 2> %t
+# RUN: FileCheck < %t %s --check-prefix=CHECK-ERROR-MISPAGED
+# RUN: not lld -flavor darwin -arch x86_64 -stack_size hithere %s >/dev/null 2> %t
+# RUN: FileCheck < %t %s --check-prefix=CHECK-ERROR-NOTHEX
+
+--- !native
+defined-atoms:
+ - name: _main
+ scope: global
+ content: []
+
+# CHECK-DEFAULT: cmd LC_MAIN
+# CHECK-DEFAULT: stacksize 0
+
+# CHECK-EXPLICIT: cmd LC_MAIN
+# CHECK-EXPLICIT: stacksize 3384796143616
+
+# CHECK-ERROR-MISPAGED: error: stack_size must be a multiple of page size (0x1000)
+
+# CHECK-ERROR-NOTHEX: error: stack_size expects a hex number
diff --git a/test/mach-o/twolevel_namespace_undef_dynamic_lookup.yaml b/test/mach-o/twolevel_namespace_undef_dynamic_lookup.yaml
new file mode 100644
index 000000000000..a39a3e7f8c1b
--- /dev/null
+++ b/test/mach-o/twolevel_namespace_undef_dynamic_lookup.yaml
@@ -0,0 +1,17 @@
+# RUN: lld -flavor darwin -arch x86_64 -macosx_version_min 10.9 -twolevel_namespace -undefined dynamic_lookup %s -o %t %p/Inputs/libSystem.yaml
+#
+# Sanity check '-twolevel_namespace -undefined dynamic_lookup'.
+# This should pass without error, even though '_bar' is undefined.
+
+--- !native
+defined-atoms:
+ - name: _main
+ scope: global
+ content: [ E9, 00, 00, 00, 00 ]
+ alignment: 16
+ references:
+ - kind: branch32
+ offset: 1
+ target: _bar
+undefined-atoms:
+ - name: _bar
diff --git a/test/mach-o/twolevel_namespace_undef_warning_suppress.yaml b/test/mach-o/twolevel_namespace_undef_warning_suppress.yaml
new file mode 100644
index 000000000000..eeb01de5f707
--- /dev/null
+++ b/test/mach-o/twolevel_namespace_undef_warning_suppress.yaml
@@ -0,0 +1,23 @@
+# RUN: not lld -flavor darwin -arch x86_64 -macosx_version_min 10.9 -twolevel_namespace -undefined warning %s -o %t %p/Inputs/libSystem.yaml 2>&1 | \
+# RUN: FileCheck --check-prefix=CHECK-WARNING %s
+# RUN: not lld -flavor darwin -arch x86_64 -macosx_version_min 10.9 -twolevel_namespace -undefined suppress %s -o %t %p/Inputs/libSystem.yaml 2>&1 | \
+# RUN: FileCheck --check-prefix=CHECK-SUPPRESS %s
+
+--- !native
+defined-atoms:
+ - name: _main
+ scope: global
+ content: [ E9, 00, 00, 00, 00 ]
+ alignment: 16
+ references:
+ - kind: branch32
+ offset: 1
+ target: _bar
+undefined-atoms:
+ - name: _bar
+
+# Make sure that the driver issues an error diagnostic about this combination
+# being invalid.
+#
+# CHECK-WARNING: can't use -undefined warning or suppress with -twolevel_namespace
+# CHECK-SUPPRESS: can't use -undefined warning or suppress with -twolevel_namespace \ 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 d46b43ff712d..8e87230e2833 100644
--- a/test/mach-o/unwind-info-simple-arm64.yaml
+++ b/test/mach-o/unwind-info-simple-arm64.yaml
@@ -1,4 +1,5 @@
-# RUN: lld -flavor darwin -arch arm64 %s -o %t -e _main %p/Inputs/libSystem.yaml
+# RUN: lld -flavor darwin -arch arm64 -o %t %s \
+# RUN: %p/Inputs/unwind-info-simple-arm64.yaml -e _main %p/Inputs/libSystem.yaml
# RUN: llvm-objdump -unwind-info %t | FileCheck %s
--- !mach-o
@@ -12,20 +13,20 @@ sections:
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
alignment: 2
address: 0x0000000000000000
- content: [ 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91,
- 0xE0, 0x03, 0x1E, 0x32, 0x00, 0x00, 0x00, 0x94,
- 0x48, 0x01, 0x80, 0x52, 0x08, 0x00, 0x00, 0xB9,
- 0x02, 0x00, 0x80, 0xD2, 0x01, 0x00, 0x00, 0x90,
- 0x21, 0x00, 0x40, 0xF9, 0x00, 0x00, 0x00, 0x94,
- 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91,
- 0xE0, 0x03, 0x1E, 0x32, 0x00, 0x00, 0x00, 0x94,
- 0x48, 0x01, 0x80, 0x52, 0x08, 0x00, 0x00, 0xB9,
- 0x02, 0x00, 0x80, 0xD2, 0x01, 0x00, 0x00, 0x90,
- 0x21, 0x00, 0x40, 0xF9, 0x00, 0x00, 0x00, 0x94,
- 0x3F, 0x04, 0x00, 0x71, 0x81, 0x00, 0x00, 0x54,
- 0x00, 0x00, 0x00, 0x94, 0xFD, 0x7B, 0xC1, 0xA8,
- 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x94,
- 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91,
+ content: [ 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91,
+ 0xE0, 0x03, 0x1E, 0x32, 0x00, 0x00, 0x00, 0x94,
+ 0x48, 0x01, 0x80, 0x52, 0x08, 0x00, 0x00, 0xB9,
+ 0x02, 0x00, 0x80, 0xD2, 0x01, 0x00, 0x00, 0x90,
+ 0x21, 0x00, 0x40, 0xF9, 0x00, 0x00, 0x00, 0x94,
+ 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91,
+ 0xE0, 0x03, 0x1E, 0x32, 0x00, 0x00, 0x00, 0x94,
+ 0x48, 0x01, 0x80, 0x52, 0x08, 0x00, 0x00, 0xB9,
+ 0x02, 0x00, 0x80, 0xD2, 0x01, 0x00, 0x00, 0x90,
+ 0x21, 0x00, 0x40, 0xF9, 0x00, 0x00, 0x00, 0x94,
+ 0x3F, 0x04, 0x00, 0x71, 0x81, 0x00, 0x00, 0x54,
+ 0x00, 0x00, 0x00, 0x94, 0xFD, 0x7B, 0xC1, 0xA8,
+ 0x00, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x94,
+ 0xFD, 0x7B, 0xBF, 0xA9, 0xFD, 0x03, 0x00, 0x91,
0x00, 0x00, 0x00, 0x94 ]
relocations:
- offset: 0x00000070
@@ -106,14 +107,14 @@ sections:
attributes: [ ]
alignment: 2
address: 0x0000000000000074
- content: [ 0xFF, 0x9B, 0xAF, 0x80, 0x00, 0x03, 0x27, 0x00,
- 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
- 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
- 0x01, 0x28, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ content: [ 0xFF, 0x9B, 0xAF, 0x80, 0x00, 0x03, 0x27, 0x00,
+ 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00,
+ 0x10, 0x00, 0x00, 0x00, 0x28, 0x00, 0x00, 0x00,
+ 0x01, 0x28, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
0xD0, 0xFF, 0xFF, 0xFF ]
- relocations:
+ relocations:
- offset: 0x00000030
type: ARM64_RELOC_POINTER_TO_GOT
length: 2
@@ -126,19 +127,19 @@ sections:
attributes: [ ]
alignment: 3
address: 0x00000000000000A8
- content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ content: [ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x44,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x74, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x0C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ]
- relocations:
+ relocations:
- offset: 0x00000040
type: ARM64_RELOC_UNSIGNED
length: 3
@@ -186,7 +187,7 @@ local-symbols:
type: N_SECT
sect: 3
value: 0x00000000000000A8
-global-symbols:
+global-symbols:
- name: __Z3barv
type: N_SECT
scope: [ N_EXT ]
@@ -202,7 +203,7 @@ global-symbols:
scope: [ N_EXT ]
sect: 1
value: 0x0000000000000068
-undefined-symbols:
+undefined-symbols:
- name: __Unwind_Resume
type: N_UNDF
scope: [ N_EXT ]
@@ -236,20 +237,6 @@ undefined-symbols:
scope: [ N_EXT ]
value: 0x0000000000000000
---- !mach-o
-arch: arm64
-file-type: MH_DYLIB
-install-name: /usr/lib/libc++.dylib
-exports:
- - name: __Unwind_Resume
- - name: __ZTIl
- - name: __ZTIi
- - name: ___cxa_end_catch
- - name: ___cxa_begin_catch
- - name: ___cxa_allocate_exception
- - name: ___cxa_throw
- - name: ___gxx_personality_v0
-
...
@@ -263,7 +250,7 @@ exports:
# CHECK: Number of indices in array: 0x2
# CHECK: Common encodings: (count = 0)
# CHECK: Personality functions: (count = 1)
-# CHECK: personality[1]: 0x00004018
+# CHECK: personality[1]: 0x00004020
# CHECK: Top level indices: (count = 2)
# CHECK: [0]: function offset=0x00003e68, 2nd level page offset=0x00000040, LSDA offset=0x00000038
# CHECK: [1]: function offset=0x00003edc, 2nd level page offset=0x00000000, LSDA offset=0x00000040
diff --git a/test/mach-o/unwind-info-simple-x86_64.yaml b/test/mach-o/unwind-info-simple-x86_64.yaml
index 8886e5271661..1d2294a99678 100644
--- a/test/mach-o/unwind-info-simple-x86_64.yaml
+++ b/test/mach-o/unwind-info-simple-x86_64.yaml
@@ -67,8 +67,9 @@ defined-atoms:
target: _needsDwarfButNoCompactUnwind
# Generic x86_64 CIE:
- - type: unwind-cfi
- content: [ 14, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 52, 00,
+ - name: LCIE
+ type: unwind-cfi
+ content: [ 14, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 52, 00,
01, 78, 10, 01, 10, 0C, 07, 08, 90, 01, 00, 00 ]
- type: unwind-cfi
@@ -80,6 +81,9 @@ defined-atoms:
- kind: unwindFDEToFunction
offset: 8
target: _needsDwarfButNoCompactUnwind
+ - kind: negDelta32
+ offset: 4
+ target: LCIE
- type: unwind-cfi
content: [ 24, 00, 00, 00, 44, 00, 00, 00, C8, FE, FF, FF,
@@ -90,7 +94,22 @@ defined-atoms:
- kind: unwindFDEToFunction
offset: 8
target: _needsDwarfSaysCompactUnwind
+ - kind: negDelta32
+ offset: 4
+ target: LCIE
+ - type: unwind-cfi
+ content: [ 24, 00, 00, 00, 6C, 00, 00, 00, C8, FE, FF, FF,
+ FF, FF, FF, FF, 01, 00, 00, 00, 00, 00, 00, 00,
+ 00, 41, 0E, 10, 86, 02, 43, 0D, 06, 00, 00, 00,
+ 00, 00, 00, 00 ]
+ references:
+ - kind: unwindFDEToFunction
+ offset: 8
+ target: _main
+ - kind: negDelta32
+ offset: 4
+ target: LCIE
- name: __Z3barv
scope: global
diff --git a/test/mach-o/upward-dylib-load-command.yaml b/test/mach-o/upward-dylib-load-command.yaml
index fee3e41d5bd5..1383ad75b0a6 100644
--- a/test/mach-o/upward-dylib-load-command.yaml
+++ b/test/mach-o/upward-dylib-load-command.yaml
@@ -1,7 +1,7 @@
# RUN: lld -flavor darwin -arch x86_64 -dylib %p/Inputs/bar.yaml \
# RUN: -install_name /usr/lib/libbar.dylib %p/Inputs/libSystem.yaml -o %t1.dylib
# RUN: lld -flavor darwin -arch x86_64 -dylib %s -upward_library %t1.dylib \
-# RUN: -install_name /usr/lib/libfoo.dylib %p/Inputs/libSystem.yaml -o %t
+# RUN: -install_name /usr/lib/libfoo.dylib %p/Inputs/libSystem.yaml -o %t
# RUN: llvm-objdump -private-headers %t | FileCheck %s
#
#
@@ -19,7 +19,7 @@ sections:
type: S_REGULAR
attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
address: 0x0000000000000000
- content: [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0x5D, 0xE9,
+ content: [ 0x55, 0x48, 0x89, 0xE5, 0x31, 0xC0, 0x5D, 0xE9,
0x00, 0x00, 0x00, 0x00 ]
relocations:
- offset: 0x00000008
diff --git a/test/mach-o/use-simple-dylib.yaml b/test/mach-o/use-simple-dylib.yaml
index 0da7d1b0bd05..658be16356ea 100644
--- a/test/mach-o/use-simple-dylib.yaml
+++ b/test/mach-o/use-simple-dylib.yaml
@@ -1,4 +1,5 @@
-# RUN: lld -flavor darwin -arch x86_64 -print_atoms -r %s -o %t | FileCheck %s
+# RUN: lld -flavor darwin -arch x86_64 -print_atoms -r %s \
+# RUN: %p/Inputs/use-simple-dylib.yaml -o %t | FileCheck %s
--- !mach-o
@@ -53,65 +54,6 @@ undefined-symbols:
type: N_UNDF
scope: [ N_EXT ]
value: 0x0000000000000000
-
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-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 ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0xCC, 0xC3, 0x90, 0xC3, 0x90, 0x90, 0xC3, 0x90,
- 0x90, 0x90, 0xC3, 0x90, 0x90, 0x90, 0x90, 0xC3,
- 0x31, 0xC0, 0xC3 ]
-local-symbols:
- - name: _myStatic
- type: N_SECT
- sect: 1
- value: 0x000000000000000B
- - name: _myVariablePreviouslyKnownAsPrivateExtern
- type: N_SECT
- scope: [ N_PEXT ]
- sect: 1
- desc: [ N_SYMBOL_RESOLVER ]
- value: 0x0000000000000011
-global-symbols:
- - name: _myGlobal
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000001
- - name: _myGlobalWeak
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ N_WEAK_DEF ]
- value: 0x0000000000000002
- - name: _myHidden
- type: N_SECT
- scope: [ N_EXT, N_PEXT ]
- sect: 1
- value: 0x0000000000000004
- - name: _myHiddenWeak
- type: N_SECT
- scope: [ N_EXT, N_PEXT ]
- sect: 1
- desc: [ N_WEAK_DEF ]
- value: 0x0000000000000007
- - name: _myResolver
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- desc: [ N_SYMBOL_RESOLVER ]
- value: 0x0000000000000010
-
-install-name: libspecial.dylib
...
diff --git a/test/mach-o/write-final-sections.yaml b/test/mach-o/write-final-sections.yaml
index 7d4afb31900a..4e94acfa25b1 100644
--- a/test/mach-o/write-final-sections.yaml
+++ b/test/mach-o/write-final-sections.yaml
@@ -1,4 +1,5 @@
-# RUN: lld -flavor darwin -arch x86_64 %s -o %t -e _foo
+# RUN: lld -flavor darwin -arch x86_64 %s %p/Inputs/write-final-sections.yaml \
+# RUN: -o %t -e _foo
# RUN: llvm-readobj -sections -section-data %t | FileCheck %s
--- !native
@@ -68,12 +69,31 @@ defined-atoms:
# CHECK-NEXT: )
# For __TEXT, __eh_frame, (with typeCFI)
+ - name: LCIE
+ type: unwind-cfi
+ content: [ 14, 00, 00, 00, 00, 00, 00, 00, 01, 7A, 52, 00,
+ 01, 78, 10, 01, 10, 0C, 07, 08, 90, 01, 00, 00 ]
+
- type: unwind-cfi
- content: [ 07 ]
+ content: [ 24, 00, 00, 00, 1C, 00, 00, 00, C8, FE, FF, FF,
+ FF, FF, FF, FF, 01, 00, 00, 00, 00, 00, 00, 00,
+ 00, 41, 0E, 10, 86, 02, 43, 0D, 06, 00, 00, 00,
+ 00, 00, 00, 00 ]
+ references:
+ - kind: unwindFDEToFunction
+ offset: 8
+ target: _foo
+ - kind: negDelta32
+ offset: 4
+ target: LCIE
+
# CHECK: Name: __eh_frame
# CHECK: Segment: __TEXT
# CHECK: SectionData (
-# CHECK-NEXT: 0000: 07
+# CHECK-NEXT: 0000: 14000000 00000000 017A5200 01781001
+# CHECK-NEXT: 0010: 100C0708 90010000 24000000 1C000000
+# CHECK-NEXT: 0020: 70FFFFFF FFFFFFFF 01000000 00000000
+# CHECK-NEXT: 0030: 00410E10 8602430D 06000000 00000000
# CHECK-NEXT: )
# For __DATA, __data, (with typeData)
@@ -143,25 +163,3 @@ defined-atoms:
- type: compact-unwind
content: [ 0E, 00, 00, 00, 00, 00, 00, 00 ]
# CHECK-NOT: Name: __compact_unwind
-
-
---- !mach-o
-arch: x86_64
-file-type: MH_DYLIB
-flags: [ ]
-install-name: /usr/lib/libSystem.B.dylib
-sections:
- - segment: __TEXT
- section: __text
- type: S_REGULAR
- attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS ]
- address: 0x0000000000000000
- content: [ 0x55 ]
-
-global-symbols:
- - name: dyld_stub_binder
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
-
diff --git a/test/mach-o/wrong-arch-error.yaml b/test/mach-o/wrong-arch-error.yaml
index 6d233798a7b6..3b8ef0dc7ee6 100644
--- a/test/mach-o/wrong-arch-error.yaml
+++ b/test/mach-o/wrong-arch-error.yaml
@@ -1,4 +1,5 @@
-# RUN: not lld -flavor darwin -arch x86_64 -r %s 2> %t.err
+# RUN: not lld -flavor darwin -arch x86_64 -r %s \
+# RUN: %p/Inputs/wrong-arch-error.yaml 2> %t.err
# RUN: FileCheck %s < %t.err
--- !mach-o
@@ -21,28 +22,6 @@ global-symbols:
scope: [ N_EXT ]
sect: 1
value: 0x0000000000000000
-
---- !mach-o
-arch: x86
-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 ]
- alignment: 4
- address: 0x0000000000000000
- content: [ 0xC3 ]
-
-global-symbols:
- - name: _bar
- type: N_SECT
- scope: [ N_EXT ]
- sect: 1
- value: 0x0000000000000000
...
diff --git a/test/elf/AArch64/Inputs/fn.c b/test/old-elf/AArch64/Inputs/fn.c
index 54939a2426b2..54939a2426b2 100644
--- a/test/elf/AArch64/Inputs/fn.c
+++ b/test/old-elf/AArch64/Inputs/fn.c
diff --git a/test/elf/AArch64/Inputs/fn.o b/test/old-elf/AArch64/Inputs/fn.o
index 53e47ad37742..53e47ad37742 100644
--- a/test/elf/AArch64/Inputs/fn.o
+++ b/test/old-elf/AArch64/Inputs/fn.o
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
new file mode 100644
index 000000000000..e355a3d85cdf
--- /dev/null
+++ b/test/old-elf/AArch64/Inputs/general-dyn-tls-0.yaml
@@ -0,0 +1,64 @@
+---
+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/elf/AArch64/Inputs/initfini-option.c b/test/old-elf/AArch64/Inputs/initfini-option.c
index 6021fb57ffa9..6021fb57ffa9 100644
--- a/test/elf/AArch64/Inputs/initfini-option.c
+++ b/test/old-elf/AArch64/Inputs/initfini-option.c
diff --git a/test/elf/AArch64/Inputs/initfini-option.o b/test/old-elf/AArch64/Inputs/initfini-option.o
index c75079b013fa..c75079b013fa 100644
--- a/test/elf/AArch64/Inputs/initfini-option.o
+++ b/test/old-elf/AArch64/Inputs/initfini-option.o
Binary files differ
diff --git a/test/elf/AArch64/Inputs/initfini.c b/test/old-elf/AArch64/Inputs/initfini.c
index 8369d68a8dab..8369d68a8dab 100644
--- a/test/elf/AArch64/Inputs/initfini.c
+++ b/test/old-elf/AArch64/Inputs/initfini.c
diff --git a/test/elf/AArch64/Inputs/initfini.o b/test/old-elf/AArch64/Inputs/initfini.o
index 030fe59878be..030fe59878be 100644
--- a/test/elf/AArch64/Inputs/initfini.o
+++ b/test/old-elf/AArch64/Inputs/initfini.o
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
new file mode 100644
index 000000000000..2a6104a150ea
--- /dev/null
+++ b/test/old-elf/AArch64/Inputs/initial-exec-tls-1.yaml
@@ -0,0 +1,77 @@
+---
+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/elf/AArch64/Inputs/main.c b/test/old-elf/AArch64/Inputs/main.c
index 0280c9127076..0280c9127076 100644
--- a/test/elf/AArch64/Inputs/main.c
+++ b/test/old-elf/AArch64/Inputs/main.c
diff --git a/test/elf/AArch64/Inputs/main.o b/test/old-elf/AArch64/Inputs/main.o
index 8c0f049da6a8..8c0f049da6a8 100644
--- a/test/elf/AArch64/Inputs/main.o
+++ b/test/old-elf/AArch64/Inputs/main.o
Binary files differ
diff --git a/test/elf/AArch64/Inputs/no-interp-section.c b/test/old-elf/AArch64/Inputs/no-interp-section.c
index 3981c038ed33..3981c038ed33 100644
--- a/test/elf/AArch64/Inputs/no-interp-section.c
+++ b/test/old-elf/AArch64/Inputs/no-interp-section.c
diff --git a/test/elf/AArch64/Inputs/no-interp-section.o b/test/old-elf/AArch64/Inputs/no-interp-section.o
index 36b41fdbf782..36b41fdbf782 100644
--- a/test/elf/AArch64/Inputs/no-interp-section.o
+++ b/test/old-elf/AArch64/Inputs/no-interp-section.o
Binary files differ
diff --git a/test/elf/AArch64/Inputs/zerosizedsection.o b/test/old-elf/AArch64/Inputs/zerosizedsection.o
index 10123fcef90d..10123fcef90d 100644
--- a/test/elf/AArch64/Inputs/zerosizedsection.o
+++ b/test/old-elf/AArch64/Inputs/zerosizedsection.o
Binary files differ
diff --git a/test/elf/AArch64/Inputs/zerosizedsection.s b/test/old-elf/AArch64/Inputs/zerosizedsection.s
index 651ee3aab503..651ee3aab503 100644
--- a/test/elf/AArch64/Inputs/zerosizedsection.s
+++ b/test/old-elf/AArch64/Inputs/zerosizedsection.s
diff --git a/test/old-elf/AArch64/defsym.test b/test/old-elf/AArch64/defsym.test
new file mode 100644
index 000000000000..f9864092ddc3
--- /dev/null
+++ b/test/old-elf/AArch64/defsym.test
@@ -0,0 +1,22 @@
+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
new file mode 100644
index 000000000000..8f3b27702208
--- /dev/null
+++ b/test/old-elf/AArch64/dontignorezerosize-sections.test
@@ -0,0 +1,9 @@
+# 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
new file mode 100644
index 000000000000..80228f0cd4b2
--- /dev/null
+++ b/test/old-elf/AArch64/dynamicvars.test
@@ -0,0 +1,113 @@
+# 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
new file mode 100644
index 000000000000..c4f4edab61b1
--- /dev/null
+++ b/test/old-elf/AArch64/dynlib-nointerp-section.test
@@ -0,0 +1,5 @@
+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
new file mode 100644
index 000000000000..ae2af94d057d
--- /dev/null
+++ b/test/old-elf/AArch64/general-dyn-tls-0.test
@@ -0,0 +1,103 @@
+# 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
new file mode 100644
index 000000000000..c5f385082edc
--- /dev/null
+++ b/test/old-elf/AArch64/initfini.test
@@ -0,0 +1,23 @@
+# 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
new file mode 100644
index 000000000000..4cb5f9c7052a
--- /dev/null
+++ b/test/old-elf/AArch64/initial-exec-tls-0.test
@@ -0,0 +1,146 @@
+# 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
new file mode 100644
index 000000000000..f339ae20e154
--- /dev/null
+++ b/test/old-elf/AArch64/local-tls.test
@@ -0,0 +1,184 @@
+# 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
new file mode 100644
index 000000000000..06221c902bd7
--- /dev/null
+++ b/test/old-elf/AArch64/rel-abs16-overflow.test
@@ -0,0 +1,44 @@
+# 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
new file mode 100644
index 000000000000..e6b817570eb4
--- /dev/null
+++ b/test/old-elf/AArch64/rel-abs16.test
@@ -0,0 +1,53 @@
+# 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
new file mode 100644
index 000000000000..17154c6ddc82
--- /dev/null
+++ b/test/old-elf/AArch64/rel-abs32-overflow.test
@@ -0,0 +1,53 @@
+# 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
new file mode 100644
index 000000000000..7faa662d3462
--- /dev/null
+++ b/test/old-elf/AArch64/rel-abs32.test
@@ -0,0 +1,59 @@
+# 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
new file mode 100644
index 000000000000..0304584d121d
--- /dev/null
+++ b/test/old-elf/AArch64/rel-abs64.test
@@ -0,0 +1,59 @@
+# 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
new file mode 100644
index 000000000000..4f8e6b607bc7
--- /dev/null
+++ b/test/old-elf/AArch64/rel-adr_prel_lo21-overflow.test
@@ -0,0 +1,45 @@
+# 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
new file mode 100644
index 000000000000..36a9489c1aa4
--- /dev/null
+++ b/test/old-elf/AArch64/rel-adr_prel_lo21.test
@@ -0,0 +1,51 @@
+# 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
new file mode 100644
index 000000000000..f095f60e82a6
--- /dev/null
+++ b/test/old-elf/AArch64/rel-adr_prel_pg_hi21-overflow.test
@@ -0,0 +1,45 @@
+# 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
new file mode 100644
index 000000000000..36a20c2f6473
--- /dev/null
+++ b/test/old-elf/AArch64/rel-adr_prel_pg_hi21.test
@@ -0,0 +1,52 @@
+# 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
new file mode 100644
index 000000000000..7d2ed192de56
--- /dev/null
+++ b/test/old-elf/AArch64/rel-bad.test
@@ -0,0 +1,44 @@
+# 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
new file mode 100644
index 000000000000..ea08f9700ee4
--- /dev/null
+++ b/test/old-elf/AArch64/rel-prel16-overflow.test
@@ -0,0 +1,53 @@
+# 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
new file mode 100644
index 000000000000..11e6028e253b
--- /dev/null
+++ b/test/old-elf/AArch64/rel-prel16.test
@@ -0,0 +1,59 @@
+# 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
new file mode 100644
index 000000000000..513adad08efe
--- /dev/null
+++ b/test/old-elf/AArch64/rel-prel32-overflow.test
@@ -0,0 +1,53 @@
+# 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
new file mode 100644
index 000000000000..0e178ba97f41
--- /dev/null
+++ b/test/old-elf/AArch64/rel-prel32.test
@@ -0,0 +1,59 @@
+# 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
new file mode 100644
index 000000000000..3a3eb8b90fc3
--- /dev/null
+++ b/test/old-elf/AArch64/rel-prel64.test
@@ -0,0 +1,59 @@
+# 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/AMDGPU/hsa.test b/test/old-elf/AMDGPU/hsa.test
new file mode 100644
index 000000000000..4a17ae2223e0
--- /dev/null
+++ b/test/old-elf/AMDGPU/hsa.test
@@ -0,0 +1,53 @@
+# RUN: yaml2obj -format=elf %s > %t.obj
+# RUN: lld -flavor old-gnu -target amdgcn--hsa %t.obj -o %t.exe --noinhibit-exec
+# RUN: llvm-readobj -h -program-headers -s -symbols %t.exe | FileCheck %s
+
+# CHECK: ElfHeader {
+# CHECK: Ident {
+# CHECK: Class: 64-bit (0x2)
+# CHECK: DataEncoding: LittleEndian (0x1)
+# CHECK: Machine: EM_AMDGPU (0xE0)
+
+
+# CHECK: Section {
+# CHECK: Name: .hsatext
+# CHECK: Type: SHT_PROGBITS (0x1)
+# CHECK: Flags [ (0xC00007
+# CHECK: SHF_ALLOC (0x2)
+# CHECK: SHF_AMDGPU_HSA_AGENT (0x800000)
+# CHECK: SHF_AMDGPU_HSA_CODE (0x400000)
+# CHECK: SHF_EXECINSTR (0x4)
+# CHECK: SHF_WRITE (0x1)
+#
+# CHECK: Symbol {
+# CHECK: Name: kernel
+# CHECK: Value: 0x0
+# CHECK: Binding: Local (0x0)
+# CHECK: Type: AMDGPU_HSA_KERNEL (0xA)
+
+# CHECK: ProgramHeader {
+# CHECK: Type: PT_AMDGPU_HSA_LOAD_CODE_AGENT (0x60000003)
+
+---
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ OSABI: ELFOSABI_GNU
+ Type: ET_REL
+ Machine: EM_AMDGPU
+Sections:
+ - Name: .hsatext
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ AddressAlign: 0x0000000000000004
+ Content: ''
+ - Name: .note
+ Type: SHT_NOTE
+ AddressAlign: 0x0000000000000001
+ Content: '00'
+Symbols:
+ Local:
+ - Name: kernel
+ Type: STT_GNU_IFUNC
+ Section: .hsatext
+...
diff --git a/test/old-elf/ARM/Inputs/fn.c b/test/old-elf/ARM/Inputs/fn.c
new file mode 100644
index 000000000000..37c897ebb7f2
--- /dev/null
+++ b/test/old-elf/ARM/Inputs/fn.c
@@ -0,0 +1 @@
+int fn() { return 1; }
diff --git a/test/old-elf/ARM/Inputs/libfn.so b/test/old-elf/ARM/Inputs/libfn.so
new file mode 100755
index 000000000000..51934714841b
--- /dev/null
+++ b/test/old-elf/ARM/Inputs/libfn.so
Binary files differ
diff --git a/test/old-elf/ARM/Inputs/libobj.so b/test/old-elf/ARM/Inputs/libobj.so
new file mode 100755
index 000000000000..85b3ae4ca3d1
--- /dev/null
+++ b/test/old-elf/ARM/Inputs/libobj.so
Binary files differ
diff --git a/test/old-elf/ARM/Inputs/obj.c b/test/old-elf/ARM/Inputs/obj.c
new file mode 100644
index 000000000000..fb6a9f13f698
--- /dev/null
+++ b/test/old-elf/ARM/Inputs/obj.c
@@ -0,0 +1,4 @@
+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
new file mode 100644
index 000000000000..ddf3c80862a5
--- /dev/null
+++ b/test/old-elf/ARM/arm-symbols.test
@@ -0,0 +1,51 @@
+# 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
new file mode 100644
index 000000000000..7d4fa7fcd4dc
--- /dev/null
+++ b/test/old-elf/ARM/defsym.test
@@ -0,0 +1,50 @@
+# 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
new file mode 100644
index 000000000000..13963be8e701
--- /dev/null
+++ b/test/old-elf/ARM/dynamic-symbols.test
@@ -0,0 +1,83 @@
+# 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
new file mode 100644
index 000000000000..4cfee4aa6c7b
--- /dev/null
+++ b/test/old-elf/ARM/entry-point.test
@@ -0,0 +1,113 @@
+# 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
new file mode 100644
index 000000000000..a277cfcd09ae
--- /dev/null
+++ b/test/old-elf/ARM/exidx.test
@@ -0,0 +1,254 @@
+# .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
new file mode 100644
index 000000000000..735d65225216
--- /dev/null
+++ b/test/old-elf/ARM/header-flags.test
@@ -0,0 +1,57 @@
+# 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
new file mode 100644
index 000000000000..affa10b464f8
--- /dev/null
+++ b/test/old-elf/ARM/mapping-code-model.test
@@ -0,0 +1,160 @@
+# 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
new file mode 100644
index 000000000000..c6a4b7afc50b
--- /dev/null
+++ b/test/old-elf/ARM/mapping-symbols.test
@@ -0,0 +1,122 @@
+# 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
new file mode 100644
index 000000000000..a0d3dd51e57b
--- /dev/null
+++ b/test/old-elf/ARM/missing-symbol.test
@@ -0,0 +1,38 @@
+# 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
new file mode 100644
index 000000000000..905f628edb49
--- /dev/null
+++ b/test/old-elf/ARM/plt-dynamic.test
@@ -0,0 +1,200 @@
+# 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
new file mode 100644
index 000000000000..29d8282edf26
--- /dev/null
+++ b/test/old-elf/ARM/plt-ifunc-interwork.test
@@ -0,0 +1,396 @@
+# 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
new file mode 100644
index 000000000000..8c6d23aec084
--- /dev/null
+++ b/test/old-elf/ARM/plt-ifunc-mapping.test
@@ -0,0 +1,109 @@
+# 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
new file mode 100644
index 000000000000..7dcf632f53d3
--- /dev/null
+++ b/test/old-elf/ARM/rel-abs32.test
@@ -0,0 +1,58 @@
+# 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
new file mode 100644
index 000000000000..64b789204286
--- /dev/null
+++ b/test/old-elf/ARM/rel-arm-call.test
@@ -0,0 +1,112 @@
+# 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
new file mode 100644
index 000000000000..76e9523dbbe7
--- /dev/null
+++ b/test/old-elf/ARM/rel-arm-jump24-veneer-b.test
@@ -0,0 +1,122 @@
+# 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
new file mode 100644
index 000000000000..300355fbb11c
--- /dev/null
+++ b/test/old-elf/ARM/rel-arm-jump24-veneer-bl.test
@@ -0,0 +1,120 @@
+# 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
new file mode 100644
index 000000000000..c0d8ccc8d386
--- /dev/null
+++ b/test/old-elf/ARM/rel-arm-jump24.test
@@ -0,0 +1,108 @@
+# 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
new file mode 100644
index 000000000000..b492cc259060
--- /dev/null
+++ b/test/old-elf/ARM/rel-arm-mov.test
@@ -0,0 +1,64 @@
+# 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
new file mode 100644
index 000000000000..b07d5dd9fd75
--- /dev/null
+++ b/test/old-elf/ARM/rel-arm-prel31.test
@@ -0,0 +1,90 @@
+# 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
new file mode 100644
index 000000000000..064c68661875
--- /dev/null
+++ b/test/old-elf/ARM/rel-arm-target1.test
@@ -0,0 +1,114 @@
+# 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
new file mode 100644
index 000000000000..3e0e30a614ee
--- /dev/null
+++ b/test/old-elf/ARM/rel-arm-thm-interwork.test
@@ -0,0 +1,121 @@
+# 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
new file mode 100644
index 000000000000..054ce58ff7b8
--- /dev/null
+++ b/test/old-elf/ARM/rel-base-prel.test
@@ -0,0 +1,61 @@
+# 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
new file mode 100644
index 000000000000..f181f72a2192
--- /dev/null
+++ b/test/old-elf/ARM/rel-copy.test
@@ -0,0 +1,60 @@
+# 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
new file mode 100644
index 000000000000..34f50c5b0e3d
--- /dev/null
+++ b/test/old-elf/ARM/rel-glob-dat.test
@@ -0,0 +1,57 @@
+# 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
new file mode 100644
index 000000000000..c8786d81127f
--- /dev/null
+++ b/test/old-elf/ARM/rel-got-brel.test
@@ -0,0 +1,63 @@
+# 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
new file mode 100644
index 000000000000..16e82b3e4271
--- /dev/null
+++ b/test/old-elf/ARM/rel-group-relocs.test
@@ -0,0 +1,71 @@
+# 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
new file mode 100644
index 000000000000..7044534af1e3
--- /dev/null
+++ b/test/old-elf/ARM/rel-ifunc.test
@@ -0,0 +1,101 @@
+# 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
new file mode 100644
index 000000000000..2a4f4eba8d84
--- /dev/null
+++ b/test/old-elf/ARM/rel-jump-slot.test
@@ -0,0 +1,50 @@
+# 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
new file mode 100644
index 000000000000..9e5aab000523
--- /dev/null
+++ b/test/old-elf/ARM/rel-rel32.test
@@ -0,0 +1,56 @@
+# 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
new file mode 100644
index 000000000000..7e7289a99768
--- /dev/null
+++ b/test/old-elf/ARM/rel-thm-call.test
@@ -0,0 +1,114 @@
+# 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
new file mode 100644
index 000000000000..e074b9ae1abf
--- /dev/null
+++ b/test/old-elf/ARM/rel-thm-jump11.test
@@ -0,0 +1,209 @@
+# 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
new file mode 100644
index 000000000000..5893b53da84a
--- /dev/null
+++ b/test/old-elf/ARM/rel-thm-jump24-veneer.test
@@ -0,0 +1,120 @@
+# 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
new file mode 100644
index 000000000000..b58bc053aca0
--- /dev/null
+++ b/test/old-elf/ARM/rel-thm-jump24.test
@@ -0,0 +1,110 @@
+# 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
new file mode 100644
index 000000000000..5e2e134ce781
--- /dev/null
+++ b/test/old-elf/ARM/rel-thm-mov.test
@@ -0,0 +1,70 @@
+# 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
new file mode 100644
index 000000000000..e05b262cd1bc
--- /dev/null
+++ b/test/old-elf/ARM/rel-tls-ie32.test
@@ -0,0 +1,125 @@
+# 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
new file mode 100644
index 000000000000..eba4f950515b
--- /dev/null
+++ b/test/old-elf/ARM/rel-tls-le32.test
@@ -0,0 +1,73 @@
+# 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
new file mode 100644
index 000000000000..d2d3a7772b47
--- /dev/null
+++ b/test/old-elf/ARM/rel-v4bx.test
@@ -0,0 +1,72 @@
+# 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
new file mode 100644
index 000000000000..6377d1e3ef89
--- /dev/null
+++ b/test/old-elf/ARM/thm-symbols.test
@@ -0,0 +1,51 @@
+# 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
new file mode 100644
index 000000000000..e0420eff1918
--- /dev/null
+++ b/test/old-elf/ARM/two-got-for-symbol.test
@@ -0,0 +1,62 @@
+# 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
new file mode 100644
index 000000000000..361c6482dabe
--- /dev/null
+++ b/test/old-elf/ARM/undef-lazy-symbol.test
@@ -0,0 +1,133 @@
+# 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
new file mode 100644
index 000000000000..ccd93eea4fbd
--- /dev/null
+++ b/test/old-elf/ARM/veneer-mapping.test
@@ -0,0 +1,92 @@
+# 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
new file mode 100644
index 000000000000..76c7a4d15b65
--- /dev/null
+++ b/test/old-elf/ARM/weak-branch.test
@@ -0,0 +1,221 @@
+# 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/elf/Hexagon/Inputs/dynobj-data.c b/test/old-elf/Hexagon/Inputs/dynobj-data.c
index 0f4ea9b80526..0f4ea9b80526 100644
--- a/test/elf/Hexagon/Inputs/dynobj-data.c
+++ b/test/old-elf/Hexagon/Inputs/dynobj-data.c
diff --git a/test/elf/Hexagon/Inputs/dynobj-data.o b/test/old-elf/Hexagon/Inputs/dynobj-data.o
index 13d283cd0eff..13d283cd0eff 100644
--- a/test/elf/Hexagon/Inputs/dynobj-data.o
+++ b/test/old-elf/Hexagon/Inputs/dynobj-data.o
Binary files differ
diff --git a/test/elf/Hexagon/Inputs/dynobj.c b/test/old-elf/Hexagon/Inputs/dynobj.c
index f17fdadd6945..f17fdadd6945 100644
--- a/test/elf/Hexagon/Inputs/dynobj.c
+++ b/test/old-elf/Hexagon/Inputs/dynobj.c
diff --git a/test/elf/Hexagon/Inputs/dynobj.o b/test/old-elf/Hexagon/Inputs/dynobj.o
index 6c184f2edd60..6c184f2edd60 100644
--- a/test/elf/Hexagon/Inputs/dynobj.o
+++ b/test/old-elf/Hexagon/Inputs/dynobj.o
Binary files differ
diff --git a/test/elf/Hexagon/Inputs/got-plt-order.c b/test/old-elf/Hexagon/Inputs/got-plt-order.c
index 621f670ef7c5..621f670ef7c5 100644
--- a/test/elf/Hexagon/Inputs/got-plt-order.c
+++ b/test/old-elf/Hexagon/Inputs/got-plt-order.c
diff --git a/test/elf/Hexagon/Inputs/got-plt-order.o b/test/old-elf/Hexagon/Inputs/got-plt-order.o
index e97678b739bd..e97678b739bd 100644
--- a/test/elf/Hexagon/Inputs/got-plt-order.o
+++ b/test/old-elf/Hexagon/Inputs/got-plt-order.o
Binary files differ
diff --git a/test/elf/Hexagon/Inputs/libMaxAlignment.a b/test/old-elf/Hexagon/Inputs/libMaxAlignment.a
index cc5461a09ae4..cc5461a09ae4 100644
--- a/test/elf/Hexagon/Inputs/libMaxAlignment.a
+++ b/test/old-elf/Hexagon/Inputs/libMaxAlignment.a
Binary files differ
diff --git a/test/elf/Hexagon/Inputs/sda-base.o b/test/old-elf/Hexagon/Inputs/sda-base.o
index 410a3d47d320..410a3d47d320 100644
--- a/test/elf/Hexagon/Inputs/sda-base.o
+++ b/test/old-elf/Hexagon/Inputs/sda-base.o
Binary files differ
diff --git a/test/elf/Hexagon/Inputs/sdata1.c b/test/old-elf/Hexagon/Inputs/sdata1.c
index 77c2a54c36a1..77c2a54c36a1 100644
--- a/test/elf/Hexagon/Inputs/sdata1.c
+++ b/test/old-elf/Hexagon/Inputs/sdata1.c
diff --git a/test/elf/Hexagon/Inputs/sdata1.o b/test/old-elf/Hexagon/Inputs/sdata1.o
index bf908fed27e9..bf908fed27e9 100644
--- a/test/elf/Hexagon/Inputs/sdata1.o
+++ b/test/old-elf/Hexagon/Inputs/sdata1.o
Binary files differ
diff --git a/test/elf/Hexagon/Inputs/sdata2.c b/test/old-elf/Hexagon/Inputs/sdata2.c
index 96b37271d773..96b37271d773 100644
--- a/test/elf/Hexagon/Inputs/sdata2.c
+++ b/test/old-elf/Hexagon/Inputs/sdata2.c
diff --git a/test/elf/Hexagon/Inputs/sdata2.o b/test/old-elf/Hexagon/Inputs/sdata2.o
index e4ec810866e5..e4ec810866e5 100644
--- a/test/elf/Hexagon/Inputs/sdata2.o
+++ b/test/old-elf/Hexagon/Inputs/sdata2.o
Binary files differ
diff --git a/test/elf/Hexagon/Inputs/use-shared.hexagon b/test/old-elf/Hexagon/Inputs/use-shared.hexagon
index 9e5ffb42d36a..9e5ffb42d36a 100644
--- a/test/elf/Hexagon/Inputs/use-shared.hexagon
+++ b/test/old-elf/Hexagon/Inputs/use-shared.hexagon
Binary files differ
diff --git a/test/old-elf/Hexagon/dynlib-data.test b/test/old-elf/Hexagon/dynlib-data.test
new file mode 100644
index 000000000000..2da312b54d43
--- /dev/null
+++ b/test/old-elf/Hexagon/dynlib-data.test
@@ -0,0 +1,9 @@
+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
new file mode 100644
index 000000000000..f31d23bc5ebc
--- /dev/null
+++ b/test/old-elf/Hexagon/dynlib-gotoff.test
@@ -0,0 +1,128 @@
+# 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
new file mode 100644
index 000000000000..e26368120970
--- /dev/null
+++ b/test/old-elf/Hexagon/dynlib-hash.test
@@ -0,0 +1,9 @@
+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
new file mode 100644
index 000000000000..86e38ede6280
--- /dev/null
+++ b/test/old-elf/Hexagon/dynlib-rela.test
@@ -0,0 +1,9 @@
+# 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
new file mode 100644
index 000000000000..08f8930bb205
--- /dev/null
+++ b/test/old-elf/Hexagon/dynlib-syms.test
@@ -0,0 +1,7 @@
+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
new file mode 100644
index 000000000000..9e591ed06075
--- /dev/null
+++ b/test/old-elf/Hexagon/dynlib.test
@@ -0,0 +1,36 @@
+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
new file mode 100644
index 000000000000..e2d37d1f6440
--- /dev/null
+++ b/test/old-elf/Hexagon/hexagon-got-plt-order.test
@@ -0,0 +1,5 @@
+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
new file mode 100644
index 000000000000..51d8bd6a6b71
--- /dev/null
+++ b/test/old-elf/Hexagon/hexagon-plt-setup.test
@@ -0,0 +1,12 @@
+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
new file mode 100644
index 000000000000..15a2bf3d80be
--- /dev/null
+++ b/test/old-elf/Hexagon/maxalignment.test
@@ -0,0 +1,8 @@
+# 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
new file mode 100644
index 000000000000..777b923fd737
--- /dev/null
+++ b/test/old-elf/Hexagon/rela-order.test
@@ -0,0 +1,9 @@
+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
new file mode 100644
index 000000000000..cfcafbce8377
--- /dev/null
+++ b/test/old-elf/Hexagon/sda-base.test
@@ -0,0 +1,4 @@
+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
new file mode 100644
index 000000000000..1b932fe6e7b1
--- /dev/null
+++ b/test/old-elf/Hexagon/zerofillquick-sdata.test
@@ -0,0 +1,18 @@
+# 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/elf/Inputs/abs-test.i386 b/test/old-elf/Inputs/abs-test.i386
index 8556c24da551..8556c24da551 100644
--- a/test/elf/Inputs/abs-test.i386
+++ b/test/old-elf/Inputs/abs-test.i386
Binary files differ
diff --git a/test/old-elf/Inputs/allowduplicates.objtxt b/test/old-elf/Inputs/allowduplicates.objtxt
new file mode 100644
index 000000000000..9b8ba8902aba
--- /dev/null
+++ b/test/old-elf/Inputs/allowduplicates.objtxt
@@ -0,0 +1,12 @@
+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/elf/Inputs/bar.o.x86-64 b/test/old-elf/Inputs/bar.o.x86-64
index 467485f0bb96..467485f0bb96 100644
--- a/test/elf/Inputs/bar.o.x86-64
+++ b/test/old-elf/Inputs/bar.o.x86-64
Binary files differ
diff --git a/test/elf/Inputs/branch-test.hexagon b/test/old-elf/Inputs/branch-test.hexagon
index 1ffb47228e32..1ffb47228e32 100644
--- a/test/elf/Inputs/branch-test.hexagon
+++ b/test/old-elf/Inputs/branch-test.hexagon
Binary files differ
diff --git a/test/elf/Inputs/branch-test.ppc b/test/old-elf/Inputs/branch-test.ppc
index 4698941e7503..4698941e7503 100644
--- a/test/elf/Inputs/branch-test.ppc
+++ b/test/old-elf/Inputs/branch-test.ppc
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
new file mode 100644
index 000000000000..cbd9c665b6d5
--- /dev/null
+++ b/test/old-elf/Inputs/consecutive-weak-defs.o.yaml
@@ -0,0 +1,65 @@
+---
+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/elf/Inputs/constants-merge.x86-64 b/test/old-elf/Inputs/constants-merge.x86-64
index 0087eb8f8cb5..0087eb8f8cb5 100644
--- a/test/elf/Inputs/constants-merge.x86-64
+++ b/test/old-elf/Inputs/constants-merge.x86-64
Binary files differ
diff --git a/test/elf/Inputs/constdata.x86-64 b/test/old-elf/Inputs/constdata.x86-64
index d877a5535357..d877a5535357 100644
--- a/test/elf/Inputs/constdata.x86-64
+++ b/test/old-elf/Inputs/constdata.x86-64
Binary files differ
diff --git a/test/elf/Inputs/foo.o.x86-64 b/test/old-elf/Inputs/foo.o.x86-64
index 72a89eefa8ed..72a89eefa8ed 100644
--- a/test/elf/Inputs/foo.o.x86-64
+++ b/test/old-elf/Inputs/foo.o.x86-64
Binary files differ
diff --git a/test/elf/Inputs/globalconst.c b/test/old-elf/Inputs/globalconst.c
index 08395a88e7ca..08395a88e7ca 100644
--- a/test/elf/Inputs/globalconst.c
+++ b/test/old-elf/Inputs/globalconst.c
diff --git a/test/elf/Inputs/globalconst.o.x86-64 b/test/old-elf/Inputs/globalconst.o.x86-64
index d8e266e76334..d8e266e76334 100644
--- a/test/elf/Inputs/globalconst.o.x86-64
+++ b/test/old-elf/Inputs/globalconst.o.x86-64
Binary files differ
diff --git a/test/elf/Inputs/gotpcrel.S b/test/old-elf/Inputs/gotpcrel.S
index 300675f59612..300675f59612 100644
--- a/test/elf/Inputs/gotpcrel.S
+++ b/test/old-elf/Inputs/gotpcrel.S
diff --git a/test/elf/Inputs/gotpcrel.x86-64 b/test/old-elf/Inputs/gotpcrel.x86-64
index f9c61d0edf15..f9c61d0edf15 100644
--- a/test/elf/Inputs/gotpcrel.x86-64
+++ b/test/old-elf/Inputs/gotpcrel.x86-64
Binary files differ
diff --git a/test/elf/Inputs/group-cmd-search-1.ls b/test/old-elf/Inputs/group-cmd-search-1.ls
index 965369309a20..965369309a20 100644
--- a/test/elf/Inputs/group-cmd-search-1.ls
+++ b/test/old-elf/Inputs/group-cmd-search-1.ls
diff --git a/test/elf/Inputs/group-cmd-search-2.ls b/test/old-elf/Inputs/group-cmd-search-2.ls
index f1eee6a35efa..f1eee6a35efa 100644
--- a/test/elf/Inputs/group-cmd-search-2.ls
+++ b/test/old-elf/Inputs/group-cmd-search-2.ls
diff --git a/test/elf/Inputs/group-cmd-search-3.ls b/test/old-elf/Inputs/group-cmd-search-3.ls
index 83ce0ca62fb1..83ce0ca62fb1 100644
--- a/test/elf/Inputs/group-cmd-search-3.ls
+++ b/test/old-elf/Inputs/group-cmd-search-3.ls
diff --git a/test/elf/Inputs/ifunc.S b/test/old-elf/Inputs/ifunc.S
index 0ac1f5a5b0bb..0ac1f5a5b0bb 100644
--- a/test/elf/Inputs/ifunc.S
+++ b/test/old-elf/Inputs/ifunc.S
diff --git a/test/elf/Inputs/ifunc.cpp b/test/old-elf/Inputs/ifunc.cpp
index 2e520277d36c..2e520277d36c 100644
--- a/test/elf/Inputs/ifunc.cpp
+++ b/test/old-elf/Inputs/ifunc.cpp
diff --git a/test/elf/Inputs/ifunc.cpp.x86-64 b/test/old-elf/Inputs/ifunc.cpp.x86-64
index 20c812cabd2c..20c812cabd2c 100644
--- a/test/elf/Inputs/ifunc.cpp.x86-64
+++ b/test/old-elf/Inputs/ifunc.cpp.x86-64
Binary files differ
diff --git a/test/elf/Inputs/ifunc.x86-64 b/test/old-elf/Inputs/ifunc.x86-64
index 36c8e04ca837..36c8e04ca837 100644
--- a/test/elf/Inputs/ifunc.x86-64
+++ b/test/old-elf/Inputs/ifunc.x86-64
Binary files differ
diff --git a/test/elf/Inputs/libfnarchive.a b/test/old-elf/Inputs/libfnarchive.a
index 753acd6e2c65..753acd6e2c65 100644
--- a/test/elf/Inputs/libfnarchive.a
+++ b/test/old-elf/Inputs/libfnarchive.a
Binary files differ
diff --git a/test/elf/Inputs/libifunc.x86-64.so b/test/old-elf/Inputs/libifunc.x86-64.so
index 0f05b308ce78..0f05b308ce78 100644
--- a/test/elf/Inputs/libifunc.x86-64.so
+++ b/test/old-elf/Inputs/libifunc.x86-64.so
Binary files differ
diff --git a/test/elf/Inputs/libundef.so b/test/old-elf/Inputs/libundef.so
index 41f2a668f360..41f2a668f360 100644
--- a/test/elf/Inputs/libundef.so
+++ b/test/old-elf/Inputs/libundef.so
Binary files differ
diff --git a/test/elf/Inputs/libweaksym.so b/test/old-elf/Inputs/libweaksym.so
index 7ff4ea56ae60..7ff4ea56ae60 100755
--- a/test/elf/Inputs/libweaksym.so
+++ b/test/old-elf/Inputs/libweaksym.so
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
new file mode 100644
index 000000000000..d3eeb8fe24b6
--- /dev/null
+++ b/test/old-elf/Inputs/main-with-global-def.o.yaml
@@ -0,0 +1,55 @@
+---
+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/elf/Inputs/mainobj.x86_64 b/test/old-elf/Inputs/mainobj.x86_64
index d0f29418237d..d0f29418237d 100644
--- a/test/elf/Inputs/mainobj.x86_64
+++ b/test/old-elf/Inputs/mainobj.x86_64
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
new file mode 100644
index 000000000000..fd92f5f0c6e7
--- /dev/null
+++ b/test/old-elf/Inputs/no-unique-section-names.x86-64
Binary files differ
diff --git a/test/elf/Inputs/object-test.elf-hexagon b/test/old-elf/Inputs/object-test.elf-hexagon
index bfc85a7d0b76..bfc85a7d0b76 100644
--- a/test/elf/Inputs/object-test.elf-hexagon
+++ b/test/old-elf/Inputs/object-test.elf-hexagon
Binary files differ
diff --git a/test/elf/Inputs/object-test.elf-i386 b/test/old-elf/Inputs/object-test.elf-i386
index 872684c7fcc1..872684c7fcc1 100644
--- a/test/elf/Inputs/object-test.elf-i386
+++ b/test/old-elf/Inputs/object-test.elf-i386
Binary files differ
diff --git a/test/elf/Inputs/phdr.i386 b/test/old-elf/Inputs/phdr.i386
index 7c83dd314891..7c83dd314891 100644
--- a/test/elf/Inputs/phdr.i386
+++ b/test/old-elf/Inputs/phdr.i386
Binary files differ
diff --git a/test/elf/Inputs/quickdata-sort-test.o.elf-hexagon b/test/old-elf/Inputs/quickdata-sort-test.o.elf-hexagon
index 03d028707129..03d028707129 100644
--- a/test/elf/Inputs/quickdata-sort-test.o.elf-hexagon
+++ b/test/old-elf/Inputs/quickdata-sort-test.o.elf-hexagon
Binary files differ
diff --git a/test/elf/Inputs/quickdata-sortcommon-test.o.elf-hexagon b/test/old-elf/Inputs/quickdata-sortcommon-test.o.elf-hexagon
index 410a3d47d320..410a3d47d320 100644
--- a/test/elf/Inputs/quickdata-sortcommon-test.o.elf-hexagon
+++ b/test/old-elf/Inputs/quickdata-sortcommon-test.o.elf-hexagon
Binary files differ
diff --git a/test/elf/Inputs/quickdata-test.elf-hexagon b/test/old-elf/Inputs/quickdata-test.elf-hexagon
index c3ae53a6babe..c3ae53a6babe 100644
--- a/test/elf/Inputs/quickdata-test.elf-hexagon
+++ b/test/old-elf/Inputs/quickdata-test.elf-hexagon
Binary files differ
diff --git a/test/elf/Inputs/reloc-test.elf-i386 b/test/old-elf/Inputs/reloc-test.elf-i386
index 1a5558131fff..1a5558131fff 100644
--- a/test/elf/Inputs/reloc-test.elf-i386
+++ b/test/old-elf/Inputs/reloc-test.elf-i386
Binary files differ
diff --git a/test/elf/Inputs/reloc-xb.x86 b/test/old-elf/Inputs/reloc-xb.x86
index 4d9770aa2356..4d9770aa2356 100644
--- a/test/elf/Inputs/reloc-xb.x86
+++ b/test/old-elf/Inputs/reloc-xb.x86
Binary files differ
diff --git a/test/elf/Inputs/reloc-xt.x86 b/test/old-elf/Inputs/reloc-xt.x86
index dcdfbfb09f71..dcdfbfb09f71 100644
--- a/test/elf/Inputs/reloc-xt.x86
+++ b/test/old-elf/Inputs/reloc-xt.x86
Binary files differ
diff --git a/test/elf/Inputs/relocs-dynamic.x86-64 b/test/old-elf/Inputs/relocs-dynamic.x86-64
index 0c44924d18e6..0c44924d18e6 100644
--- a/test/elf/Inputs/relocs-dynamic.x86-64
+++ b/test/old-elf/Inputs/relocs-dynamic.x86-64
Binary files differ
diff --git a/test/elf/Inputs/relocs.x86-64 b/test/old-elf/Inputs/relocs.x86-64
index 112dfa733db9..112dfa733db9 100644
--- a/test/elf/Inputs/relocs.x86-64
+++ b/test/old-elf/Inputs/relocs.x86-64
Binary files differ
diff --git a/test/elf/Inputs/responsefile b/test/old-elf/Inputs/responsefile
index 2fe657a0e3b0..2fe657a0e3b0 100644
--- a/test/elf/Inputs/responsefile
+++ b/test/old-elf/Inputs/responsefile
diff --git a/test/elf/Inputs/rodata-test.hexagon b/test/old-elf/Inputs/rodata-test.hexagon
index f448748e2abe..f448748e2abe 100644
--- a/test/elf/Inputs/rodata-test.hexagon
+++ b/test/old-elf/Inputs/rodata-test.hexagon
Binary files differ
diff --git a/test/elf/Inputs/rodata-test.i386 b/test/old-elf/Inputs/rodata-test.i386
index 09f71eb59969..09f71eb59969 100644
--- a/test/elf/Inputs/rodata-test.i386
+++ b/test/old-elf/Inputs/rodata-test.i386
Binary files differ
diff --git a/test/elf/Inputs/rodata.c b/test/old-elf/Inputs/rodata.c
index b43c9c945898..b43c9c945898 100644
--- a/test/elf/Inputs/rodata.c
+++ b/test/old-elf/Inputs/rodata.c
diff --git a/test/elf/Inputs/rodata.o b/test/old-elf/Inputs/rodata.o
index f13ddc9bba98..f13ddc9bba98 100644
--- a/test/elf/Inputs/rodata.o
+++ b/test/old-elf/Inputs/rodata.o
Binary files differ
diff --git a/test/elf/Inputs/section-test.i386 b/test/old-elf/Inputs/section-test.i386
index 2b447a9f8f5b..2b447a9f8f5b 100644
--- a/test/elf/Inputs/section-test.i386
+++ b/test/old-elf/Inputs/section-test.i386
Binary files differ
diff --git a/test/elf/Inputs/shared.c b/test/old-elf/Inputs/shared.c
index 2be91c4b9e45..2be91c4b9e45 100644
--- a/test/elf/Inputs/shared.c
+++ b/test/old-elf/Inputs/shared.c
diff --git a/test/elf/Inputs/shared.so-x86-64 b/test/old-elf/Inputs/shared.so-x86-64
index 0240f0e67431..0240f0e67431 100644
--- a/test/elf/Inputs/shared.so-x86-64
+++ b/test/old-elf/Inputs/shared.so-x86-64
Binary files differ
diff --git a/test/old-elf/Inputs/shndx.o-x86_64 b/test/old-elf/Inputs/shndx.o-x86_64
new file mode 100644
index 000000000000..9e3e5d8526d7
--- /dev/null
+++ b/test/old-elf/Inputs/shndx.o-x86_64
Binary files differ
diff --git a/test/old-elf/Inputs/stripped-empty.x86_64 b/test/old-elf/Inputs/stripped-empty.x86_64
new file mode 100644
index 000000000000..7368ba280d79
--- /dev/null
+++ b/test/old-elf/Inputs/stripped-empty.x86_64
Binary files differ
diff --git a/test/elf/Inputs/target-test.hexagon b/test/old-elf/Inputs/target-test.hexagon
index 7da114561920..7da114561920 100644
--- a/test/elf/Inputs/target-test.hexagon
+++ b/test/old-elf/Inputs/target-test.hexagon
Binary files differ
diff --git a/test/elf/Inputs/target-test.ppc b/test/old-elf/Inputs/target-test.ppc
index 001be338c20d..001be338c20d 100644
--- a/test/elf/Inputs/target-test.ppc
+++ b/test/old-elf/Inputs/target-test.ppc
Binary files differ
diff --git a/test/old-elf/Inputs/tls-tbss-size.yaml b/test/old-elf/Inputs/tls-tbss-size.yaml
new file mode 100644
index 000000000000..0577dd157c6e
--- /dev/null
+++ b/test/old-elf/Inputs/tls-tbss-size.yaml
@@ -0,0 +1,59 @@
+---
+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/elf/Inputs/tls.S b/test/old-elf/Inputs/tls.S
index 7d9eab647b53..7d9eab647b53 100644
--- a/test/elf/Inputs/tls.S
+++ b/test/old-elf/Inputs/tls.S
diff --git a/test/elf/Inputs/tls.c b/test/old-elf/Inputs/tls.c
index 672350756562..672350756562 100644
--- a/test/elf/Inputs/tls.c
+++ b/test/old-elf/Inputs/tls.c
diff --git a/test/elf/Inputs/tls.x86-64 b/test/old-elf/Inputs/tls.x86-64
index b420ce89b19b..b420ce89b19b 100644
--- a/test/elf/Inputs/tls.x86-64
+++ b/test/old-elf/Inputs/tls.x86-64
Binary files differ
diff --git a/test/elf/Inputs/tlsAddr.x86-64 b/test/old-elf/Inputs/tlsAddr.x86-64
index 16cc9ab25abf..16cc9ab25abf 100644
--- a/test/elf/Inputs/tlsAddr.x86-64
+++ b/test/old-elf/Inputs/tlsAddr.x86-64
Binary files differ
diff --git a/test/elf/Inputs/tlsaddr.c b/test/old-elf/Inputs/tlsaddr.c
index f62d57b3bfb4..f62d57b3bfb4 100644
--- a/test/elf/Inputs/tlsaddr.c
+++ b/test/old-elf/Inputs/tlsaddr.c
diff --git a/test/elf/Inputs/undef-from-main-so.c b/test/old-elf/Inputs/undef-from-main-so.c
index f1cb63db7ada..f1cb63db7ada 100644
--- a/test/elf/Inputs/undef-from-main-so.c
+++ b/test/old-elf/Inputs/undef-from-main-so.c
diff --git a/test/elf/Inputs/undef-from-main.c b/test/old-elf/Inputs/undef-from-main.c
index 366d934dd84f..366d934dd84f 100644
--- a/test/elf/Inputs/undef-from-main.c
+++ b/test/old-elf/Inputs/undef-from-main.c
diff --git a/test/elf/Inputs/undef-pc32.o b/test/old-elf/Inputs/undef-pc32.o
index 954916d59991..954916d59991 100644
--- a/test/elf/Inputs/undef-pc32.o
+++ b/test/old-elf/Inputs/undef-pc32.o
Binary files differ
diff --git a/test/elf/Inputs/undef.o b/test/old-elf/Inputs/undef.o
index 3c9b60c6ca33..3c9b60c6ca33 100644
--- a/test/elf/Inputs/undef.o
+++ b/test/old-elf/Inputs/undef.o
Binary files differ
diff --git a/test/old-elf/Inputs/undef2-so.o.yaml b/test/old-elf/Inputs/undef2-so.o.yaml
new file mode 100644
index 000000000000..f640cea39a5d
--- /dev/null
+++ b/test/old-elf/Inputs/undef2-so.o.yaml
@@ -0,0 +1,49 @@
+---
+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/elf/Inputs/use-shared-32s.c b/test/old-elf/Inputs/use-shared-32s.c
index 63054cb036ea..63054cb036ea 100644
--- a/test/elf/Inputs/use-shared-32s.c
+++ b/test/old-elf/Inputs/use-shared-32s.c
diff --git a/test/elf/Inputs/use-shared-32s.x86-64 b/test/old-elf/Inputs/use-shared-32s.x86-64
index 7e223677b93f..7e223677b93f 100644
--- a/test/elf/Inputs/use-shared-32s.x86-64
+++ b/test/old-elf/Inputs/use-shared-32s.x86-64
Binary files differ
diff --git a/test/elf/Inputs/use-shared.c b/test/old-elf/Inputs/use-shared.c
index b370eaa4fac2..b370eaa4fac2 100644
--- a/test/elf/Inputs/use-shared.c
+++ b/test/old-elf/Inputs/use-shared.c
diff --git a/test/elf/Inputs/use-shared.x86-64 b/test/old-elf/Inputs/use-shared.x86-64
index 25e1eb87a2b4..25e1eb87a2b4 100644
--- a/test/elf/Inputs/use-shared.x86-64
+++ b/test/old-elf/Inputs/use-shared.x86-64
Binary files differ
diff --git a/test/elf/Inputs/weaksym.o b/test/old-elf/Inputs/weaksym.o
index 010ce704a313..010ce704a313 100644
--- a/test/elf/Inputs/weaksym.o
+++ b/test/old-elf/Inputs/weaksym.o
Binary files differ
diff --git a/test/elf/Inputs/writersyms.o b/test/old-elf/Inputs/writersyms.o
index 7cd472d99d77..7cd472d99d77 100644
--- a/test/elf/Inputs/writersyms.o
+++ b/test/old-elf/Inputs/writersyms.o
Binary files differ
diff --git a/test/elf/Inputs/x86-64-relocs.S b/test/old-elf/Inputs/x86-64-relocs.S
index 2547c0f19bb0..2547c0f19bb0 100644
--- a/test/elf/Inputs/x86-64-relocs.S
+++ b/test/old-elf/Inputs/x86-64-relocs.S
diff --git a/test/old-elf/Mips/abi-flags-01.test b/test/old-elf/Mips/abi-flags-01.test
new file mode 100644
index 000000000000..d2eb13f3186a
--- /dev/null
+++ b/test/old-elf/Mips/abi-flags-01.test
@@ -0,0 +1,35 @@
+# 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
new file mode 100644
index 000000000000..f3c1f29abc55
--- /dev/null
+++ b/test/old-elf/Mips/abi-flags-02.test
@@ -0,0 +1,92 @@
+# 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
new file mode 100644
index 000000000000..a28bb2826730
--- /dev/null
+++ b/test/old-elf/Mips/abi-flags-03.test
@@ -0,0 +1,149 @@
+# 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
new file mode 100644
index 000000000000..6cde797dd3a0
--- /dev/null
+++ b/test/old-elf/Mips/abi-flags-04.test
@@ -0,0 +1,125 @@
+# 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
new file mode 100644
index 000000000000..6a009db7344a
--- /dev/null
+++ b/test/old-elf/Mips/abi-flags-05.test
@@ -0,0 +1,186 @@
+# 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
new file mode 100644
index 000000000000..d7df379039bb
--- /dev/null
+++ b/test/old-elf/Mips/abi-flags-06.test
@@ -0,0 +1,79 @@
+# 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
new file mode 100644
index 000000000000..6cae9b2feb4d
--- /dev/null
+++ b/test/old-elf/Mips/abi-flags-07.test
@@ -0,0 +1,60 @@
+# 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
new file mode 100644
index 000000000000..c4b75bcf4516
--- /dev/null
+++ b/test/old-elf/Mips/abi-flags-08.test
@@ -0,0 +1,71 @@
+# 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
new file mode 100644
index 000000000000..1ab03abe3810
--- /dev/null
+++ b/test/old-elf/Mips/abi-flags-09.test
@@ -0,0 +1,67 @@
+# 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
new file mode 100644
index 000000000000..50732d5c1151
--- /dev/null
+++ b/test/old-elf/Mips/abi-flags-10.test
@@ -0,0 +1,60 @@
+# 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
new file mode 100644
index 000000000000..e0e8547abbc7
--- /dev/null
+++ b/test/old-elf/Mips/abi-flags-11.test
@@ -0,0 +1,59 @@
+# 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
new file mode 100644
index 000000000000..6b553d227820
--- /dev/null
+++ b/test/old-elf/Mips/base-address-64.test
@@ -0,0 +1,80 @@
+# 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
new file mode 100644
index 000000000000..67c04326cc15
--- /dev/null
+++ b/test/old-elf/Mips/base-address.test
@@ -0,0 +1,95 @@
+# 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
new file mode 100644
index 000000000000..b33ed43292e7
--- /dev/null
+++ b/test/old-elf/Mips/ctors-order.test
@@ -0,0 +1,164 @@
+# 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
new file mode 100644
index 000000000000..0ab636c427c9
--- /dev/null
+++ b/test/old-elf/Mips/driver-hash-style.test
@@ -0,0 +1,15 @@
+# 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
new file mode 100644
index 000000000000..152e82372799
--- /dev/null
+++ b/test/old-elf/Mips/dt-textrel-64.test
@@ -0,0 +1,74 @@
+# 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
new file mode 100644
index 000000000000..af86f4926273
--- /dev/null
+++ b/test/old-elf/Mips/dt-textrel.test
@@ -0,0 +1,74 @@
+# 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
new file mode 100644
index 000000000000..aeab7645ed51
--- /dev/null
+++ b/test/old-elf/Mips/dynamic-linking.test
@@ -0,0 +1,22 @@
+# 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
new file mode 100644
index 000000000000..43a69d82c3a3
--- /dev/null
+++ b/test/old-elf/Mips/dynamic-sym.test
@@ -0,0 +1,41 @@
+# 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
new file mode 100644
index 000000000000..fca036a52624
--- /dev/null
+++ b/test/old-elf/Mips/dynlib-dynamic.test
@@ -0,0 +1,110 @@
+# 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
new file mode 100644
index 000000000000..6757847fac73
--- /dev/null
+++ b/test/old-elf/Mips/dynlib-dynsym-micro.test
@@ -0,0 +1,208 @@
+# 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
new file mode 100644
index 000000000000..23b0cd6a90c2
--- /dev/null
+++ b/test/old-elf/Mips/dynlib-dynsym.test
@@ -0,0 +1,202 @@
+# 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
new file mode 100644
index 000000000000..f3b45d4d738e
--- /dev/null
+++ b/test/old-elf/Mips/dynlib-fileheader-64.test
@@ -0,0 +1,72 @@
+# 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
new file mode 100644
index 000000000000..531cee134caf
--- /dev/null
+++ b/test/old-elf/Mips/dynlib-fileheader-micro-64.test
@@ -0,0 +1,75 @@
+# 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
new file mode 100644
index 000000000000..dcd38f1036d0
--- /dev/null
+++ b/test/old-elf/Mips/dynlib-fileheader-micro.test
@@ -0,0 +1,79 @@
+# 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
new file mode 100644
index 000000000000..a3b4a19a90f1
--- /dev/null
+++ b/test/old-elf/Mips/dynlib-fileheader.test
@@ -0,0 +1,76 @@
+# 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
new file mode 100644
index 000000000000..8821ae358254
--- /dev/null
+++ b/test/old-elf/Mips/dynsym-table-1.test
@@ -0,0 +1,127 @@
+# 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
new file mode 100644
index 000000000000..ad85bfe84e43
--- /dev/null
+++ b/test/old-elf/Mips/dynsym-table-2.test
@@ -0,0 +1,105 @@
+# 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
new file mode 100644
index 000000000000..3e52afd223cd
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-1-64.test
@@ -0,0 +1,30 @@
+# 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
new file mode 100644
index 000000000000..bc100534112d
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-1.test
@@ -0,0 +1,56 @@
+# 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
new file mode 100644
index 000000000000..5dacaa0e069d
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-10.test
@@ -0,0 +1,43 @@
+# 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
new file mode 100644
index 000000000000..e61eb0d6d65a
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-11.test
@@ -0,0 +1,43 @@
+# 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
new file mode 100644
index 000000000000..0a0c43fc996a
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-12.test
@@ -0,0 +1,44 @@
+# 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
new file mode 100644
index 000000000000..4e024d2a465b
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-2-64.test
@@ -0,0 +1,33 @@
+# 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
new file mode 100644
index 000000000000..3ca531728728
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-2.test
@@ -0,0 +1,35 @@
+# 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
new file mode 100644
index 000000000000..45326813e12f
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-3-64.test
@@ -0,0 +1,130 @@
+# 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
new file mode 100644
index 000000000000..612f0b458631
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-3.test
@@ -0,0 +1,134 @@
+# 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
new file mode 100644
index 000000000000..59a8bf131d95
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-4-64.test
@@ -0,0 +1,64 @@
+# 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
new file mode 100644
index 000000000000..6a2de375e624
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-4.test
@@ -0,0 +1,65 @@
+# 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
new file mode 100644
index 000000000000..f1fdac2c8c05
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-5-64.test
@@ -0,0 +1,42 @@
+# 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
new file mode 100644
index 000000000000..56edc4bfa10f
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-5.test
@@ -0,0 +1,42 @@
+# 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
new file mode 100644
index 000000000000..9f83365441af
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-6-64.test
@@ -0,0 +1,79 @@
+# 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
new file mode 100644
index 000000000000..0d8bcee5ad64
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-6.test
@@ -0,0 +1,80 @@
+# 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
new file mode 100644
index 000000000000..0e74ac53684a
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-7-64.test
@@ -0,0 +1,42 @@
+# 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
new file mode 100644
index 000000000000..08051df506be
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-7.test
@@ -0,0 +1,42 @@
+# 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
new file mode 100644
index 000000000000..2a2fdfee3c46
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-8.test
@@ -0,0 +1,65 @@
+# 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
new file mode 100644
index 000000000000..ada24d788c9a
--- /dev/null
+++ b/test/old-elf/Mips/e-flags-merge-9.test
@@ -0,0 +1,43 @@
+# 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
new file mode 100644
index 000000000000..f6ce0c4f223b
--- /dev/null
+++ b/test/old-elf/Mips/entry-name.test
@@ -0,0 +1,26 @@
+# 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
new file mode 100644
index 000000000000..93fdce9fdc7d
--- /dev/null
+++ b/test/old-elf/Mips/exe-dynamic.test
@@ -0,0 +1,110 @@
+# 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
new file mode 100644
index 000000000000..477e174f3d6c
--- /dev/null
+++ b/test/old-elf/Mips/exe-dynsym-micro.test
@@ -0,0 +1,94 @@
+# 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
new file mode 100644
index 000000000000..c50ce67d5f57
--- /dev/null
+++ b/test/old-elf/Mips/exe-dynsym.test
@@ -0,0 +1,91 @@
+# 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
new file mode 100644
index 000000000000..b3cd88c139b6
--- /dev/null
+++ b/test/old-elf/Mips/exe-fileheader-02.test
@@ -0,0 +1,62 @@
+# 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
new file mode 100644
index 000000000000..dfe4fcc43e67
--- /dev/null
+++ b/test/old-elf/Mips/exe-fileheader-03.test
@@ -0,0 +1,72 @@
+# 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
new file mode 100644
index 000000000000..20bb43a216d5
--- /dev/null
+++ b/test/old-elf/Mips/exe-fileheader-64.test
@@ -0,0 +1,66 @@
+# 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
new file mode 100644
index 000000000000..70457fe217c6
--- /dev/null
+++ b/test/old-elf/Mips/exe-fileheader-be-64.test
@@ -0,0 +1,60 @@
+# 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
new file mode 100644
index 000000000000..292a92e59097
--- /dev/null
+++ b/test/old-elf/Mips/exe-fileheader-be.test
@@ -0,0 +1,60 @@
+# 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
new file mode 100644
index 000000000000..a37d2d710637
--- /dev/null
+++ b/test/old-elf/Mips/exe-fileheader-micro-64.test
@@ -0,0 +1,68 @@
+# 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
new file mode 100644
index 000000000000..0adaf5b17373
--- /dev/null
+++ b/test/old-elf/Mips/exe-fileheader-micro.test
@@ -0,0 +1,69 @@
+# 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
new file mode 100644
index 000000000000..f6a1725b4443
--- /dev/null
+++ b/test/old-elf/Mips/exe-fileheader-n32.test
@@ -0,0 +1,65 @@
+# 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
new file mode 100644
index 000000000000..0188a682b3fb
--- /dev/null
+++ b/test/old-elf/Mips/exe-fileheader.test
@@ -0,0 +1,105 @@
+# 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
new file mode 100644
index 000000000000..7b3a919880de
--- /dev/null
+++ b/test/old-elf/Mips/exe-got-micro.test
@@ -0,0 +1,115 @@
+# 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
new file mode 100644
index 000000000000..636de16b4202
--- /dev/null
+++ b/test/old-elf/Mips/exe-got.test
@@ -0,0 +1,116 @@
+# 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
new file mode 100644
index 000000000000..5457ab9f1879
--- /dev/null
+++ b/test/old-elf/Mips/got-page-32-micro.test
@@ -0,0 +1,251 @@
+# 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
new file mode 100644
index 000000000000..44f45536d501
--- /dev/null
+++ b/test/old-elf/Mips/got-page-32.test
@@ -0,0 +1,244 @@
+# 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
new file mode 100644
index 000000000000..37bae77001e4
--- /dev/null
+++ b/test/old-elf/Mips/got-page-64-micro.test
@@ -0,0 +1,210 @@
+# 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
new file mode 100644
index 000000000000..3c6ef57c78f5
--- /dev/null
+++ b/test/old-elf/Mips/got-page-64.test
@@ -0,0 +1,203 @@
+# 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
new file mode 100644
index 000000000000..01f11a5920cd
--- /dev/null
+++ b/test/old-elf/Mips/got16-2.test
@@ -0,0 +1,73 @@
+# 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
new file mode 100644
index 000000000000..25de08e95c4e
--- /dev/null
+++ b/test/old-elf/Mips/got16-micro.test
@@ -0,0 +1,165 @@
+# 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
new file mode 100644
index 000000000000..4dde15a11c26
--- /dev/null
+++ b/test/old-elf/Mips/got16.test
@@ -0,0 +1,196 @@
+# 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
new file mode 100644
index 000000000000..bc89ba5d3768
--- /dev/null
+++ b/test/old-elf/Mips/gotsym.test
@@ -0,0 +1,43 @@
+# 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
new file mode 100644
index 000000000000..0e1bea9c38da
--- /dev/null
+++ b/test/old-elf/Mips/gp-sym-1-micro.test
@@ -0,0 +1,88 @@
+# 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
new file mode 100644
index 000000000000..ebb73c3afd60
--- /dev/null
+++ b/test/old-elf/Mips/gp-sym-1.test
@@ -0,0 +1,86 @@
+# 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
new file mode 100644
index 000000000000..b6d95f350af3
--- /dev/null
+++ b/test/old-elf/Mips/gp-sym-2.test
@@ -0,0 +1,103 @@
+# 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
new file mode 100644
index 000000000000..b284140f748f
--- /dev/null
+++ b/test/old-elf/Mips/hilo16-1.test
@@ -0,0 +1,40 @@
+# 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
new file mode 100644
index 000000000000..e47b9003a8dd
--- /dev/null
+++ b/test/old-elf/Mips/hilo16-2.test
@@ -0,0 +1,70 @@
+# 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
new file mode 100644
index 000000000000..94fc90b3be54
--- /dev/null
+++ b/test/old-elf/Mips/hilo16-3-overflow.test
@@ -0,0 +1,44 @@
+# 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
new file mode 100644
index 000000000000..17873c0a629c
--- /dev/null
+++ b/test/old-elf/Mips/hilo16-3.test
@@ -0,0 +1,74 @@
+# 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
new file mode 100644
index 000000000000..2db17344e30f
--- /dev/null
+++ b/test/old-elf/Mips/hilo16-4.test
@@ -0,0 +1,93 @@
+# 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
new file mode 100644
index 000000000000..597425e8ba74
--- /dev/null
+++ b/test/old-elf/Mips/hilo16-5.test
@@ -0,0 +1,103 @@
+# 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
new file mode 100644
index 000000000000..ef8ac782341c
--- /dev/null
+++ b/test/old-elf/Mips/hilo16-8-micro.test
@@ -0,0 +1,81 @@
+# 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
new file mode 100644
index 000000000000..293e35f36cd5
--- /dev/null
+++ b/test/old-elf/Mips/hilo16-9-micro.test
@@ -0,0 +1,142 @@
+# 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
new file mode 100644
index 000000000000..ca2708f1bb29
--- /dev/null
+++ b/test/old-elf/Mips/initfini-micro.test
@@ -0,0 +1,45 @@
+# 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
new file mode 100644
index 000000000000..7cfd0c51a3c4
--- /dev/null
+++ b/test/old-elf/Mips/interpreter-64.test
@@ -0,0 +1,26 @@
+# 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
new file mode 100644
index 000000000000..7d17256ba43c
--- /dev/null
+++ b/test/old-elf/Mips/interpreter-n32.test
@@ -0,0 +1,27 @@
+# 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
new file mode 100644
index 000000000000..4ae17b42df1c
--- /dev/null
+++ b/test/old-elf/Mips/interpreter.test
@@ -0,0 +1,26 @@
+# 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
new file mode 100644
index 000000000000..2856ecc92607
--- /dev/null
+++ b/test/old-elf/Mips/invalid-reginfo.test
@@ -0,0 +1,28 @@
+# 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
new file mode 100644
index 000000000000..8fc5310bbad8
--- /dev/null
+++ b/test/old-elf/Mips/jalx-align-err.test
@@ -0,0 +1,46 @@
+# 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
new file mode 100644
index 000000000000..d02e9d7c2bac
--- /dev/null
+++ b/test/old-elf/Mips/jalx-jalr.test
@@ -0,0 +1,47 @@
+# 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
new file mode 100644
index 000000000000..60d6ea71193c
--- /dev/null
+++ b/test/old-elf/Mips/jalx.test
@@ -0,0 +1,71 @@
+# 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
new file mode 100644
index 000000000000..0e5a5298a731
--- /dev/null
+++ b/test/old-elf/Mips/jump-fix-err.test
@@ -0,0 +1,45 @@
+# 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
new file mode 100644
index 000000000000..9527e7a80644
--- /dev/null
+++ b/test/old-elf/Mips/la25-stub-be.test
@@ -0,0 +1,113 @@
+# 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
new file mode 100644
index 000000000000..0bea3e6ac8b0
--- /dev/null
+++ b/test/old-elf/Mips/la25-stub-micro-be.test
@@ -0,0 +1,121 @@
+# 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
new file mode 100644
index 000000000000..c01da5908829
--- /dev/null
+++ b/test/old-elf/Mips/la25-stub-micro.test
@@ -0,0 +1,136 @@
+# 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
new file mode 100644
index 000000000000..9ff6af06cb2b
--- /dev/null
+++ b/test/old-elf/Mips/la25-stub-npic-01.test
@@ -0,0 +1,153 @@
+# 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
new file mode 100644
index 000000000000..4f2eb14d8c92
--- /dev/null
+++ b/test/old-elf/Mips/la25-stub-npic-02.test
@@ -0,0 +1,123 @@
+# 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
new file mode 100644
index 000000000000..72bac30f86ad
--- /dev/null
+++ b/test/old-elf/Mips/la25-stub-npic-shared.test
@@ -0,0 +1,152 @@
+# 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
new file mode 100644
index 000000000000..8db88404aaef
--- /dev/null
+++ b/test/old-elf/Mips/la25-stub-pic.test
@@ -0,0 +1,144 @@
+# 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
new file mode 100644
index 000000000000..4df7f85e8c89
--- /dev/null
+++ b/test/old-elf/Mips/la25-stub.test
@@ -0,0 +1,133 @@
+# 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
new file mode 100644
index 000000000000..8f2e63ca3b5f
--- /dev/null
+++ b/test/old-elf/Mips/mips-options-01.test
@@ -0,0 +1,34 @@
+# 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
new file mode 100644
index 000000000000..a5f19e55735f
--- /dev/null
+++ b/test/old-elf/Mips/mips-options-02.test
@@ -0,0 +1,104 @@
+# 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
new file mode 100644
index 000000000000..a0dea5709b6f
--- /dev/null
+++ b/test/old-elf/Mips/mips-options-03.test
@@ -0,0 +1,41 @@
+# 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
new file mode 100644
index 000000000000..5df94aae9257
--- /dev/null
+++ b/test/old-elf/Mips/mips-options-04.test
@@ -0,0 +1,77 @@
+# 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
new file mode 100644
index 000000000000..f7e9728b3cf4
--- /dev/null
+++ b/test/old-elf/Mips/mips-options-05.test
@@ -0,0 +1,119 @@
+# 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
new file mode 100644
index 000000000000..73e578347f2c
--- /dev/null
+++ b/test/old-elf/Mips/mips-options-gp0.test
@@ -0,0 +1,77 @@
+# 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
new file mode 100644
index 000000000000..9569eb7c5855
--- /dev/null
+++ b/test/old-elf/Mips/n32-rela-chain.test
@@ -0,0 +1,68 @@
+# 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
new file mode 100644
index 000000000000..3797c4321701
--- /dev/null
+++ b/test/old-elf/Mips/n64-rel-chain.test
@@ -0,0 +1,204 @@
+# 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
new file mode 100644
index 000000000000..31a780beb998
--- /dev/null
+++ b/test/old-elf/Mips/n64-rel-shift.test
@@ -0,0 +1,48 @@
+# 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
new file mode 100644
index 000000000000..a48b49bfaa02
--- /dev/null
+++ b/test/old-elf/Mips/opt-emulation.test
@@ -0,0 +1,43 @@
+# 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
new file mode 100644
index 000000000000..89e9ab7bb73f
--- /dev/null
+++ b/test/old-elf/Mips/pc23-range.test
@@ -0,0 +1,54 @@
+# 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
new file mode 100644
index 000000000000..e05eec4c8109
--- /dev/null
+++ b/test/old-elf/Mips/plt-entry-mixed-1.test
@@ -0,0 +1,114 @@
+# 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
new file mode 100644
index 000000000000..299aa5ce065c
--- /dev/null
+++ b/test/old-elf/Mips/plt-entry-mixed-2.test
@@ -0,0 +1,93 @@
+# 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
new file mode 100644
index 000000000000..c946ecc82d2f
--- /dev/null
+++ b/test/old-elf/Mips/plt-entry-mixed-3.test
@@ -0,0 +1,98 @@
+# 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
new file mode 100644
index 000000000000..ba8b04866b98
--- /dev/null
+++ b/test/old-elf/Mips/plt-entry-mixed-4.test
@@ -0,0 +1,85 @@
+# 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
new file mode 100644
index 000000000000..3e15ece894e0
--- /dev/null
+++ b/test/old-elf/Mips/plt-entry-r6-be.test
@@ -0,0 +1,109 @@
+# 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
new file mode 100644
index 000000000000..0d8bbf494afe
--- /dev/null
+++ b/test/old-elf/Mips/plt-entry-r6.test
@@ -0,0 +1,109 @@
+# 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
new file mode 100644
index 000000000000..e453e44f76d6
--- /dev/null
+++ b/test/old-elf/Mips/plt-header-be.test
@@ -0,0 +1,104 @@
+# 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
new file mode 100644
index 000000000000..e9aa51ef85eb
--- /dev/null
+++ b/test/old-elf/Mips/plt-header-micro-be.test
@@ -0,0 +1,105 @@
+# 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
new file mode 100644
index 000000000000..743c4c332184
--- /dev/null
+++ b/test/old-elf/Mips/plt-header-micro.test
@@ -0,0 +1,108 @@
+# 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
new file mode 100644
index 000000000000..456f5a91c98b
--- /dev/null
+++ b/test/old-elf/Mips/plt-header-mixed.test
@@ -0,0 +1,105 @@
+# 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
new file mode 100644
index 000000000000..6d303254d16d
--- /dev/null
+++ b/test/old-elf/Mips/plt-header.test
@@ -0,0 +1,99 @@
+# 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
new file mode 100644
index 000000000000..c59b5aa61a53
--- /dev/null
+++ b/test/old-elf/Mips/r26-1-micro.test
@@ -0,0 +1,131 @@
+# 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
new file mode 100644
index 000000000000..41c58deceedb
--- /dev/null
+++ b/test/old-elf/Mips/r26-1.test
@@ -0,0 +1,132 @@
+# 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
new file mode 100644
index 000000000000..7d4f86e57f70
--- /dev/null
+++ b/test/old-elf/Mips/r26-2-micro.test
@@ -0,0 +1,31 @@
+# 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
new file mode 100644
index 000000000000..b9db959d3ea7
--- /dev/null
+++ b/test/old-elf/Mips/r26-2.test
@@ -0,0 +1,31 @@
+# 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
new file mode 100644
index 000000000000..ee7cd6a5fcee
--- /dev/null
+++ b/test/old-elf/Mips/reginfo-01.test
@@ -0,0 +1,30 @@
+# 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
new file mode 100644
index 000000000000..41eac01a11b1
--- /dev/null
+++ b/test/old-elf/Mips/reginfo-02.test
@@ -0,0 +1,107 @@
+# 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
new file mode 100644
index 000000000000..edee1440d358
--- /dev/null
+++ b/test/old-elf/Mips/reginfo-03.test
@@ -0,0 +1,45 @@
+# 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
new file mode 100644
index 000000000000..bad34e5003f7
--- /dev/null
+++ b/test/old-elf/Mips/reginfo-04.test
@@ -0,0 +1,81 @@
+# 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
new file mode 100644
index 000000000000..9de9fa62149a
--- /dev/null
+++ b/test/old-elf/Mips/reginfo-05.test
@@ -0,0 +1,123 @@
+# 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
new file mode 100644
index 000000000000..e2a73f693361
--- /dev/null
+++ b/test/old-elf/Mips/rel-16-overflow.test
@@ -0,0 +1,45 @@
+# 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
new file mode 100644
index 000000000000..24961e8b78ff
--- /dev/null
+++ b/test/old-elf/Mips/rel-16.test
@@ -0,0 +1,51 @@
+# 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
new file mode 100644
index 000000000000..3eac8a2848f0
--- /dev/null
+++ b/test/old-elf/Mips/rel-32-be.test
@@ -0,0 +1,60 @@
+# 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
new file mode 100644
index 000000000000..f028d79c8688
--- /dev/null
+++ b/test/old-elf/Mips/rel-32.test
@@ -0,0 +1,59 @@
+# 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
new file mode 100644
index 000000000000..c97ff991c0c4
--- /dev/null
+++ b/test/old-elf/Mips/rel-64.test
@@ -0,0 +1,61 @@
+# 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
new file mode 100644
index 000000000000..88f2e337d928
--- /dev/null
+++ b/test/old-elf/Mips/rel-call-hilo-01.test
@@ -0,0 +1,109 @@
+# 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
new file mode 100644
index 000000000000..0df68def92b3
--- /dev/null
+++ b/test/old-elf/Mips/rel-call-hilo-micro.test
@@ -0,0 +1,154 @@
+# 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
new file mode 100644
index 000000000000..ba47c84a2c5c
--- /dev/null
+++ b/test/old-elf/Mips/rel-copy-micro.test
@@ -0,0 +1,159 @@
+# 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
new file mode 100644
index 000000000000..cf723f53719c
--- /dev/null
+++ b/test/old-elf/Mips/rel-copy-pc.test
@@ -0,0 +1,113 @@
+# 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
new file mode 100644
index 000000000000..751034dcd728
--- /dev/null
+++ b/test/old-elf/Mips/rel-copy.test
@@ -0,0 +1,177 @@
+# 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
new file mode 100644
index 000000000000..56dd7dfdeccd
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-01-micro.test
@@ -0,0 +1,201 @@
+# 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
new file mode 100644
index 000000000000..e24449eeeb58
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-01.test
@@ -0,0 +1,261 @@
+# 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
new file mode 100644
index 000000000000..24b7c624c6a0
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-02.test
@@ -0,0 +1,101 @@
+# 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
new file mode 100644
index 000000000000..891649d8cdbc
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-03-micro.test
@@ -0,0 +1,133 @@
+# 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
new file mode 100644
index 000000000000..2552473ca80f
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-03.test
@@ -0,0 +1,129 @@
+# 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
new file mode 100644
index 000000000000..de1131c67f43
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-04-micro.test
@@ -0,0 +1,226 @@
+# 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
new file mode 100644
index 000000000000..df8c676af330
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-04.test
@@ -0,0 +1,221 @@
+# 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
new file mode 100644
index 000000000000..16c6a9c6aad5
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-05-micro.test
@@ -0,0 +1,192 @@
+# 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
new file mode 100644
index 000000000000..8348bc511fbd
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-05.test
@@ -0,0 +1,188 @@
+# 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
new file mode 100644
index 000000000000..6b0d28993f94
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-06-64.test
@@ -0,0 +1,114 @@
+# 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
new file mode 100644
index 000000000000..ead7dfb08ddf
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-06.test
@@ -0,0 +1,115 @@
+# 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
new file mode 100644
index 000000000000..823a66d521e2
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-07-64.test
@@ -0,0 +1,348 @@
+# 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
new file mode 100644
index 000000000000..41c31c66a5f3
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-07.test
@@ -0,0 +1,363 @@
+# 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
new file mode 100644
index 000000000000..019b8e5161a8
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-08-64.test
@@ -0,0 +1,275 @@
+# 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
new file mode 100644
index 000000000000..2d25b504ee28
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-08-micro.test
@@ -0,0 +1,278 @@
+# 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
new file mode 100644
index 000000000000..a89e6ecf480e
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-08.test
@@ -0,0 +1,275 @@
+# 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
new file mode 100644
index 000000000000..2011ae079645
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-09-micro.test
@@ -0,0 +1,109 @@
+# 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
new file mode 100644
index 000000000000..9b02ec1b5707
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-09.test
@@ -0,0 +1,107 @@
+# 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
new file mode 100644
index 000000000000..4600af85c27c
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-10-micro.test
@@ -0,0 +1,166 @@
+# 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
new file mode 100644
index 000000000000..68a311df73e4
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-10.test
@@ -0,0 +1,160 @@
+# 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
new file mode 100644
index 000000000000..01edbd64812f
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-11.test
@@ -0,0 +1,110 @@
+# 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
new file mode 100644
index 000000000000..c684df3f2628
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-12.test
@@ -0,0 +1,237 @@
+# 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
new file mode 100644
index 000000000000..2bf014e51025
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-13.test
@@ -0,0 +1,94 @@
+# 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
new file mode 100644
index 000000000000..33197ae92b81
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-14.test
@@ -0,0 +1,94 @@
+# 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
new file mode 100644
index 000000000000..13e2083bfc02
--- /dev/null
+++ b/test/old-elf/Mips/rel-dynamic-15.test
@@ -0,0 +1,81 @@
+# 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
new file mode 100644
index 000000000000..08e5d78683a8
--- /dev/null
+++ b/test/old-elf/Mips/rel-eh-01.test
@@ -0,0 +1,186 @@
+# 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
new file mode 100644
index 000000000000..e78c967ed301
--- /dev/null
+++ b/test/old-elf/Mips/rel-eh-02.test
@@ -0,0 +1,130 @@
+# 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
new file mode 100644
index 000000000000..63ed74cd56f8
--- /dev/null
+++ b/test/old-elf/Mips/rel-eh-03.test
@@ -0,0 +1,128 @@
+# 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
new file mode 100644
index 000000000000..c73d8765cbd5
--- /dev/null
+++ b/test/old-elf/Mips/rel-got-hilo-01.test
@@ -0,0 +1,109 @@
+# 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
new file mode 100644
index 000000000000..39dd1848f92e
--- /dev/null
+++ b/test/old-elf/Mips/rel-got-hilo-micro.test
@@ -0,0 +1,154 @@
+# 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
new file mode 100644
index 000000000000..7b023aecba41
--- /dev/null
+++ b/test/old-elf/Mips/rel-gprel16-micro-overflow.test
@@ -0,0 +1,57 @@
+# 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
new file mode 100644
index 000000000000..c0119a51e484
--- /dev/null
+++ b/test/old-elf/Mips/rel-gprel16-micro.test
@@ -0,0 +1,78 @@
+# 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
new file mode 100644
index 000000000000..2943b5d200f4
--- /dev/null
+++ b/test/old-elf/Mips/rel-gprel16-overflow.test
@@ -0,0 +1,48 @@
+# 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
new file mode 100644
index 000000000000..d7e8a1a92598
--- /dev/null
+++ b/test/old-elf/Mips/rel-gprel16.test
@@ -0,0 +1,104 @@
+# 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
new file mode 100644
index 000000000000..15498a693e4d
--- /dev/null
+++ b/test/old-elf/Mips/rel-gprel32-64.test
@@ -0,0 +1,84 @@
+# 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
new file mode 100644
index 000000000000..14ec8cebcabd
--- /dev/null
+++ b/test/old-elf/Mips/rel-gprel32.test
@@ -0,0 +1,84 @@
+# 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
new file mode 100644
index 000000000000..5609786aa04a
--- /dev/null
+++ b/test/old-elf/Mips/rel-gprel7-micro-overflow.test
@@ -0,0 +1,48 @@
+# 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
new file mode 100644
index 000000000000..b7790d9d169c
--- /dev/null
+++ b/test/old-elf/Mips/rel-gprel7-micro.test
@@ -0,0 +1,65 @@
+# 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
new file mode 100644
index 000000000000..82f62954b992
--- /dev/null
+++ b/test/old-elf/Mips/rel-hi0-lo16-micro.test
@@ -0,0 +1,58 @@
+# 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
new file mode 100644
index 000000000000..613fedbe31db
--- /dev/null
+++ b/test/old-elf/Mips/rel-high-01.test
@@ -0,0 +1,25 @@
+# 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
new file mode 100644
index 000000000000..7a40a617a680
--- /dev/null
+++ b/test/old-elf/Mips/rel-high-02.test
@@ -0,0 +1,25 @@
+# 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
new file mode 100644
index 000000000000..3c519056e1a9
--- /dev/null
+++ b/test/old-elf/Mips/rel-jalr-01.test
@@ -0,0 +1,101 @@
+# 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
new file mode 100644
index 000000000000..e9c74c4c3300
--- /dev/null
+++ b/test/old-elf/Mips/rel-jalr-02.test
@@ -0,0 +1,68 @@
+# 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
new file mode 100644
index 000000000000..783b24f83813
--- /dev/null
+++ b/test/old-elf/Mips/rel-lit-micro.test
@@ -0,0 +1,59 @@
+# 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
new file mode 100644
index 000000000000..19aa68721691
--- /dev/null
+++ b/test/old-elf/Mips/rel-lit.test
@@ -0,0 +1,57 @@
+# 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
new file mode 100644
index 000000000000..6791926762b2
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc-hilo.test
@@ -0,0 +1,70 @@
+# 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
new file mode 100644
index 000000000000..6366a4d67e92
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc16-align.test
@@ -0,0 +1,43 @@
+# 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
new file mode 100644
index 000000000000..910482ee6154
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc16-overflow.test
@@ -0,0 +1,45 @@
+# 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
new file mode 100644
index 000000000000..f298afd81cd6
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc16.test
@@ -0,0 +1,53 @@
+# 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
new file mode 100644
index 000000000000..ca2fa18ecaa0
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc18-s3-align.test
@@ -0,0 +1,44 @@
+# 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
new file mode 100644
index 000000000000..fc143a75e569
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc18-s3-micro.test
@@ -0,0 +1,56 @@
+# 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
new file mode 100644
index 000000000000..d61427448d53
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc18-s3.test
@@ -0,0 +1,54 @@
+# 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
new file mode 100644
index 000000000000..19010a445578
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc19-s2-align.test
@@ -0,0 +1,44 @@
+# 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
new file mode 100644
index 000000000000..d9a930e41d88
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc19-s2-micro.test
@@ -0,0 +1,56 @@
+# 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
new file mode 100644
index 000000000000..da21864a1214
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc19-s2.test
@@ -0,0 +1,54 @@
+# 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
new file mode 100644
index 000000000000..a79e1e2a46e0
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc21-s2-align.test
@@ -0,0 +1,44 @@
+# 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
new file mode 100644
index 000000000000..4aa0a7de9489
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc21-s2-micro.test
@@ -0,0 +1,56 @@
+# 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
new file mode 100644
index 000000000000..ad88e0c14b44
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc21-s2-overflow.test
@@ -0,0 +1,45 @@
+# 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
new file mode 100644
index 000000000000..c2b58c859af9
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc21-s2.test
@@ -0,0 +1,54 @@
+# 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
new file mode 100644
index 000000000000..23e660848365
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc26-s2-align.test
@@ -0,0 +1,44 @@
+# 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
new file mode 100644
index 000000000000..193c328be687
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc26-s2-micro.test
@@ -0,0 +1,56 @@
+# 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
new file mode 100644
index 000000000000..c500f00cb860
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc26-s2.test
@@ -0,0 +1,54 @@
+# 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
new file mode 100644
index 000000000000..9faa32efec7b
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc32.test
@@ -0,0 +1,59 @@
+# 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
new file mode 100644
index 000000000000..51c4c3a670f1
--- /dev/null
+++ b/test/old-elf/Mips/rel-pc7-10-16-23.test
@@ -0,0 +1,86 @@
+# 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
new file mode 100644
index 000000000000..831a020ce2f9
--- /dev/null
+++ b/test/old-elf/Mips/rel-sub-micro.test
@@ -0,0 +1,62 @@
+# 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
new file mode 100644
index 000000000000..5100406fd5d5
--- /dev/null
+++ b/test/old-elf/Mips/rel-sub.test
@@ -0,0 +1,61 @@
+# 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
new file mode 100644
index 000000000000..ee063be1d7fc
--- /dev/null
+++ b/test/old-elf/Mips/rld_map.test
@@ -0,0 +1,42 @@
+# 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
new file mode 100644
index 000000000000..3e5341f2c230
--- /dev/null
+++ b/test/old-elf/Mips/sign-rela.test
@@ -0,0 +1,54 @@
+# 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
new file mode 100644
index 000000000000..2bb1f8b96e07
--- /dev/null
+++ b/test/old-elf/Mips/st-other.test
@@ -0,0 +1,90 @@
+# 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
new file mode 100644
index 000000000000..77a33469df3f
--- /dev/null
+++ b/test/old-elf/Mips/static-01.test
@@ -0,0 +1,119 @@
+# 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
new file mode 100644
index 000000000000..f47592a5ab7d
--- /dev/null
+++ b/test/old-elf/Mips/tls-1-micro.test
@@ -0,0 +1,65 @@
+# 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
new file mode 100644
index 000000000000..c25a06c1dee9
--- /dev/null
+++ b/test/old-elf/Mips/tls-1.test
@@ -0,0 +1,63 @@
+# 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
new file mode 100644
index 000000000000..c8c30ea06c60
--- /dev/null
+++ b/test/old-elf/Mips/tls-2-64-static.test
@@ -0,0 +1,71 @@
+# 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
new file mode 100644
index 000000000000..3a6f6b3bedea
--- /dev/null
+++ b/test/old-elf/Mips/tls-2-64.test
@@ -0,0 +1,69 @@
+# 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
new file mode 100644
index 000000000000..88d8797cd06a
--- /dev/null
+++ b/test/old-elf/Mips/tls-2-micro.test
@@ -0,0 +1,70 @@
+# 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
new file mode 100644
index 000000000000..3ac2122628d6
--- /dev/null
+++ b/test/old-elf/Mips/tls-2-static.test
@@ -0,0 +1,125 @@
+# 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
new file mode 100644
index 000000000000..de8fc2a70861
--- /dev/null
+++ b/test/old-elf/Mips/tls-2.test
@@ -0,0 +1,69 @@
+# 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
new file mode 100644
index 000000000000..2183d1fd6833
--- /dev/null
+++ b/test/old-elf/Mips/tls-3-64-static.test
@@ -0,0 +1,70 @@
+# 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
new file mode 100644
index 000000000000..347332e6633e
--- /dev/null
+++ b/test/old-elf/Mips/tls-3-micro.test
@@ -0,0 +1,183 @@
+# 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
new file mode 100644
index 000000000000..5d3a7b8bfd6a
--- /dev/null
+++ b/test/old-elf/Mips/tls-3-static.test
@@ -0,0 +1,67 @@
+# 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
new file mode 100644
index 000000000000..eb9750fee28d
--- /dev/null
+++ b/test/old-elf/Mips/tls-3.test
@@ -0,0 +1,180 @@
+# 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
new file mode 100644
index 000000000000..3aa37046d36b
--- /dev/null
+++ b/test/old-elf/Mips/tls-4-64-static.test
@@ -0,0 +1,71 @@
+# 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
new file mode 100644
index 000000000000..23d8e0a1de31
--- /dev/null
+++ b/test/old-elf/Mips/tls-4-micro.test
@@ -0,0 +1,126 @@
+# 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
new file mode 100644
index 000000000000..5fdb11df874b
--- /dev/null
+++ b/test/old-elf/Mips/tls-4-static.test
@@ -0,0 +1,68 @@
+# 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
new file mode 100644
index 000000000000..95df6d67151f
--- /dev/null
+++ b/test/old-elf/Mips/tls-4.test
@@ -0,0 +1,123 @@
+# 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
new file mode 100644
index 000000000000..43e6e6c1cf30
--- /dev/null
+++ b/test/old-elf/Mips/tls-5-64.test
@@ -0,0 +1,71 @@
+# 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
new file mode 100644
index 000000000000..412456417826
--- /dev/null
+++ b/test/old-elf/Mips/tls-5-micro.test
@@ -0,0 +1,70 @@
+# 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
new file mode 100644
index 000000000000..cb71e3ac5f9e
--- /dev/null
+++ b/test/old-elf/Mips/tls-5.test
@@ -0,0 +1,69 @@
+# 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
new file mode 100644
index 000000000000..0b8734c5429e
--- /dev/null
+++ b/test/old-elf/Mips/validate-rel-01.test
@@ -0,0 +1,82 @@
+# 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
new file mode 100644
index 000000000000..baf8516c63b0
--- /dev/null
+++ b/test/old-elf/Mips/validate-rel-03.test
@@ -0,0 +1,56 @@
+# 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
new file mode 100644
index 000000000000..aec09eae3a30
--- /dev/null
+++ b/test/old-elf/X86_64/ExampleTarget/triple.test
@@ -0,0 +1,32 @@
+# 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/elf/X86_64/Inputs/constint.c b/test/old-elf/X86_64/Inputs/constint.c
index 9fc0ebcf6591..9fc0ebcf6591 100644
--- a/test/elf/X86_64/Inputs/constint.c
+++ b/test/old-elf/X86_64/Inputs/constint.c
diff --git a/test/elf/X86_64/Inputs/constint.o b/test/old-elf/X86_64/Inputs/constint.o
index 8324b73014d0..8324b73014d0 100644
--- a/test/elf/X86_64/Inputs/constint.o
+++ b/test/old-elf/X86_64/Inputs/constint.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/debug0.c b/test/old-elf/X86_64/Inputs/debug0.c
index 1ebe50087383..1ebe50087383 100644
--- a/test/elf/X86_64/Inputs/debug0.c
+++ b/test/old-elf/X86_64/Inputs/debug0.c
diff --git a/test/elf/X86_64/Inputs/debug0.x86-64 b/test/old-elf/X86_64/Inputs/debug0.x86-64
index 914f5224b9a2..914f5224b9a2 100644
--- a/test/elf/X86_64/Inputs/debug0.x86-64
+++ b/test/old-elf/X86_64/Inputs/debug0.x86-64
Binary files differ
diff --git a/test/elf/X86_64/Inputs/debug1.c b/test/old-elf/X86_64/Inputs/debug1.c
index 281b8a361dbb..281b8a361dbb 100644
--- a/test/elf/X86_64/Inputs/debug1.c
+++ b/test/old-elf/X86_64/Inputs/debug1.c
diff --git a/test/elf/X86_64/Inputs/debug1.x86-64 b/test/old-elf/X86_64/Inputs/debug1.x86-64
index bfc81458a034..bfc81458a034 100644
--- a/test/elf/X86_64/Inputs/debug1.x86-64
+++ b/test/old-elf/X86_64/Inputs/debug1.x86-64
Binary files differ
diff --git a/test/elf/X86_64/Inputs/externtls.c b/test/old-elf/X86_64/Inputs/externtls.c
index 499a645a9217..499a645a9217 100644
--- a/test/elf/X86_64/Inputs/externtls.c
+++ b/test/old-elf/X86_64/Inputs/externtls.c
diff --git a/test/elf/X86_64/Inputs/externtls.x86-64 b/test/old-elf/X86_64/Inputs/externtls.x86-64
index 3019aa0ca27c..3019aa0ca27c 100644
--- a/test/elf/X86_64/Inputs/externtls.x86-64
+++ b/test/old-elf/X86_64/Inputs/externtls.x86-64
Binary files differ
diff --git a/test/elf/X86_64/Inputs/fn.c b/test/old-elf/X86_64/Inputs/fn.c
index 54939a2426b2..54939a2426b2 100644
--- a/test/elf/X86_64/Inputs/fn.c
+++ b/test/old-elf/X86_64/Inputs/fn.c
diff --git a/test/elf/X86_64/Inputs/fn.o b/test/old-elf/X86_64/Inputs/fn.o
index 4b67d459dfdb..4b67d459dfdb 100644
--- a/test/elf/X86_64/Inputs/fn.o
+++ b/test/old-elf/X86_64/Inputs/fn.o
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
new file mode 100644
index 000000000000..53a7fb6435e9
--- /dev/null
+++ b/test/old-elf/X86_64/Inputs/generaltls-so.o.yaml
@@ -0,0 +1,67 @@
+---
+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/elf/X86_64/Inputs/group/1.c b/test/old-elf/X86_64/Inputs/group/1.c
index f5e618bc4a85..f5e618bc4a85 100644
--- a/test/elf/X86_64/Inputs/group/1.c
+++ b/test/old-elf/X86_64/Inputs/group/1.c
diff --git a/test/elf/X86_64/Inputs/group/1.o b/test/old-elf/X86_64/Inputs/group/1.o
index 743518eb0fa3..743518eb0fa3 100644
--- a/test/elf/X86_64/Inputs/group/1.o
+++ b/test/old-elf/X86_64/Inputs/group/1.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/group/fn.c b/test/old-elf/X86_64/Inputs/group/fn.c
index e443c73a1ee0..e443c73a1ee0 100644
--- a/test/elf/X86_64/Inputs/group/fn.c
+++ b/test/old-elf/X86_64/Inputs/group/fn.c
diff --git a/test/elf/X86_64/Inputs/group/fn.o b/test/old-elf/X86_64/Inputs/group/fn.o
index 1134432449cd..1134432449cd 100644
--- a/test/elf/X86_64/Inputs/group/fn.o
+++ b/test/old-elf/X86_64/Inputs/group/fn.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/group/fn1.c b/test/old-elf/X86_64/Inputs/group/fn1.c
index cca0df7fd277..cca0df7fd277 100644
--- a/test/elf/X86_64/Inputs/group/fn1.c
+++ b/test/old-elf/X86_64/Inputs/group/fn1.c
diff --git a/test/elf/X86_64/Inputs/group/fn1.o b/test/old-elf/X86_64/Inputs/group/fn1.o
index 2b02310003db..2b02310003db 100644
--- a/test/elf/X86_64/Inputs/group/fn1.o
+++ b/test/old-elf/X86_64/Inputs/group/fn1.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/group/fn2.c b/test/old-elf/X86_64/Inputs/group/fn2.c
index a60370ed1e6b..a60370ed1e6b 100644
--- a/test/elf/X86_64/Inputs/group/fn2.c
+++ b/test/old-elf/X86_64/Inputs/group/fn2.c
diff --git a/test/elf/X86_64/Inputs/group/fn2.o b/test/old-elf/X86_64/Inputs/group/fn2.o
index fabec849a775..fabec849a775 100644
--- a/test/elf/X86_64/Inputs/group/fn2.o
+++ b/test/old-elf/X86_64/Inputs/group/fn2.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/group/group.sh b/test/old-elf/X86_64/Inputs/group/group.sh
index 2eba1030160b..2eba1030160b 100755
--- a/test/elf/X86_64/Inputs/group/group.sh
+++ b/test/old-elf/X86_64/Inputs/group/group.sh
diff --git a/test/elf/X86_64/Inputs/group/libfn.a b/test/old-elf/X86_64/Inputs/group/libfn.a
index c157c3babed9..c157c3babed9 100644
--- a/test/elf/X86_64/Inputs/group/libfn.a
+++ b/test/old-elf/X86_64/Inputs/group/libfn.a
Binary files differ
diff --git a/test/elf/X86_64/Inputs/group/libfn.so b/test/old-elf/X86_64/Inputs/group/libfn.so
index fcbd11fe5519..fcbd11fe5519 100755
--- a/test/elf/X86_64/Inputs/group/libfn.so
+++ b/test/old-elf/X86_64/Inputs/group/libfn.so
Binary files differ
diff --git a/test/elf/X86_64/Inputs/group/libfn1.a b/test/old-elf/X86_64/Inputs/group/libfn1.a
index 69b9c75b5d16..69b9c75b5d16 100644
--- a/test/elf/X86_64/Inputs/group/libfn1.a
+++ b/test/old-elf/X86_64/Inputs/group/libfn1.a
Binary files differ
diff --git a/test/elf/X86_64/Inputs/group/libfn2.so b/test/old-elf/X86_64/Inputs/group/libfn2.so
index 7ce867373910..7ce867373910 100755
--- a/test/elf/X86_64/Inputs/group/libfn2.so
+++ b/test/old-elf/X86_64/Inputs/group/libfn2.so
Binary files differ
diff --git a/test/elf/X86_64/Inputs/initfini-option.c b/test/old-elf/X86_64/Inputs/initfini-option.c
index e9a6c08c12ac..e9a6c08c12ac 100644
--- a/test/elf/X86_64/Inputs/initfini-option.c
+++ b/test/old-elf/X86_64/Inputs/initfini-option.c
diff --git a/test/elf/X86_64/Inputs/initfini-option.o b/test/old-elf/X86_64/Inputs/initfini-option.o
index b1ba0557353c..b1ba0557353c 100644
--- a/test/elf/X86_64/Inputs/initfini-option.o
+++ b/test/old-elf/X86_64/Inputs/initfini-option.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/initfini.c b/test/old-elf/X86_64/Inputs/initfini.c
index 9427a86b6c9b..9427a86b6c9b 100644
--- a/test/elf/X86_64/Inputs/initfini.c
+++ b/test/old-elf/X86_64/Inputs/initfini.c
diff --git a/test/elf/X86_64/Inputs/initfini.o b/test/old-elf/X86_64/Inputs/initfini.o
index f0e55a90b8b6..f0e55a90b8b6 100644
--- a/test/elf/X86_64/Inputs/initfini.o
+++ b/test/old-elf/X86_64/Inputs/initfini.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/largebss.c b/test/old-elf/X86_64/Inputs/largebss.c
index 157d01755b6a..157d01755b6a 100644
--- a/test/elf/X86_64/Inputs/largebss.c
+++ b/test/old-elf/X86_64/Inputs/largebss.c
diff --git a/test/elf/X86_64/Inputs/largebss.o b/test/old-elf/X86_64/Inputs/largebss.o
index 377370ec2db2..377370ec2db2 100644
--- a/test/elf/X86_64/Inputs/largebss.o
+++ b/test/old-elf/X86_64/Inputs/largebss.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/layoutpass/1.c b/test/old-elf/X86_64/Inputs/layoutpass/1.c
index fec984503214..fec984503214 100644
--- a/test/elf/X86_64/Inputs/layoutpass/1.c
+++ b/test/old-elf/X86_64/Inputs/layoutpass/1.c
diff --git a/test/elf/X86_64/Inputs/layoutpass/1.o b/test/old-elf/X86_64/Inputs/layoutpass/1.o
index 848a5b3321ac..848a5b3321ac 100644
--- a/test/elf/X86_64/Inputs/layoutpass/1.o
+++ b/test/old-elf/X86_64/Inputs/layoutpass/1.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/layoutpass/2.c b/test/old-elf/X86_64/Inputs/layoutpass/2.c
index fb9dbcc28aa6..fb9dbcc28aa6 100644
--- a/test/elf/X86_64/Inputs/layoutpass/2.c
+++ b/test/old-elf/X86_64/Inputs/layoutpass/2.c
diff --git a/test/elf/X86_64/Inputs/layoutpass/2.o b/test/old-elf/X86_64/Inputs/layoutpass/2.o
index 4c5ef8679581..4c5ef8679581 100644
--- a/test/elf/X86_64/Inputs/layoutpass/2.o
+++ b/test/old-elf/X86_64/Inputs/layoutpass/2.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/layoutpass/3.c b/test/old-elf/X86_64/Inputs/layoutpass/3.c
index 054029fe5cfe..054029fe5cfe 100644
--- a/test/elf/X86_64/Inputs/layoutpass/3.c
+++ b/test/old-elf/X86_64/Inputs/layoutpass/3.c
diff --git a/test/elf/X86_64/Inputs/layoutpass/3.o b/test/old-elf/X86_64/Inputs/layoutpass/3.o
index 76ef76e97901..76ef76e97901 100644
--- a/test/elf/X86_64/Inputs/layoutpass/3.o
+++ b/test/old-elf/X86_64/Inputs/layoutpass/3.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/layoutpass/lib2.a b/test/old-elf/X86_64/Inputs/layoutpass/lib2.a
index 5f076c869817..5f076c869817 100644
--- a/test/elf/X86_64/Inputs/layoutpass/lib2.a
+++ b/test/old-elf/X86_64/Inputs/layoutpass/lib2.a
Binary files differ
diff --git a/test/elf/X86_64/Inputs/libfn.a b/test/old-elf/X86_64/Inputs/libfn.a
index 380844b0838d..380844b0838d 100644
--- a/test/elf/X86_64/Inputs/libfn.a
+++ b/test/old-elf/X86_64/Inputs/libfn.a
Binary files differ
diff --git a/test/elf/X86_64/Inputs/libfn.so b/test/old-elf/X86_64/Inputs/libfn.so
index dc02480aa690..dc02480aa690 100755
--- a/test/elf/X86_64/Inputs/libfn.so
+++ b/test/old-elf/X86_64/Inputs/libfn.so
Binary files differ
diff --git a/test/elf/X86_64/Inputs/main.c b/test/old-elf/X86_64/Inputs/main.c
index 0280c9127076..0280c9127076 100644
--- a/test/elf/X86_64/Inputs/main.c
+++ b/test/old-elf/X86_64/Inputs/main.c
diff --git a/test/elf/X86_64/Inputs/main.o b/test/old-elf/X86_64/Inputs/main.o
index ec8929f4b51d..ec8929f4b51d 100644
--- a/test/elf/X86_64/Inputs/main.o
+++ b/test/old-elf/X86_64/Inputs/main.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/multi-ovrd.c b/test/old-elf/X86_64/Inputs/multi-ovrd.c
index cf6c0b6ac361..cf6c0b6ac361 100644
--- a/test/elf/X86_64/Inputs/multi-ovrd.c
+++ b/test/old-elf/X86_64/Inputs/multi-ovrd.c
diff --git a/test/elf/X86_64/Inputs/multi-ovrd.o b/test/old-elf/X86_64/Inputs/multi-ovrd.o
index e4c4d6037fdd..e4c4d6037fdd 100644
--- a/test/elf/X86_64/Inputs/multi-ovrd.o
+++ b/test/old-elf/X86_64/Inputs/multi-ovrd.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/multi-weak.c b/test/old-elf/X86_64/Inputs/multi-weak.c
index 10b9160352d9..10b9160352d9 100644
--- a/test/elf/X86_64/Inputs/multi-weak.c
+++ b/test/old-elf/X86_64/Inputs/multi-weak.c
diff --git a/test/elf/X86_64/Inputs/multi-weak.o b/test/old-elf/X86_64/Inputs/multi-weak.o
index d5677b699ac4..d5677b699ac4 100644
--- a/test/elf/X86_64/Inputs/multi-weak.o
+++ b/test/old-elf/X86_64/Inputs/multi-weak.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/multiweaksyms.o b/test/old-elf/X86_64/Inputs/multiweaksyms.o
index 5e2e54d66b0d..5e2e54d66b0d 100644
--- a/test/elf/X86_64/Inputs/multiweaksyms.o
+++ b/test/old-elf/X86_64/Inputs/multiweaksyms.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/nmagic.c b/test/old-elf/X86_64/Inputs/nmagic.c
index 3ad15f0c4971..3ad15f0c4971 100644
--- a/test/elf/X86_64/Inputs/nmagic.c
+++ b/test/old-elf/X86_64/Inputs/nmagic.c
diff --git a/test/elf/X86_64/Inputs/nmagic.o b/test/old-elf/X86_64/Inputs/nmagic.o
index af28e0ada8b3..af28e0ada8b3 100644
--- a/test/elf/X86_64/Inputs/nmagic.o
+++ b/test/old-elf/X86_64/Inputs/nmagic.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/no-interp-section.c b/test/old-elf/X86_64/Inputs/no-interp-section.c
index 3981c038ed33..3981c038ed33 100644
--- a/test/elf/X86_64/Inputs/no-interp-section.c
+++ b/test/old-elf/X86_64/Inputs/no-interp-section.c
diff --git a/test/elf/X86_64/Inputs/no-interp-section.o b/test/old-elf/X86_64/Inputs/no-interp-section.o
index 063eb3244f22..063eb3244f22 100644
--- a/test/elf/X86_64/Inputs/no-interp-section.o
+++ b/test/old-elf/X86_64/Inputs/no-interp-section.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/note.o b/test/old-elf/X86_64/Inputs/note.o
index d86b0cf85d19..d86b0cf85d19 100644
--- a/test/elf/X86_64/Inputs/note.o
+++ b/test/old-elf/X86_64/Inputs/note.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/note.s b/test/old-elf/X86_64/Inputs/note.s
index 0a0b03da6bb7..0a0b03da6bb7 100644
--- a/test/elf/X86_64/Inputs/note.s
+++ b/test/old-elf/X86_64/Inputs/note.s
diff --git a/test/elf/X86_64/Inputs/note_ro_rw.o b/test/old-elf/X86_64/Inputs/note_ro_rw.o
index 76f2486d2736..76f2486d2736 100644
--- a/test/elf/X86_64/Inputs/note_ro_rw.o
+++ b/test/old-elf/X86_64/Inputs/note_ro_rw.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/note_ro_rw.s b/test/old-elf/X86_64/Inputs/note_ro_rw.s
index 2a0eff5dfb2b..2a0eff5dfb2b 100644
--- a/test/elf/X86_64/Inputs/note_ro_rw.s
+++ b/test/old-elf/X86_64/Inputs/note_ro_rw.s
diff --git a/test/elf/X86_64/Inputs/ovrd.c b/test/old-elf/X86_64/Inputs/ovrd.c
index a3d721dac2aa..a3d721dac2aa 100644
--- a/test/elf/X86_64/Inputs/ovrd.c
+++ b/test/old-elf/X86_64/Inputs/ovrd.c
diff --git a/test/elf/X86_64/Inputs/ovrd.o b/test/old-elf/X86_64/Inputs/ovrd.o
index ea7353d94ed9..ea7353d94ed9 100644
--- a/test/elf/X86_64/Inputs/ovrd.o
+++ b/test/old-elf/X86_64/Inputs/ovrd.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/rodata.c b/test/old-elf/X86_64/Inputs/rodata.c
index 01489fe550c8..01489fe550c8 100644
--- a/test/elf/X86_64/Inputs/rodata.c
+++ b/test/old-elf/X86_64/Inputs/rodata.c
diff --git a/test/elf/X86_64/Inputs/rodata.o b/test/old-elf/X86_64/Inputs/rodata.o
index 660606cdc9c0..660606cdc9c0 100644
--- a/test/elf/X86_64/Inputs/rodata.o
+++ b/test/old-elf/X86_64/Inputs/rodata.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/rodata.s b/test/old-elf/X86_64/Inputs/rodata.s
index e1a2eb702736..e1a2eb702736 100644
--- a/test/elf/X86_64/Inputs/rodata.s
+++ b/test/old-elf/X86_64/Inputs/rodata.s
diff --git a/test/elf/X86_64/Inputs/rwint.c b/test/old-elf/X86_64/Inputs/rwint.c
index d1cf7d62c801..d1cf7d62c801 100644
--- a/test/elf/X86_64/Inputs/rwint.c
+++ b/test/old-elf/X86_64/Inputs/rwint.c
diff --git a/test/elf/X86_64/Inputs/rwint.o b/test/old-elf/X86_64/Inputs/rwint.o
index 9fba51f07add..9fba51f07add 100644
--- a/test/elf/X86_64/Inputs/rwint.o
+++ b/test/old-elf/X86_64/Inputs/rwint.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/sectionmap.c b/test/old-elf/X86_64/Inputs/sectionmap.c
index c4f530148949..c4f530148949 100644
--- a/test/elf/X86_64/Inputs/sectionmap.c
+++ b/test/old-elf/X86_64/Inputs/sectionmap.c
diff --git a/test/elf/X86_64/Inputs/sectionmap.o b/test/old-elf/X86_64/Inputs/sectionmap.o
index 599cf2cca563..599cf2cca563 100644
--- a/test/elf/X86_64/Inputs/sectionmap.o
+++ b/test/old-elf/X86_64/Inputs/sectionmap.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/undefcpp.c b/test/old-elf/X86_64/Inputs/undefcpp.c
index ce84c2a592b6..ce84c2a592b6 100644
--- a/test/elf/X86_64/Inputs/undefcpp.c
+++ b/test/old-elf/X86_64/Inputs/undefcpp.c
diff --git a/test/elf/X86_64/Inputs/undefcpp.o b/test/old-elf/X86_64/Inputs/undefcpp.o
index 6b8ebf5b6ab0..6b8ebf5b6ab0 100644
--- a/test/elf/X86_64/Inputs/undefcpp.o
+++ b/test/old-elf/X86_64/Inputs/undefcpp.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/weak-zero-sized.o b/test/old-elf/X86_64/Inputs/weak-zero-sized.o
index 7c10c6a509ed..7c10c6a509ed 100644
--- a/test/elf/X86_64/Inputs/weak-zero-sized.o
+++ b/test/old-elf/X86_64/Inputs/weak-zero-sized.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/weak.c b/test/old-elf/X86_64/Inputs/weak.c
index ae07ffc745d8..ae07ffc745d8 100644
--- a/test/elf/X86_64/Inputs/weak.c
+++ b/test/old-elf/X86_64/Inputs/weak.c
diff --git a/test/elf/X86_64/Inputs/weak.o b/test/old-elf/X86_64/Inputs/weak.o
index 41cc88a0c482..41cc88a0c482 100644
--- a/test/elf/X86_64/Inputs/weak.o
+++ b/test/old-elf/X86_64/Inputs/weak.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/weak.s b/test/old-elf/X86_64/Inputs/weak.s
index 64ce779553b6..64ce779553b6 100644
--- a/test/elf/X86_64/Inputs/weak.s
+++ b/test/old-elf/X86_64/Inputs/weak.s
diff --git a/test/elf/X86_64/Inputs/zerosizedsection.o b/test/old-elf/X86_64/Inputs/zerosizedsection.o
index a0f2f13a307a..a0f2f13a307a 100644
--- a/test/elf/X86_64/Inputs/zerosizedsection.o
+++ b/test/old-elf/X86_64/Inputs/zerosizedsection.o
Binary files differ
diff --git a/test/elf/X86_64/Inputs/zerosizedsection.s b/test/old-elf/X86_64/Inputs/zerosizedsection.s
index 651ee3aab503..651ee3aab503 100644
--- a/test/elf/X86_64/Inputs/zerosizedsection.s
+++ b/test/old-elf/X86_64/Inputs/zerosizedsection.s
diff --git a/test/old-elf/X86_64/alignoffset.test b/test/old-elf/X86_64/alignoffset.test
new file mode 100644
index 000000000000..53e29211af67
--- /dev/null
+++ b/test/old-elf/X86_64/alignoffset.test
@@ -0,0 +1,118 @@
+# 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
new file mode 100644
index 000000000000..26ba367da574
--- /dev/null
+++ b/test/old-elf/X86_64/debug.test
@@ -0,0 +1,57 @@
+# 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
new file mode 100644
index 000000000000..d98abf39d428
--- /dev/null
+++ b/test/old-elf/X86_64/defsym.test
@@ -0,0 +1,22 @@
+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
new file mode 100644
index 000000000000..caae8256d99a
--- /dev/null
+++ b/test/old-elf/X86_64/demangle.test
@@ -0,0 +1,12 @@
+# 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
new file mode 100644
index 000000000000..f3042b5508fd
--- /dev/null
+++ b/test/old-elf/X86_64/dontignorezerosize-sections.test
@@ -0,0 +1,9 @@
+# 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
new file mode 100644
index 000000000000..c6f679038320
--- /dev/null
+++ b/test/old-elf/X86_64/dynamicvars.test
@@ -0,0 +1,123 @@
+# 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
new file mode 100644
index 000000000000..c23d283d2a6d
--- /dev/null
+++ b/test/old-elf/X86_64/dynlib-nointerp-section.test
@@ -0,0 +1,4 @@
+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
new file mode 100644
index 000000000000..efd7272fb145
--- /dev/null
+++ b/test/old-elf/X86_64/dynlib-search.test
@@ -0,0 +1,6 @@
+# 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
new file mode 100644
index 000000000000..8e1cc9fa8ec9
--- /dev/null
+++ b/test/old-elf/X86_64/dynsym-weak.test
@@ -0,0 +1,118 @@
+# 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
new file mode 100644
index 000000000000..d22b06057a9a
--- /dev/null
+++ b/test/old-elf/X86_64/extern-tls.test
@@ -0,0 +1,16 @@
+# 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
new file mode 100644
index 000000000000..12ad1071ae1e
--- /dev/null
+++ b/test/old-elf/X86_64/general-dynamic-tls.test
@@ -0,0 +1,128 @@
+# 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
new file mode 100644
index 000000000000..7b6f7318d72d
--- /dev/null
+++ b/test/old-elf/X86_64/imagebase.test
@@ -0,0 +1,94 @@
+# 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
new file mode 100644
index 000000000000..e6afcf644346
--- /dev/null
+++ b/test/old-elf/X86_64/initfini-order.test
@@ -0,0 +1,10 @@
+# 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
new file mode 100644
index 000000000000..09d2bc129c25
--- /dev/null
+++ b/test/old-elf/X86_64/initfini.test
@@ -0,0 +1,23 @@
+# 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
new file mode 100644
index 000000000000..722ec1c72bf9
--- /dev/null
+++ b/test/old-elf/X86_64/largebss.test
@@ -0,0 +1,20 @@
+# 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
new file mode 100644
index 000000000000..ec180c970e78
--- /dev/null
+++ b/test/old-elf/X86_64/layoutpass-order.test
@@ -0,0 +1,14 @@
+# 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
new file mode 100644
index 000000000000..303bd86eec0b
--- /dev/null
+++ b/test/old-elf/X86_64/maxpagesize.test
@@ -0,0 +1,113 @@
+# 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
new file mode 100644
index 000000000000..2b9b08faa23f
--- /dev/null
+++ b/test/old-elf/X86_64/mergesimilarstrings.test
@@ -0,0 +1,47 @@
+# 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
new file mode 100644
index 000000000000..879b4b1b3052
--- /dev/null
+++ b/test/old-elf/X86_64/multi-weak-layout.test
@@ -0,0 +1,52 @@
+# 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
new file mode 100644
index 000000000000..75c86e7e405f
--- /dev/null
+++ b/test/old-elf/X86_64/multi-weak-override.test
@@ -0,0 +1,16 @@
+# 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
new file mode 100644
index 000000000000..a8e21e13f870
--- /dev/null
+++ b/test/old-elf/X86_64/multi-weak-syms-order.test
@@ -0,0 +1,13 @@
+# 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
new file mode 100644
index 000000000000..3ed9228fa787
--- /dev/null
+++ b/test/old-elf/X86_64/nmagic.test
@@ -0,0 +1,91 @@
+# 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
new file mode 100644
index 000000000000..4963575b674b
--- /dev/null
+++ b/test/old-elf/X86_64/noalignsegments.test
@@ -0,0 +1,95 @@
+# 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
new file mode 100644
index 000000000000..b4eafaf277c4
--- /dev/null
+++ b/test/old-elf/X86_64/note-sections-ro_plus_rw.test
@@ -0,0 +1,42 @@
+# 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
new file mode 100644
index 000000000000..b831e7e192b4
--- /dev/null
+++ b/test/old-elf/X86_64/note-sections.test
@@ -0,0 +1,23 @@
+# 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
new file mode 100644
index 000000000000..fe2633e67a95
--- /dev/null
+++ b/test/old-elf/X86_64/omagic.test
@@ -0,0 +1,237 @@
+# 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
new file mode 100644
index 000000000000..1c76b6eb855c
--- /dev/null
+++ b/test/old-elf/X86_64/outputsegments.test
@@ -0,0 +1,188 @@
+# 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
new file mode 100644
index 000000000000..093fbeb4f137
--- /dev/null
+++ b/test/old-elf/X86_64/reloc_r_x86_64_16.test
@@ -0,0 +1,59 @@
+# 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
new file mode 100644
index 000000000000..c6e53ad636e8
--- /dev/null
+++ b/test/old-elf/X86_64/reloc_r_x86_64_pc16.test
@@ -0,0 +1,60 @@
+# 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
new file mode 100644
index 000000000000..a7c5e88965c5
--- /dev/null
+++ b/test/old-elf/X86_64/reloc_r_x86_64_pc64.test
@@ -0,0 +1,60 @@
+# 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
new file mode 100644
index 000000000000..6f85ac0423fd
--- /dev/null
+++ b/test/old-elf/X86_64/rodata.test
@@ -0,0 +1,9 @@
+# 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
new file mode 100644
index 000000000000..7ff838fed98d
--- /dev/null
+++ b/test/old-elf/X86_64/sectionchoice.test
@@ -0,0 +1,7 @@
+# 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
new file mode 100644
index 000000000000..5fa04bd87051
--- /dev/null
+++ b/test/old-elf/X86_64/sectionmap.test
@@ -0,0 +1,22 @@
+# 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
new file mode 100644
index 000000000000..e79e436a6513
--- /dev/null
+++ b/test/old-elf/X86_64/startGroupEndGroup.test
@@ -0,0 +1,48 @@
+# 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
new file mode 100644
index 000000000000..30bfe1530f8e
--- /dev/null
+++ b/test/old-elf/X86_64/startGroupEndGroupWithDynlib.test
@@ -0,0 +1,10 @@
+# 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
new file mode 100644
index 000000000000..b84bd299f385
--- /dev/null
+++ b/test/old-elf/X86_64/staticlib-search.test
@@ -0,0 +1,6 @@
+# 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
new file mode 100644
index 000000000000..f948286a339b
--- /dev/null
+++ b/test/old-elf/X86_64/undef.test
@@ -0,0 +1,18 @@
+# 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
new file mode 100644
index 000000000000..4ca0c94013ea
--- /dev/null
+++ b/test/old-elf/X86_64/underscore-end.test
@@ -0,0 +1,81 @@
+# 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
new file mode 100644
index 000000000000..25cb9d5d687f
--- /dev/null
+++ b/test/old-elf/X86_64/weak-override.test
@@ -0,0 +1,45 @@
+# 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
new file mode 100644
index 000000000000..93e27a355d64
--- /dev/null
+++ b/test/old-elf/X86_64/weak-zero-sized.test
@@ -0,0 +1,26 @@
+# 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
new file mode 100644
index 000000000000..9e4f2da9bdba
--- /dev/null
+++ b/test/old-elf/X86_64/weaksym.test
@@ -0,0 +1,77 @@
+# 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
new file mode 100644
index 000000000000..1c51811eec95
--- /dev/null
+++ b/test/old-elf/X86_64/yamlinput.test
@@ -0,0 +1,166 @@
+# 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
new file mode 100644
index 000000000000..c662c9b44b4a
--- /dev/null
+++ b/test/old-elf/abs-dup.objtxt
@@ -0,0 +1,19 @@
+# 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
new file mode 100644
index 000000000000..f542582bfa85
--- /dev/null
+++ b/test/old-elf/abs.test
@@ -0,0 +1,19 @@
+#
+# 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
new file mode 100644
index 000000000000..b2f263148b60
--- /dev/null
+++ b/test/old-elf/allowduplicates.objtxt
@@ -0,0 +1,41 @@
+# 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
new file mode 100644
index 000000000000..db5ba6cdfaa2
--- /dev/null
+++ b/test/old-elf/archive-elf-forceload.test
@@ -0,0 +1,43 @@
+# 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
new file mode 100644
index 000000000000..7784eb9279dc
--- /dev/null
+++ b/test/old-elf/archive-elf.test
@@ -0,0 +1,38 @@
+# 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
new file mode 100644
index 000000000000..bcebfbac2f24
--- /dev/null
+++ b/test/old-elf/as-needed.test
@@ -0,0 +1,15 @@
+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
new file mode 100644
index 000000000000..116fd0f07c5e
--- /dev/null
+++ b/test/old-elf/branch.test
@@ -0,0 +1,34 @@
+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
new file mode 100644
index 000000000000..3fc11728e12d
--- /dev/null
+++ b/test/old-elf/check.test
@@ -0,0 +1,39 @@
+# 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
new file mode 100644
index 000000000000..71304a443b8b
--- /dev/null
+++ b/test/old-elf/checkrodata.test
@@ -0,0 +1,9 @@
+
+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
new file mode 100644
index 000000000000..e337ac399140
--- /dev/null
+++ b/test/old-elf/common.test
@@ -0,0 +1,10 @@
+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
new file mode 100644
index 000000000000..0120aa126551
--- /dev/null
+++ b/test/old-elf/consecutive-weak-sym-defs.test
@@ -0,0 +1,81 @@
+#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
new file mode 100644
index 000000000000..7fdc20d4dd93
--- /dev/null
+++ b/test/old-elf/defsym.objtxt
@@ -0,0 +1,31 @@
+# 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
new file mode 100644
index 000000000000..7fca435008ab
--- /dev/null
+++ b/test/old-elf/discard-all.test
@@ -0,0 +1,88 @@
+# 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
new file mode 100644
index 000000000000..d1a0918949ad
--- /dev/null
+++ b/test/old-elf/discard-locals.test
@@ -0,0 +1,65 @@
+# 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
new file mode 100644
index 000000000000..e9143d83f0f6
--- /dev/null
+++ b/test/old-elf/dynamic-segorder.test
@@ -0,0 +1,17 @@
+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
new file mode 100644
index 000000000000..fc661684b19b
--- /dev/null
+++ b/test/old-elf/dynamic-undef.test
@@ -0,0 +1,38 @@
+#
+# 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
new file mode 100644
index 000000000000..2b548a7aaf5e
--- /dev/null
+++ b/test/old-elf/dynamic.test
@@ -0,0 +1,80 @@
+# 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
new file mode 100644
index 000000000000..74383b8dbc5b
--- /dev/null
+++ b/test/old-elf/eh_frame_hdr.test
@@ -0,0 +1,30 @@
+#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
new file mode 100644
index 000000000000..6590d139c417
--- /dev/null
+++ b/test/old-elf/entry.objtxt
@@ -0,0 +1,58 @@
+# 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
new file mode 100644
index 000000000000..b88961597ea0
--- /dev/null
+++ b/test/old-elf/export-dynamic.test
@@ -0,0 +1,98 @@
+# 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
new file mode 100644
index 000000000000..5020e9cf9b74
--- /dev/null
+++ b/test/old-elf/filenotfound.test
@@ -0,0 +1,3 @@
+# 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
new file mode 100644
index 000000000000..c05a06fab32b
--- /dev/null
+++ b/test/old-elf/gnulinkonce/gnulinkonce-report-discarded-reference.test
@@ -0,0 +1,145 @@
+# 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
new file mode 100644
index 000000000000..f91123f0efad
--- /dev/null
+++ b/test/old-elf/gnulinkonce/gnulinkonce-report-undef.test
@@ -0,0 +1,127 @@
+# 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
new file mode 100644
index 000000000000..eacd41d6ded5
--- /dev/null
+++ b/test/old-elf/gnulinkonce/gnulinkonce.test
@@ -0,0 +1,149 @@
+# 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
new file mode 100644
index 000000000000..b8695f1aedfb
--- /dev/null
+++ b/test/old-elf/gotpcrel.test
@@ -0,0 +1,21 @@
+# 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
new file mode 100644
index 000000000000..969874e538a5
--- /dev/null
+++ b/test/old-elf/gottpoff.test
@@ -0,0 +1,119 @@
+# 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
new file mode 100644
index 000000000000..1d7f5ee43367
--- /dev/null
+++ b/test/old-elf/group-cmd-search.test
@@ -0,0 +1,134 @@
+/*
+ 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
new file mode 100644
index 000000000000..98488b75ceb7
--- /dev/null
+++ b/test/old-elf/hexagon-quickdata-sort.test
@@ -0,0 +1,12 @@
+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
new file mode 100644
index 000000000000..d4d7d6a617e6
--- /dev/null
+++ b/test/old-elf/hexagon-quickdata-sortcommon.test
@@ -0,0 +1,16 @@
+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
new file mode 100644
index 000000000000..0aa317a24e6f
--- /dev/null
+++ b/test/old-elf/ifunc.test
@@ -0,0 +1,69 @@
+# 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
new file mode 100644
index 000000000000..aa03a2eb4e73
--- /dev/null
+++ b/test/old-elf/ignore-unknownoption.test
@@ -0,0 +1,5 @@
+# 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
new file mode 100644
index 000000000000..2b8bcb65c3e4
--- /dev/null
+++ b/test/old-elf/init_array-order.test
@@ -0,0 +1,67 @@
+#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
new file mode 100644
index 000000000000..f7f48445621e
--- /dev/null
+++ b/test/old-elf/init_array.test
@@ -0,0 +1,127 @@
+# 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
new file mode 100644
index 000000000000..f8571a637197
--- /dev/null
+++ b/test/old-elf/initfini-options.test-1.test
@@ -0,0 +1,33 @@
+# 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
new file mode 100644
index 000000000000..35361c76d973
--- /dev/null
+++ b/test/old-elf/initfini-options.test-2.test
@@ -0,0 +1,47 @@
+# 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
new file mode 100644
index 000000000000..2c9ab3cceb94
--- /dev/null
+++ b/test/old-elf/initfini-options.test-3.test
@@ -0,0 +1,53 @@
+# 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
new file mode 100644
index 000000000000..9b1b8f2cffc4
--- /dev/null
+++ b/test/old-elf/librarynotfound.test
@@ -0,0 +1,5 @@
+# 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
new file mode 100644
index 000000000000..8b07ae9d1a71
--- /dev/null
+++ b/test/old-elf/linker-as-ld.test
@@ -0,0 +1,16 @@
+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/elf/linkerscript/Inputs/externs.ls b/test/old-elf/linkerscript/Inputs/externs.ls
index 20fdc0c3f980..20fdc0c3f980 100644
--- a/test/elf/linkerscript/Inputs/externs.ls
+++ b/test/old-elf/linkerscript/Inputs/externs.ls
diff --git a/test/elf/linkerscript/Inputs/invalid.ls b/test/old-elf/linkerscript/Inputs/invalid.ls
index 894d4bef2732..894d4bef2732 100644
--- a/test/elf/linkerscript/Inputs/invalid.ls
+++ b/test/old-elf/linkerscript/Inputs/invalid.ls
diff --git a/test/old-elf/linkerscript/Inputs/prog1.o.yaml b/test/old-elf/linkerscript/Inputs/prog1.o.yaml
new file mode 100644
index 000000000000..f450048ab37b
--- /dev/null
+++ b/test/old-elf/linkerscript/Inputs/prog1.o.yaml
@@ -0,0 +1,87 @@
+---
+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
new file mode 100644
index 000000000000..4d1bbd5754ea
--- /dev/null
+++ b/test/old-elf/linkerscript/Inputs/prog2.o.yaml
@@ -0,0 +1,88 @@
+---
+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
new file mode 100644
index 000000000000..2402be4d42b6
--- /dev/null
+++ b/test/old-elf/linkerscript/Inputs/prog3.o.yaml
@@ -0,0 +1,51 @@
+---
+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
new file mode 100644
index 000000000000..f826034053c3
--- /dev/null
+++ b/test/old-elf/linkerscript/Inputs/simple-pic.o.yaml
@@ -0,0 +1,32 @@
+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
new file mode 100644
index 000000000000..fc9cd4c5f67d
--- /dev/null
+++ b/test/old-elf/linkerscript/Inputs/simple.o.yaml
@@ -0,0 +1,51 @@
+---
+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/elf/linkerscript/Inputs/valid.ls b/test/old-elf/linkerscript/Inputs/valid.ls
index 43593602d3fb..43593602d3fb 100644
--- a/test/elf/linkerscript/Inputs/valid.ls
+++ b/test/old-elf/linkerscript/Inputs/valid.ls
diff --git a/test/old-elf/linkerscript/externs.objtxt b/test/old-elf/linkerscript/externs.objtxt
new file mode 100644
index 000000000000..d79c56a142c9
--- /dev/null
+++ b/test/old-elf/linkerscript/externs.objtxt
@@ -0,0 +1,21 @@
+# 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
new file mode 100644
index 000000000000..9376d5a5cfb4
--- /dev/null
+++ b/test/old-elf/linkerscript/filename-with-wildcards.test
@@ -0,0 +1,49 @@
+/*
+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
new file mode 100644
index 000000000000..72d2edebb4d5
--- /dev/null
+++ b/test/old-elf/linkerscript/invalid-script-cli-1.test
@@ -0,0 +1,10 @@
+# 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
new file mode 100644
index 000000000000..cc76f0e55a81
--- /dev/null
+++ b/test/old-elf/linkerscript/invalid-script-cli-2.test
@@ -0,0 +1,6 @@
+# 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
new file mode 100644
index 000000000000..a00a200225dc
--- /dev/null
+++ b/test/old-elf/linkerscript/invalid.test
@@ -0,0 +1,5 @@
+# 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
new file mode 100644
index 000000000000..45baf188d8d8
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs-all-none.test
@@ -0,0 +1,26 @@
+/*
+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
new file mode 100644
index 000000000000..e3672cf8fd30
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs-custom-none.test
@@ -0,0 +1,36 @@
+/*
+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
new file mode 100644
index 000000000000..8c493d020504
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs-default.test
@@ -0,0 +1,82 @@
+/*
+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
new file mode 100644
index 000000000000..7fe14dd543d1
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs-different.test
@@ -0,0 +1,45 @@
+/*
+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
new file mode 100644
index 000000000000..3bf27dcb1f5a
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs-extra-program.test
@@ -0,0 +1,27 @@
+/*
+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
new file mode 100644
index 000000000000..0fac53e75302
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs-flags.test
@@ -0,0 +1,46 @@
+/*
+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
new file mode 100644
index 000000000000..83fe94c70614
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs-has-program.test
@@ -0,0 +1,33 @@
+/*
+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
new file mode 100644
index 000000000000..c1426e8ffa5f
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs-invalid.test
@@ -0,0 +1,63 @@
+/*
+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
new file mode 100644
index 000000000000..0fb669d818c4
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs-misplaced-program.test
@@ -0,0 +1,26 @@
+/*
+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
new file mode 100644
index 000000000000..e461d5061019
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs-no-program.test
@@ -0,0 +1,25 @@
+/*
+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
new file mode 100644
index 000000000000..a1c84e59fc60
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs-one-none.test
@@ -0,0 +1,36 @@
+/*
+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
new file mode 100644
index 000000000000..2a719a6cb296
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs-program-flags.test
@@ -0,0 +1,33 @@
+/*
+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
new file mode 100644
index 000000000000..373facc380ba
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs-program-good-phdrs.test
@@ -0,0 +1,34 @@
+/*
+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
new file mode 100644
index 000000000000..3e639bdb0f43
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs-program-no-phdrs.test
@@ -0,0 +1,26 @@
+/*
+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
new file mode 100644
index 000000000000..c27b23d85876
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs-program-wrong-phdrs.test
@@ -0,0 +1,26 @@
+/*
+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
new file mode 100644
index 000000000000..e39f61881033
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs-same-flags.test
@@ -0,0 +1,35 @@
+/*
+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
new file mode 100644
index 000000000000..92b3ad3909c3
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs-same.test
@@ -0,0 +1,36 @@
+/*
+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
new file mode 100644
index 000000000000..ac30df78d5e1
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs/sections-empty-phdrs.script
@@ -0,0 +1,11 @@
+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
new file mode 100644
index 000000000000..b8848cd3ab0d
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs/sections-no-phdrs.script
@@ -0,0 +1,7 @@
+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
new file mode 100644
index 000000000000..4b240245d2b2
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs/sections-none-phdrs.script
@@ -0,0 +1,11 @@
+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
new file mode 100644
index 000000000000..f92b452d2346
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs/undef-empty-phdrs.script
@@ -0,0 +1,11 @@
+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
new file mode 100644
index 000000000000..8ac56695f00a
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs/undef-id-phdrs.script
@@ -0,0 +1,12 @@
+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
new file mode 100644
index 000000000000..d3ee5bdebe41
--- /dev/null
+++ b/test/old-elf/linkerscript/phdrs/undef-no-phdrs.script
@@ -0,0 +1,7 @@
+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
new file mode 100644
index 000000000000..4d23f5eb9d54
--- /dev/null
+++ b/test/old-elf/linkerscript/sections-order.test
@@ -0,0 +1,113 @@
+/*
+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
new file mode 100644
index 000000000000..a390a2b2d36a
--- /dev/null
+++ b/test/old-elf/linkerscript/sections-with-wildcards.test
@@ -0,0 +1,88 @@
+/*
+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
new file mode 100644
index 000000000000..15b22f6f581f
--- /dev/null
+++ b/test/old-elf/linkerscript/symbol-definition-so.test
@@ -0,0 +1,32 @@
+/*
+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
new file mode 100644
index 000000000000..daa3b17e9965
--- /dev/null
+++ b/test/old-elf/linkerscript/symbol-definition.test
@@ -0,0 +1,54 @@
+/*
+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
new file mode 100644
index 000000000000..a7342c41f529
--- /dev/null
+++ b/test/old-elf/linkerscript/valid-script-cli.objtxt
@@ -0,0 +1,23 @@
+# 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
new file mode 100644
index 000000000000..f1b78558e9c5
--- /dev/null
+++ b/test/old-elf/loginputfiles.test
@@ -0,0 +1,28 @@
+# 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
new file mode 100644
index 000000000000..ec83ac2b8849
--- /dev/null
+++ b/test/old-elf/mergeatoms.test
@@ -0,0 +1,6 @@
+# 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
new file mode 100644
index 000000000000..719ae8a8b24e
--- /dev/null
+++ b/test/old-elf/mergeconstants.test
@@ -0,0 +1,20 @@
+# 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
new file mode 100644
index 000000000000..bf8dbf7593f0
--- /dev/null
+++ b/test/old-elf/mergeglobalatoms.test
@@ -0,0 +1,11 @@
+# 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
new file mode 100644
index 000000000000..4c5f79588dbe
--- /dev/null
+++ b/test/old-elf/no-unique-section-names.test
@@ -0,0 +1,19 @@
+# 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
new file mode 100644
index 000000000000..aff01c3e5b2a
--- /dev/null
+++ b/test/old-elf/note.test
@@ -0,0 +1,50 @@
+# 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
new file mode 100644
index 000000000000..6b56f17c677d
--- /dev/null
+++ b/test/old-elf/options/dynamic-linker.test
@@ -0,0 +1,17 @@
+# 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
new file mode 100644
index 000000000000..ec5edf0ad62e
--- /dev/null
+++ b/test/old-elf/options/target-specific-args.test
@@ -0,0 +1,5 @@
+# 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
new file mode 100644
index 000000000000..c8b3664d025f
--- /dev/null
+++ b/test/old-elf/phdr.test
@@ -0,0 +1,99 @@
+# 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
new file mode 100644
index 000000000000..85ad23d0b8e9
--- /dev/null
+++ b/test/old-elf/quickdata.test
@@ -0,0 +1,15 @@
+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
new file mode 100644
index 000000000000..f8cb056e03da
--- /dev/null
+++ b/test/old-elf/reloc.test
@@ -0,0 +1,38 @@
+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
new file mode 100644
index 000000000000..89e9ffd015bd
--- /dev/null
+++ b/test/old-elf/responsefile.test
@@ -0,0 +1,6 @@
+# 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
new file mode 100644
index 000000000000..12d9abb2a194
--- /dev/null
+++ b/test/old-elf/rodata.test
@@ -0,0 +1,5 @@
+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
new file mode 100644
index 000000000000..675dc3861867
--- /dev/null
+++ b/test/old-elf/rosegment.test
@@ -0,0 +1,26 @@
+# 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
new file mode 100644
index 000000000000..dff1a96b07ee
--- /dev/null
+++ b/test/old-elf/sectionGroups/sectiongroup-new-members.test
@@ -0,0 +1,151 @@
+# 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
new file mode 100644
index 000000000000..57707f84475e
--- /dev/null
+++ b/test/old-elf/sectionGroups/sectiongroup-simple.test
@@ -0,0 +1,144 @@
+# 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
new file mode 100644
index 000000000000..56595e59d8d6
--- /dev/null
+++ b/test/old-elf/sectionGroups/sectiongroup-undef-member-other.test
@@ -0,0 +1,156 @@
+# 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
new file mode 100644
index 000000000000..65e9ec7632bf
--- /dev/null
+++ b/test/old-elf/sectionGroups/sectiongroup-undef-member.test
@@ -0,0 +1,142 @@
+# 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
new file mode 100644
index 000000000000..9f8f80c23605
--- /dev/null
+++ b/test/old-elf/sectionGroups/sectiongroup-with-globalsymbols.test
@@ -0,0 +1,250 @@
+# 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
new file mode 100644
index 000000000000..0c5d65ad544f
--- /dev/null
+++ b/test/old-elf/sectionGroups/sectiongroup-with-undef-external-reference.test
@@ -0,0 +1,236 @@
+# 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
new file mode 100644
index 000000000000..83a69a3828b2
--- /dev/null
+++ b/test/old-elf/sectionGroups/sectiongroup-with-undef-signature.test
@@ -0,0 +1,219 @@
+# 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
new file mode 100644
index 000000000000..f36cad619186
--- /dev/null
+++ b/test/old-elf/sections.test
@@ -0,0 +1,142 @@
+# 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
new file mode 100644
index 000000000000..97ddd5f1030a
--- /dev/null
+++ b/test/old-elf/sh_addralign.test
@@ -0,0 +1,37 @@
+# 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
new file mode 100644
index 000000000000..c86fa3349b5f
--- /dev/null
+++ b/test/old-elf/shndx.test
@@ -0,0 +1,18 @@
+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
new file mode 100644
index 000000000000..b4dce9746d48
--- /dev/null
+++ b/test/old-elf/soname.test
@@ -0,0 +1,6 @@
+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
new file mode 100644
index 000000000000..62c16a91ee69
--- /dev/null
+++ b/test/old-elf/start-stop-sym.test
@@ -0,0 +1,108 @@
+# 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
new file mode 100644
index 000000000000..faf30349ec84
--- /dev/null
+++ b/test/old-elf/strip-all.test
@@ -0,0 +1,108 @@
+# 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
new file mode 100644
index 000000000000..ddf3b3899d10
--- /dev/null
+++ b/test/old-elf/stripped-empty.test
@@ -0,0 +1,4 @@
+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
new file mode 100644
index 000000000000..bcf399e86eb8
--- /dev/null
+++ b/test/old-elf/symbols.test
@@ -0,0 +1,33 @@
+# 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
new file mode 100644
index 000000000000..a7fd86cb7b43
--- /dev/null
+++ b/test/old-elf/tls-tbss-size.test
@@ -0,0 +1,176 @@
+# 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
new file mode 100644
index 000000000000..6fb33941a88c
--- /dev/null
+++ b/test/old-elf/tls.test
@@ -0,0 +1,43 @@
+# 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
new file mode 100644
index 000000000000..bcb089c504ed
--- /dev/null
+++ b/test/old-elf/tlsAddr.test
@@ -0,0 +1,7 @@
+# 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
new file mode 100644
index 000000000000..c19a0197061e
--- /dev/null
+++ b/test/old-elf/undef-from-dso-to-main.test
@@ -0,0 +1,52 @@
+# 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
new file mode 100644
index 000000000000..8722a55f672c
--- /dev/null
+++ b/test/old-elf/undef-from-main-dso.test
@@ -0,0 +1,43 @@
+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
new file mode 100644
index 000000000000..59d997edc64c
--- /dev/null
+++ b/test/old-elf/weaksym.test
@@ -0,0 +1,7 @@
+# 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
new file mode 100644
index 000000000000..427764970be8
--- /dev/null
+++ b/test/old-elf/wrap.test
@@ -0,0 +1,276 @@
+# 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
new file mode 100644
index 000000000000..c5572d0aa3a3
--- /dev/null
+++ b/test/old-elf/x86-64-dynamic-relocs.test
@@ -0,0 +1,26 @@
+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
new file mode 100644
index 000000000000..d957e6ee85ee
--- /dev/null
+++ b/test/old-elf/x86-64-dynamic.test
@@ -0,0 +1,79 @@
+# 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
new file mode 100644
index 000000000000..3bc4a6963a50
--- /dev/null
+++ b/test/old-elf/x86.test
@@ -0,0 +1,38 @@
+# 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
new file mode 100644
index 000000000000..111cea53bf0c
--- /dev/null
+++ b/test/old-elf/x86_64-kinds.test
@@ -0,0 +1,23 @@
+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
new file mode 100644
index 000000000000..274981bb1360
--- /dev/null
+++ b/test/old-elf/zoption_dtflags.test
@@ -0,0 +1,89 @@
+# 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/test/pecoff/Inputs/abs.obj.yaml b/test/pecoff/Inputs/abs.obj.yaml
deleted file mode 100644
index 65c3901ad8e7..000000000000
--- a/test/pecoff/Inputs/abs.obj.yaml
+++ /dev/null
@@ -1,11 +0,0 @@
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: []
-sections:
-symbols:
- - Name: _abs_value
- Value: 0xDEADBEEF
- SectionNumber: -1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
diff --git a/test/pecoff/Inputs/alignment.obj.yaml b/test/pecoff/Inputs/alignment.obj.yaml
deleted file mode 100644
index 1b12da0e6bad..000000000000
--- a/test/pecoff/Inputs/alignment.obj.yaml
+++ /dev/null
@@ -1,103 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 256
- SectionData: CC
- - Name: .text$1
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4096
- SectionData: 00
- - Name: .data$1
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: 00
- - Name: .data$2
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: 11
- - Name: .data$3
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 0
- SectionData: 22
- - Name: .bss$1
- Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 16
- SectionData: 0000
- - Name: .bss$2
- Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 16
- SectionData: 0000
- - Name: .yyy
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4096
- SectionData: 0000
- - Name: .zzz
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 16384
- SectionData: 0000
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .text$1
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .data$1
- Value: 0
- SectionNumber: 3
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .data$2
- Value: 0
- SectionNumber: 4
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .data$3
- Value: 0
- SectionNumber: 5
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: _start
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: .bss$1
- Value: 0
- SectionNumber: 6
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .bss$2
- Value: 0
- SectionNumber: 7
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .foo
- Value: 0
- SectionNumber: 8
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .bar
- Value: 0
- SectionNumber: 9
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
-...
diff --git a/test/pecoff/Inputs/alternatename1.obj.yaml b/test/pecoff/Inputs/alternatename1.obj.yaml
deleted file mode 100644
index dac18a8ef595..000000000000
--- a/test/pecoff/Inputs/alternatename1.obj.yaml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 1
- SectionData: 90909090
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: _foo
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/alternatename2.obj.yaml b/test/pecoff/Inputs/alternatename2.obj.yaml
deleted file mode 100644
index 5b70bfced6a1..000000000000
--- a/test/pecoff/Inputs/alternatename2.obj.yaml
+++ /dev/null
@@ -1,23 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: CCCCCCCC
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: _main
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/alternatename3.obj.yaml b/test/pecoff/Inputs/alternatename3.obj.yaml
deleted file mode 100644
index 1865653ea668..000000000000
--- a/test/pecoff/Inputs/alternatename3.obj.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 1
- SectionData: 90909090
- - Name: .drectve
- Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
- Alignment: 2147483648
- SectionData: 2F616C7465726E6174656E616D653A5F6D61696E3D5F666F6F00
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: _foo
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: .drectve
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 13
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
-...
diff --git a/test/pecoff/Inputs/armnt-ImageBase.obj.yaml b/test/pecoff/Inputs/armnt-ImageBase.obj.yaml
deleted file mode 100644
index 69cd530253b0..000000000000
--- a/test/pecoff/Inputs/armnt-ImageBase.obj.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_ARMNT
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 7047FEDE00000000
- Relocations:
- - VirtualAddress: 4
- SymbolName: __ImageBase
- Type: 1
-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: 1
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 1
- - Name: mainCRTStartup
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: __ImageBase
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/armnt-ImageBase.s b/test/pecoff/Inputs/armnt-ImageBase.s
deleted file mode 100644
index a17458eddb15..000000000000
--- a/test/pecoff/Inputs/armnt-ImageBase.s
+++ /dev/null
@@ -1,16 +0,0 @@
-
- .syntax unified
- .thumb
- .text
-
- .def mainCRTStartup
- .type 32
- .scl 2
- .endef
- .align 2
- .thumb_func
-mainCRTStartup:
- bx lr
- trap
- .long __ImageBase
-
diff --git a/test/pecoff/Inputs/armnt-addr32-exec.obj.yaml b/test/pecoff/Inputs/armnt-addr32-exec.obj.yaml
deleted file mode 100644
index b550f58c03e6..000000000000
--- a/test/pecoff/Inputs/armnt-addr32-exec.obj.yaml
+++ /dev/null
@@ -1,55 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_ARMNT
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: '7047'
- - Name: .rdata
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: '00000000'
- Relocations:
- - VirtualAddress: 0
- SymbolName: function
- Type: 1
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 2
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 1
- - Name: .rdata
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 4
- NumberOfRelocations: 1
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 2
- - Name: function
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: fps
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/armnt-addr32-exec.s b/test/pecoff/Inputs/armnt-addr32-exec.s
deleted file mode 100644
index 6a0776de7dd3..000000000000
--- a/test/pecoff/Inputs/armnt-addr32-exec.s
+++ /dev/null
@@ -1,24 +0,0 @@
-
-# __declspec(dllexport) void function(void) { }
-# const void * const fps[] = { &function, };
-
- .syntax unified
- .thumb
- .text
-
- .def function
- .scl 2
- .type 32
- .endef
- .global function
- .align 2
- .thumb_func
-function:
- bx lr
-
- .section .rdata,"rd"
- .global fps
- .align 2
-fps:
- .long function
-
diff --git a/test/pecoff/Inputs/armnt-addr32.obj.yaml b/test/pecoff/Inputs/armnt-addr32.obj.yaml
deleted file mode 100644
index 62ae2c6ea992..000000000000
--- a/test/pecoff/Inputs/armnt-addr32.obj.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_ARMNT
- Characteristics: [ ]
-sections:
- - Name: .rdata
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: '0000000000000000'
- Relocations:
- - VirtualAddress: 0
- SymbolName: i
- Type: 1
-symbols:
- - Name: .rdata
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 8
- NumberOfRelocations: 1
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 1
- - Name: i
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: is
- Value: 4
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/armnt-addr32.s b/test/pecoff/Inputs/armnt-addr32.s
deleted file mode 100644
index c718e9518af9..000000000000
--- a/test/pecoff/Inputs/armnt-addr32.s
+++ /dev/null
@@ -1,18 +0,0 @@
-
-@ static const int i = 0;
-@ const int * const is[] = { &i, };
-
- .syntax unified
- .thumb
- .text
-
- .section .rdata,"rd"
- .align 2 # @i
-i:
- .long 0 # 0x0
-
- .global is # @is
- .align 2
-is:
- .long i
-
diff --git a/test/pecoff/Inputs/armnt-blx23t.obj.yaml b/test/pecoff/Inputs/armnt-blx23t.obj.yaml
deleted file mode 100644
index 03f82609f4e6..000000000000
--- a/test/pecoff/Inputs/armnt-blx23t.obj.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_ARMNT
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 704700BF2DE90048EB46202000F000F80130BDE80088
- Relocations:
- - VirtualAddress: 12
- SymbolName: identity
- Type: 21
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 22
- NumberOfRelocations: 1
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 1
- - Name: identity
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: function
- Value: 4
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/armnt-blx23t.s b/test/pecoff/Inputs/armnt-blx23t.s
deleted file mode 100644
index 89aa4194faae..000000000000
--- a/test/pecoff/Inputs/armnt-blx23t.s
+++ /dev/null
@@ -1,33 +0,0 @@
-
-# __declspec(noinline) int identity(int i) { return i; }
-# int function() { return identity(32) + 1; }
-
- .syntax unified
- .thumb
- .text
-
- .def identity
- .scl 2
- .type 32
- .endef
- .global identity
- .align 2
- .thumb_func
-identity:
- bx lr
-
- .def function
- .scl 2
- .type 32
- .endef
- .global function
- .align 2
- .thumb_func
-function:
- push.w {r11, lr}
- mov r11, sp
- movs r0, 32
- bl identity
- adds r0, 1
- pop.w {r11, pc}
-
diff --git a/test/pecoff/Inputs/armnt-branch24t.obj.yaml b/test/pecoff/Inputs/armnt-branch24t.obj.yaml
deleted file mode 100644
index 02815a4957dd..000000000000
--- a/test/pecoff/Inputs/armnt-branch24t.obj.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_ARMNT
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 704700BF202000F000B8
- Relocations:
- - VirtualAddress: 6
- SymbolName: identity
- Type: 20
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 10
- NumberOfRelocations: 1
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 1
- - Name: identity
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: function
- Value: 4
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/armnt-branch24t.s b/test/pecoff/Inputs/armnt-branch24t.s
deleted file mode 100644
index 8d85cbe0cab2..000000000000
--- a/test/pecoff/Inputs/armnt-branch24t.s
+++ /dev/null
@@ -1,26 +0,0 @@
-
-# int ___declspec(noinline) identity(int i) { return i; }
-# int function(void) { return identity(32); }
-
- .syntax unified
- .thumb
- .text
-
- .def identity
- .scl 2
- .type 32
- .endef
- .global identity
- .align 2
- .thumb_func
-identity:
- bx lr
-
- .def function
- .scl 2
- .type 32
- .endef
-function:
- movs r0, 32
- b identity
-
diff --git a/test/pecoff/Inputs/armnt-exports.def b/test/pecoff/Inputs/armnt-exports.def
deleted file mode 100644
index afb8258f95bc..000000000000
--- a/test/pecoff/Inputs/armnt-exports.def
+++ /dev/null
@@ -1,4 +0,0 @@
-LIBRARY "armnt-exports"
-EXPORTS
- function
-
diff --git a/test/pecoff/Inputs/armnt-exports.obj.yaml b/test/pecoff/Inputs/armnt-exports.obj.yaml
deleted file mode 100644
index 2a971db2fdaa..000000000000
--- a/test/pecoff/Inputs/armnt-exports.obj.yaml
+++ /dev/null
@@ -1,35 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_ARMNT
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 704700BF7047
-symbols:
- - Name: .text
- 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: 1
- - Name: function
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _DllMainCRTStartup
- Value: 4
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/armnt-import.obj.yaml b/test/pecoff/Inputs/armnt-import.obj.yaml
deleted file mode 100644
index 08876eeb0d4c..000000000000
--- a/test/pecoff/Inputs/armnt-import.obj.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_ARMNT
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 40F20000C0F2000000680047
- Relocations:
- - VirtualAddress: 0
- SymbolName: __imp_function
- Type: 17
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 12
- NumberOfRelocations: 1
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 1
- - Name: mainCRTStartup
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: __imp_function
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/armnt-import.s b/test/pecoff/Inputs/armnt-import.s
deleted file mode 100644
index 2790d0edc8d9..000000000000
--- a/test/pecoff/Inputs/armnt-import.s
+++ /dev/null
@@ -1,21 +0,0 @@
-
-# void __declspec(dllimport) function(void);
-# int mainCRTStartup(void) { return function(); }
-
- .syntax unified
- .thumb
- .text
-
- .def mainCRTStartup
- .scl 2
- .type 32
- .endef
- .global mainCRTStartup
- .align 2
- .thumb_func
-mainCRTStartup:
- movw r0, :lower16:__imp_function
- movt r0, :upper16:__imp_function
- ldr r0, [r0]
- bx r0
-
diff --git a/test/pecoff/Inputs/armnt-mov32t-exec.obj.yaml b/test/pecoff/Inputs/armnt-mov32t-exec.obj.yaml
deleted file mode 100644
index a4630bcb9e0e..000000000000
--- a/test/pecoff/Inputs/armnt-mov32t-exec.obj.yaml
+++ /dev/null
@@ -1,39 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_ARMNT
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 704700BF40F20000C0F200007047
- Relocations:
- - VirtualAddress: 4
- SymbolName: function
- Type: 17
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 14
- NumberOfRelocations: 1
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 1
- - Name: function
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: get_function
- Value: 4
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/armnt-mov32t-exec.s b/test/pecoff/Inputs/armnt-mov32t-exec.s
deleted file mode 100644
index 10a20f468c34..000000000000
--- a/test/pecoff/Inputs/armnt-mov32t-exec.s
+++ /dev/null
@@ -1,30 +0,0 @@
-
-# void function(void) { }
-# void *get_function() { return &function; }
-
- .syntax unified
- .thumb
- .text
-
- .def function
- .scl 2
- .type 32
- .endef
- .global function
- .align 2
- .thumb_func
-function:
- bx lr
-
- .def get_function
- .scl 2
- .type 32
- .endef
- .global get_function
- .align 2
- .thumb_func
-get_function:
- movw r0, :lower16:function
- movt r0, :upper16:function
- bx lr
-
diff --git a/test/pecoff/Inputs/armnt-mov32t.obj.yaml b/test/pecoff/Inputs/armnt-mov32t.obj.yaml
deleted file mode 100644
index 21e890ace28f..000000000000
--- a/test/pecoff/Inputs/armnt-mov32t.obj.yaml
+++ /dev/null
@@ -1,55 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_ARMNT
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 40F20000C0F200007047
- Relocations:
- - VirtualAddress: 0
- SymbolName: buffer
- Type: 17
- - Name: .rdata
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
- Alignment: 1
- SectionData: '62756666657200'
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 10
- NumberOfRelocations: 1
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 1
- - Name: .rdata
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 7
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 2
- - Name: get_buffer
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: buffer
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
-...
diff --git a/test/pecoff/Inputs/armnt-mov32t.s b/test/pecoff/Inputs/armnt-mov32t.s
deleted file mode 100644
index 289f917597d6..000000000000
--- a/test/pecoff/Inputs/armnt-mov32t.s
+++ /dev/null
@@ -1,24 +0,0 @@
-
-# static const char buffer[] = "buffer";
-# const char *get_buffer() { return buffer; }
-
- .syntax unified
- .thumb
- .text
-
- .def get_buffer
- .scl 2
- .type 32
- .endef
- .global get_buffer
- .align 2
- .thumb_func
-get_buffer:
- movw r0, :lower16:buffer
- movt r0, :upper16:buffer
- bx lr
-
- .section .rdata,"rd"
-buffer:
- .asciz "buffer"
-
diff --git a/test/pecoff/Inputs/armnt-obj.s b/test/pecoff/Inputs/armnt-obj.s
deleted file mode 100644
index 20eeab0e1dda..000000000000
--- a/test/pecoff/Inputs/armnt-obj.s
+++ /dev/null
@@ -1,12 +0,0 @@
-
- .syntax unified
- .thumb
- .text
-
- .def main
- .scl 2
- .type 32
- .endef
-main:
- bx lr
-
diff --git a/test/pecoff/Inputs/armnt-obj.yaml b/test/pecoff/Inputs/armnt-obj.yaml
deleted file mode 100644
index 7c53c6f00693..000000000000
--- a/test/pecoff/Inputs/armnt-obj.yaml
+++ /dev/null
@@ -1,29 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_ARMNT
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: '7047'
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 2
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 1
- - 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/pecoff/Inputs/associative1.obj.yaml b/test/pecoff/Inputs/associative1.obj.yaml
deleted file mode 100644
index 51a7be0b34d7..000000000000
--- a/test/pecoff/Inputs/associative1.obj.yaml
+++ /dev/null
@@ -1,53 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: []
-sections:
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: 00000000
- - Name: '.CRT$XCU'
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 77777777
-symbols:
- - Name: .data
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 4
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- Selection: IMAGE_COMDAT_SELECT_ANY
- - Name: _var
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: '.CRT$XCU'
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 4
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 1
- Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE
- - Name: _init
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/associative3.obj.yaml b/test/pecoff/Inputs/associative3.obj.yaml
deleted file mode 100644
index ffea761a357c..000000000000
--- a/test/pecoff/Inputs/associative3.obj.yaml
+++ /dev/null
@@ -1,33 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: []
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 0000000000000000
- Relocations:
- - VirtualAddress: 4
- SymbolName: _var
- Type: IMAGE_REL_I386_DIR32
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: _main
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _var
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/basereloc.obj.yaml b/test/pecoff/Inputs/basereloc.obj.yaml
deleted file mode 100644
index 5e5ca16a0ac7..000000000000
--- a/test/pecoff/Inputs/basereloc.obj.yaml
+++ /dev/null
@@ -1,164 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4096
- SectionData: B800000000506800000000680000000050E80000000050E80000000050E800000000
- Relocations:
- - VirtualAddress: 0
- SymbolName: abs_symbol
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 7
- SymbolName: caption
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 12
- SymbolName: message
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 18
- SymbolName: _MessageBoxA@16
- Type: IMAGE_REL_I386_REL32
- - VirtualAddress: 24
- SymbolName: _ExitProcess@4
- Type: IMAGE_REL_I386_REL32
- - VirtualAddress: 30
- SymbolName: ___ImageBase
- Type: IMAGE_REL_I386_DIR32
- - Name: .text2
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4096
- SectionData: B800000000506800000000680000000050E80000000050E80000000050E800000000
- Relocations:
- - VirtualAddress: 0
- SymbolName: abs_symbol
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 7
- SymbolName: caption
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 12
- SymbolName: message
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 18
- SymbolName: _MessageBoxA@16
- Type: IMAGE_REL_I386_REL32
- - VirtualAddress: 24
- SymbolName: _ExitProcess@4
- Type: IMAGE_REL_I386_REL32
- - VirtualAddress: 30
- SymbolName: ___ImageBase
- Type: IMAGE_REL_I386_DIR32
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: 48656C6C6F0048656C6C6F20576F726C6400
- - Name: .drectve
- Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
- Alignment: 2147483648
- SectionData: 2F454E5452593A6D61696E20
-symbols:
- - Name: "@comp.id"
- Value: 10394907
- SectionNumber: 65535
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 28
- NumberOfRelocations: 6
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: .text2
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 28
- NumberOfRelocations: 6
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: .data
- Value: 0
- SectionNumber: 3
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 18
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: _MessageBoxA@16
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _ExitProcess@4
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: message
- Value: 6
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: _main
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: caption
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .drectve
- Value: 0
- SectionNumber: 3
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 12
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: .file
- Value: 0
- SectionNumber: 65534
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- File: "hello.c"
- - Name: abs_symbol
- Value: 0xDEADBEEF
- SectionNumber: -1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: ___ImageBase
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/bss.asm b/test/pecoff/Inputs/bss.asm
deleted file mode 100644
index 802edee8591d..000000000000
--- a/test/pecoff/Inputs/bss.asm
+++ /dev/null
@@ -1,20 +0,0 @@
-.586
-.model flat, c
-
-extern ExitProcess@4 : PROC
-
-_BSS SEGMENT
- _x DD 064H DUP (?)
- _y DD 064H DUP (?)
-_BSS ENDS
-
-.code
-start:
- mov eax, 42
- mov _x, eax
- mov eax, _x
- push eax
- call ExitProcess@4
-end start
-
-end
diff --git a/test/pecoff/Inputs/bss.obj b/test/pecoff/Inputs/bss.obj
deleted file mode 100644
index 3c00dfeb830b..000000000000
--- a/test/pecoff/Inputs/bss.obj
+++ /dev/null
Binary files differ
diff --git a/test/pecoff/Inputs/comdat.obj.yaml b/test/pecoff/Inputs/comdat.obj.yaml
deleted file mode 100644
index 5537499873a3..000000000000
--- a/test/pecoff/Inputs/comdat.obj.yaml
+++ /dev/null
@@ -1,53 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: 558BEC33C05DC3
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: 558BEC33C05DC3
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 7
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 2532800969
- Number: 0
- Selection: IMAGE_COMDAT_SELECT_ANY
- - Name: .text
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 7
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 2532800969
- Number: 0
- Selection: IMAGE_COMDAT_SELECT_ANY
- - Name: "?inlinefn1@@YAHXZ"
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: "?inlinefn2@@YAHXZ"
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/common-symbol.obj.yaml b/test/pecoff/Inputs/common-symbol.obj.yaml
deleted file mode 100644
index 05ddd022f286..000000000000
--- a/test/pecoff/Inputs/common-symbol.obj.yaml
+++ /dev/null
@@ -1,85 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_AMD64
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: b800000000b800000000b800000000b800000000b800000000
- Relocations:
- - VirtualAddress: 1
- SymbolName: _bssdata4
- Type: IMAGE_REL_AMD64_ADDR32
- - VirtualAddress: 6
- SymbolName: _bsspad1
- Type: IMAGE_REL_AMD64_ADDR32
- - VirtualAddress: 11
- SymbolName: _bssdata64
- Type: IMAGE_REL_AMD64_ADDR32
- - VirtualAddress: 16
- SymbolName: _bsspad2
- Type: IMAGE_REL_AMD64_ADDR32
- - VirtualAddress: 21
- SymbolName: _bssdata16
- Type: IMAGE_REL_AMD64_ADDR32
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: 03000000
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 0
- NumberOfRelocations: 5
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: .data
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 4
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: _bssdata4
- Value: 4
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _bsspad1
- Value: 1
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _bssdata64
- Value: 64
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _bsspad2
- Value: 1
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _bssdata16
- Value: 16
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/drectve.obj.yaml b/test/pecoff/Inputs/drectve.obj.yaml
deleted file mode 100644
index 22ec63f96e3e..000000000000
--- a/test/pecoff/Inputs/drectve.obj.yaml
+++ /dev/null
@@ -1,79 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: 558BEC56FF15000000008B0D000000008B3103F0FF150000000003C65E5DC3
- Relocations:
- - VirtualAddress: 6
- SymbolName: __imp__fn
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 12
- SymbolName: __imp__var
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 22
- SymbolName: __imp___name_with_underscore
- Type: IMAGE_REL_I386_DIR32
- - Name: .drectve
- Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
- Alignment: 2147483648
- SectionData: 2f64656661756c746c69623a766172732e6c6962202f73756273797374656d3a636f6e736f6c652c34322e313935202d3f666f6f00
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 31
- NumberOfRelocations: 3
- NumberOfLinenumbers: 0
- CheckSum: 3595596940
- Number: 0
- - Name: __imp__fn
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: __imp___name_with_underscore
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _main
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: __imp__var
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _fn
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: .drectve
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 13
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
-...
diff --git a/test/pecoff/Inputs/drectve2.obj.yaml b/test/pecoff/Inputs/drectve2.obj.yaml
deleted file mode 100644
index 836cbc3e743d..000000000000
--- a/test/pecoff/Inputs/drectve2.obj.yaml
+++ /dev/null
@@ -1,45 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: 558BEC56FF15000000008B0D000000008B3103F0FF150000000003C65E5DC3
- - Name: .drectve
- Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
- Alignment: 2147483648
- SectionData: 2f696e636c7564653a666f6f00
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 31
- NumberOfRelocations: 3
- NumberOfLinenumbers: 0
- CheckSum: 3595596940
- Number: 0
- - Name: _main
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: .drectve
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 13
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
-...
diff --git a/test/pecoff/Inputs/drectve3.lib b/test/pecoff/Inputs/drectve3.lib
deleted file mode 100644
index c295d1ff6d04..000000000000
--- a/test/pecoff/Inputs/drectve3.lib
+++ /dev/null
Binary files differ
diff --git a/test/pecoff/Inputs/entry.obj.yaml b/test/pecoff/Inputs/entry.obj.yaml
deleted file mode 100644
index 35eae143c430..000000000000
--- a/test/pecoff/Inputs/entry.obj.yaml
+++ /dev/null
@@ -1,40 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: A100000000030500000000C3
-
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
-
- - Name: _foo
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-
- - Name: _bar
- Value: 4
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-
- - Name: "?baz@@YAXXZ"
- Value: 4
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/executable.obj.yaml b/test/pecoff/Inputs/executable.obj.yaml
deleted file mode 100644
index 73ba0fe71914..000000000000
--- a/test/pecoff/Inputs/executable.obj.yaml
+++ /dev/null
@@ -1,29 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_ARMNT
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: '7047'
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 2
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 1
- - Name: mainCRTStartup
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/executable.s b/test/pecoff/Inputs/executable.s
deleted file mode 100644
index 1c58f7331b26..000000000000
--- a/test/pecoff/Inputs/executable.s
+++ /dev/null
@@ -1,17 +0,0 @@
-
-# void mainCRTStartup(){}
-
- .syntax unified
- .thumb
- .text
-
- .def mainCRTStartup
- .scl 2
- .type 32
- .endef
- .global mainCRTStartup
- .align 2
- .thumb_func
-mainCRTStartup:
- bx lr
-
diff --git a/test/pecoff/Inputs/export.obj.yaml b/test/pecoff/Inputs/export.obj.yaml
deleted file mode 100644
index fa92cd09bee4..000000000000
--- a/test/pecoff/Inputs/export.obj.yaml
+++ /dev/null
@@ -1,69 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: []
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: B800000000506800000000680000000050E80000000050E800000000
- - Name: .drectve
- Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
- Alignment: 2147483648
- SectionData: 2f6578706f72743a5f6578706f7274666e334032353600 # /export:_exportfn3@256
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 28
- NumberOfRelocations: 4
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: _init
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _exportfn1
- Value: 8
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _exportfn2
- Value: 16
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _exportfn3@256
- Value: 16
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _exportfn6
- Value: 16
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _exportfn7@8
- Value: 16
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: "?exportfn8@@YAXXZ"
- Value: 16
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/exports.def b/test/pecoff/Inputs/exports.def
deleted file mode 100644
index 7b444f9719d1..000000000000
--- a/test/pecoff/Inputs/exports.def
+++ /dev/null
@@ -1,6 +0,0 @@
-; This is a comment line
-
-EXPORTS
- exportfn1 @5 ; foo
- exportfn2
- exportfn5=exportfn6 PRIVATE
diff --git a/test/pecoff/Inputs/exports2.def b/test/pecoff/Inputs/exports2.def
deleted file mode 100644
index 1c95f42ceb60..000000000000
--- a/test/pecoff/Inputs/exports2.def
+++ /dev/null
@@ -1,6 +0,0 @@
-; This is a comment line
-
-EXPORTS
- exportfn1 @5 ; foo
- exportfn7
- exportfn5=exportfn6 PRIVATE
diff --git a/test/pecoff/Inputs/grouped-sections.asm b/test/pecoff/Inputs/grouped-sections.asm
deleted file mode 100644
index af69363efefb..000000000000
--- a/test/pecoff/Inputs/grouped-sections.asm
+++ /dev/null
@@ -1,18 +0,0 @@
-.386
-.model flat, c
-
-_data$2 SEGMENT BYTE alias(".data$2")
- db "orld", 0
-_data$2 ends
-
-_data$1 SEGMENT BYTE alias(".data$1")
- db "o, w"
-_data$1 ends
-
-.data
- db "Hell"
-
-.code
-main:
- nop
-end main
diff --git a/test/pecoff/Inputs/grouped-sections.obj.yaml b/test/pecoff/Inputs/grouped-sections.obj.yaml
deleted file mode 100644
index 2180312acf92..000000000000
--- a/test/pecoff/Inputs/grouped-sections.obj.yaml
+++ /dev/null
@@ -1,83 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 90
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: 48656C6C
- - Name: ".data$2"
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 1
- SectionData: 6F726C6400
- - Name: ".data$1"
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 1
- SectionData: 6F2C2077
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 1
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: .data
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 4
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: ".data$2"
- Value: 0
- SectionNumber: 3
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 5
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: ".data$1"
- Value: 0
- SectionNumber: 4
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 4
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: foo
- Value: 2
- SectionNumber: 4
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: _main
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/hello.asm b/test/pecoff/Inputs/hello.asm
deleted file mode 100644
index e360bbf65706..000000000000
--- a/test/pecoff/Inputs/hello.asm
+++ /dev/null
@@ -1,24 +0,0 @@
-;;; ml hello.asm /link /subsystem:windows /defaultlib:kernel32.lib \
-;;; /defaultlib:user32.lib /out:hello.exe /entry:main
-
-.386
-.model flat, c
-
-extern MessageBoxA@16 : PROC
-extern ExitProcess@4 : PROC
-
-.data
- caption db "Hello", 0
- message db "Hello World", 0
-
-.code
-main:
- mov eax, 0
- push eax
- push offset caption
- push offset message
- push eax
- call MessageBoxA@16
- push eax
- call ExitProcess@4
-end main
diff --git a/test/pecoff/Inputs/hello.obj.yaml b/test/pecoff/Inputs/hello.obj.yaml
deleted file mode 100644
index 6268a74057bd..000000000000
--- a/test/pecoff/Inputs/hello.obj.yaml
+++ /dev/null
@@ -1,111 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: B800000000506800000000680000000050E80000000050E800000000
- Relocations:
- - VirtualAddress: 7
- SymbolName: caption
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 12
- SymbolName: message
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 18
- SymbolName: _MessageBoxA@16
- Type: IMAGE_REL_I386_REL32
- - VirtualAddress: 24
- SymbolName: _ExitProcess@4
- Type: IMAGE_REL_I386_REL32
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: 48656C6C6F0048656C6C6F20576F726C6400
- - Name: .drectve
- Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
- Alignment: 2147483648
- SectionData: 2F454E5452593A6D61696E20
-symbols:
- - Name: "@comp.id"
- Value: 10394907
- SectionNumber: 65535
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 28
- NumberOfRelocations: 4
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: .data
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 18
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: _MessageBoxA@16
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _ExitProcess@4
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: message
- Value: 6
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: _main
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: caption
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .drectve
- Value: 0
- SectionNumber: 3
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 12
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: .file
- Value: 0
- SectionNumber: 65534
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- File: "hello.c"
-...
diff --git a/test/pecoff/Inputs/hello64.asm b/test/pecoff/Inputs/hello64.asm
deleted file mode 100644
index bc1a41b500d0..000000000000
--- a/test/pecoff/Inputs/hello64.asm
+++ /dev/null
@@ -1,22 +0,0 @@
-;; ml hello64.asm /link /subsystem:windows /defaultlib:kernel32 \
-;; /defaultlib:user32 /out:hello64.exe /entry:main
-
-extern ExitProcess : PROC
-extern MessageBoxA : PROC
-
-.data
- caption db 'Hello', 0
- message db 'Hello World', 0
-
-.code
-main PROC
- sub rsp,28h
- mov rcx, 0
- lea rdx, message
- lea r8, caption
- mov r9d, 0
- call MessageBoxA
- mov ecx, 0
- call ExitProcess
-main ENDP
-END
diff --git a/test/pecoff/Inputs/hello64.obj.yaml b/test/pecoff/Inputs/hello64.obj.yaml
deleted file mode 100644
index 36b699623101..000000000000
--- a/test/pecoff/Inputs/hello64.obj.yaml
+++ /dev/null
@@ -1,110 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_AMD64
- Characteristics: [ ]
-sections:
- - Name: '.text$mn'
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: 4883EC2848C7C100000000488D15000000004C8D050000000041B900000000E800000000B900000000E800000000
- Relocations:
- - VirtualAddress: 14
- SymbolName: message
- Type: IMAGE_REL_AMD64_REL32
- - VirtualAddress: 21
- SymbolName: caption
- Type: IMAGE_REL_AMD64_REL32
- - VirtualAddress: 32
- SymbolName: MessageBoxA
- Type: IMAGE_REL_AMD64_REL32
- - VirtualAddress: 42
- SymbolName: ExitProcess
- Type: IMAGE_REL_AMD64_REL32
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 16
- SectionData: 48656C6C6F0048656C6C6F20576F726C6400
- - Name: '.debug$S'
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
- Alignment: 1
- SectionData: 04000000F1000000830000004800011100000000433A5C63796777696E5C686F6D655C727569755C6C6C766D5C746F6F6C735C6C6C645C746573745C7065636F66665C496E707574735C68656C6C6F36342E6F626A0037003C1103020000D00000000000000000000C0000000D5201004D6963726F736F667420285229204D6163726F20417373656D626C6572000000
-symbols:
- - Name: '@comp.id'
- Value: 14635533
- SectionNumber: 65535
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: '@feat.00'
- Value: 16
- SectionNumber: 65535
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: '.text$mn'
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 46
- NumberOfRelocations: 4
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: .data
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 18
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: '.debug$S'
- Value: 0
- SectionNumber: 3
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 144
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: ExitProcess
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: MessageBoxA
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: message
- Value: 6
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: caption
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - 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/pecoff/Inputs/hello64lib.asm b/test/pecoff/Inputs/hello64lib.asm
deleted file mode 100644
index 89f95cd49af1..000000000000
--- a/test/pecoff/Inputs/hello64lib.asm
+++ /dev/null
@@ -1,14 +0,0 @@
-.code
-ExitProcess PROC
- RET
-ExitProcess ENDP
-
-MessageBoxA PROC
- RET
-MessageBoxA ENDP
-
-_DllMainCRTStartup PROC
- RET
-_DllMainCRTStartup ENDP
-
-END
diff --git a/test/pecoff/Inputs/hello64lib.lib b/test/pecoff/Inputs/hello64lib.lib
deleted file mode 100644
index 3109c32593ca..000000000000
--- a/test/pecoff/Inputs/hello64lib.lib
+++ /dev/null
Binary files differ
diff --git a/test/pecoff/Inputs/imagebase.obj.yaml b/test/pecoff/Inputs/imagebase.obj.yaml
deleted file mode 100644
index e31e744fa058..000000000000
--- a/test/pecoff/Inputs/imagebase.obj.yaml
+++ /dev/null
@@ -1,55 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: A100000000C3
- Relocations:
- - VirtualAddress: 1
- SymbolName: ___ImageBase
- Type: IMAGE_REL_I386_DIR32
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 16
- SectionData: ""
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 6
- NumberOfRelocations: 1
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: .data
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 0
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: ___ImageBase
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: __start
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/machine-type-unknown.obj.yaml b/test/pecoff/Inputs/machine-type-unknown.obj.yaml
deleted file mode 100644
index f0da1ea7ac34..000000000000
--- a/test/pecoff/Inputs/machine-type-unknown.obj.yaml
+++ /dev/null
@@ -1,38 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_UNKNOWN
- Characteristics: []
-sections:
- - Name: .drectve
- Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
- Alignment: 2147483648
- SectionData: ''
-symbols:
- - Name: '@comp.id'
- Value: 1
- SectionNumber: 65535
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: '@feat.00'
- Value: 1
- SectionNumber: 65535
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: __imp___close
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: __imp__close
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_WEAK_EXTERNAL
- WeakExternal:
- TagIndex: 2
- Characteristics: IMAGE_WEAK_EXTERN_SEARCH_ALIAS
-...
diff --git a/test/pecoff/Inputs/main.obj.yaml b/test/pecoff/Inputs/main.obj.yaml
deleted file mode 100644
index 73a788049063..000000000000
--- a/test/pecoff/Inputs/main.obj.yaml
+++ /dev/null
@@ -1,70 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: A100000000030500000000C3
- Relocations:
- - VirtualAddress: 1
- SymbolName: _val1
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 7
- SymbolName: _val2
- Type: IMAGE_REL_I386_DIR32
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: ""
-symbols:
- - Name: "@comp.id"
- Value: 10394907
- SectionNumber: 65535
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 12
- NumberOfRelocations: 2
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: .data
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 0
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: _val1
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _val2
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _main
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/merge-largest1.obj.yaml b/test/pecoff/Inputs/merge-largest1.obj.yaml
deleted file mode 100644
index e372f9030603..000000000000
--- a/test/pecoff/Inputs/merge-largest1.obj.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: 00112233
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 7
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 2532800969
- Number: 0
- Selection: IMAGE_COMDAT_SELECT_LARGEST
- - Name: "_foo"
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/merge-largest2.obj.yaml b/test/pecoff/Inputs/merge-largest2.obj.yaml
deleted file mode 100644
index f232cd3fd870..000000000000
--- a/test/pecoff/Inputs/merge-largest2.obj.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: 0011223344556677
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 7
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 2532800969
- Number: 0
- Selection: IMAGE_COMDAT_SELECT_LARGEST
- - Name: "_foo"
- Value: 6
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/merge-same-size1.obj.yaml b/test/pecoff/Inputs/merge-same-size1.obj.yaml
deleted file mode 100644
index 02516f37220e..000000000000
--- a/test/pecoff/Inputs/merge-same-size1.obj.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: FFFFFFFFFFFFFF
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 7
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 2532800969
- Number: 0
- Selection: IMAGE_COMDAT_SELECT_SAME_SIZE
- - Name: "_foo"
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/merge-same-size2.obj.yaml b/test/pecoff/Inputs/merge-same-size2.obj.yaml
deleted file mode 100644
index 6b5b593bbab1..000000000000
--- a/test/pecoff/Inputs/merge-same-size2.obj.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: AAAAAAAAAAAAAA
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 7
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 2532800969
- Number: 0
- Selection: IMAGE_COMDAT_SELECT_SAME_SIZE
- - Name: "_foo"
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/merge-same-size3.obj.yaml b/test/pecoff/Inputs/merge-same-size3.obj.yaml
deleted file mode 100644
index 47ad417f2f0c..000000000000
--- a/test/pecoff/Inputs/merge-same-size3.obj.yaml
+++ /dev/null
@@ -1,30 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: FFFF
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 2
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 2532800969
- Number: 0
- Selection: IMAGE_COMDAT_SELECT_SAME_SIZE
- - Name: "_foo"
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/nonstandard-sections.obj.yaml b/test/pecoff/Inputs/nonstandard-sections.obj.yaml
deleted file mode 100644
index b80d8862ec61..000000000000
--- a/test/pecoff/Inputs/nonstandard-sections.obj.yaml
+++ /dev/null
@@ -1,53 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: []
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 01234678
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: 01234678
- - Name: .foo
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE, IMAGE_SCN_MEM_EXECUTE ]
- Alignment: 4
- SectionData: 01234678
- - Name: .bar
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 01234678
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .data
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .foo
- Value: 0
- SectionNumber: 3
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .bar
- Value: 0
- SectionNumber: 4
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: _main
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/nop.asm b/test/pecoff/Inputs/nop.asm
deleted file mode 100644
index 8e53070e7f5c..000000000000
--- a/test/pecoff/Inputs/nop.asm
+++ /dev/null
@@ -1,9 +0,0 @@
-.386
-.model flat, stdcall
-option casemap :none
-
-.code
-start:
- mov eax, 42
- ret
-end start
diff --git a/test/pecoff/Inputs/nop.obj.yaml b/test/pecoff/Inputs/nop.obj.yaml
deleted file mode 100644
index ccc097e7c926..000000000000
--- a/test/pecoff/Inputs/nop.obj.yaml
+++ /dev/null
@@ -1,51 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: B82A000000C3
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: ""
-symbols:
- - Name: "@comp.id"
- Value: 10394907
- SectionNumber: 65535
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .text
- 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: .data
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 0
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: _start
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/nop64.obj.yaml b/test/pecoff/Inputs/nop64.obj.yaml
deleted file mode 100644
index 66edc376a90e..000000000000
--- a/test/pecoff/Inputs/nop64.obj.yaml
+++ /dev/null
@@ -1,67 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_AMD64
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: C3C3C3C3
- Relocations:
- - VirtualAddress: 0
- SymbolName: __imp__fn
- Type: IMAGE_REL_AMD64_REL32
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 16
- SectionData: ''
-symbols:
- - Name: '@comp.id'
- Value: 13485607
- SectionNumber: 65535
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: '@feat.00'
- Value: 16
- SectionNumber: 65535
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 1
- NumberOfRelocations: 1
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: .data
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 0
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: __imp__fn
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: start
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/reloc.obj.yaml b/test/pecoff/Inputs/reloc.obj.yaml
deleted file mode 100644
index 4c83258c623c..000000000000
--- a/test/pecoff/Inputs/reloc.obj.yaml
+++ /dev/null
@@ -1,82 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: 680000000068000000006800000000680000000068000000006800000000
- Relocations:
- - VirtualAddress: 1
- SymbolName: _message
- Type: IMAGE_REL_I386_SECTION
- - VirtualAddress: 6
- SymbolName: _message
- Type: IMAGE_REL_I386_SECREL
- - VirtualAddress: 11
- SymbolName: .data
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 16
- SymbolName: .data
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 21
- SymbolName: __imp__MessageBoxA@16
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 26
- SymbolName: _abs_value
- Type: IMAGE_REL_I386_DIR32
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: 576F726C64210048656C6C6F2C00
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 60
- NumberOfRelocations: 3
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 1
- - Name: .data
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 14
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 2
- - Name: _main
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _message
- Value: 5
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: __imp__MessageBoxA@16
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _abs_value
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/reloc64.obj.yaml b/test/pecoff/Inputs/reloc64.obj.yaml
deleted file mode 100644
index 3230ca51c6cc..000000000000
--- a/test/pecoff/Inputs/reloc64.obj.yaml
+++ /dev/null
@@ -1,63 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_AMD64
- Characteristics: []
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: 48B800000000000000ffE8000000ffE8000000ffE8000000ffE8000000ffE8000000ffE8000000ffE8000000ffE8000000ffC3
- Relocations:
- - VirtualAddress: 2
- SymbolName: end
- Type: IMAGE_REL_AMD64_ADDR64
- - VirtualAddress: 11
- SymbolName: end
- Type: IMAGE_REL_AMD64_REL32
- - VirtualAddress: 16
- SymbolName: end
- Type: IMAGE_REL_AMD64_REL32_1
- - VirtualAddress: 21
- SymbolName: end
- Type: IMAGE_REL_AMD64_REL32_2
- - VirtualAddress: 26
- SymbolName: end
- Type: IMAGE_REL_AMD64_REL32_3
- - VirtualAddress: 31
- SymbolName: end
- Type: IMAGE_REL_AMD64_REL32_4
- - VirtualAddress: 36
- SymbolName: end
- Type: IMAGE_REL_AMD64_REL32_5
- - VirtualAddress: 41
- SymbolName: end
- Type: IMAGE_REL_AMD64_SECTION
- - VirtualAddress: 46
- SymbolName: end
- Type: IMAGE_REL_AMD64_SECREL
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 41
- NumberOfRelocations: 7
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: entry
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: end
- Value: 40
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/resource.rc b/test/pecoff/Inputs/resource.rc
deleted file mode 100644
index df933e83b77a..000000000000
--- a/test/pecoff/Inputs/resource.rc
+++ /dev/null
@@ -1,4 +0,0 @@
-STRINGTABLE
-{
- 1, "Hello"
-}
diff --git a/test/pecoff/Inputs/responsefile.txt b/test/pecoff/Inputs/responsefile.txt
deleted file mode 100644
index 08286119d4ed..000000000000
--- a/test/pecoff/Inputs/responsefile.txt
+++ /dev/null
@@ -1 +0,0 @@
--foo -bar\baz
diff --git a/test/pecoff/Inputs/secrel1.obj.yaml b/test/pecoff/Inputs/secrel1.obj.yaml
deleted file mode 100644
index 1c49261bbc43..000000000000
--- a/test/pecoff/Inputs/secrel1.obj.yaml
+++ /dev/null
@@ -1,69 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: C3
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: 00000000000000000000000000000000
- Relocations:
- - VirtualAddress: 0
- SymbolName: .data
- Type: IMAGE_REL_I386_SECREL
- - Name: .data2
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: 00000000000000000000000000000000
- Relocations:
- - VirtualAddress: 0
- SymbolName: .data2
- Type: IMAGE_REL_I386_SECREL
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 60
- NumberOfRelocations: 1
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 1
- - Name: .data
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 4
- NumberOfRelocations: 1
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 2
- - Name: .data2
- Value: 0
- SectionNumber: 3
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 4
- NumberOfRelocations: 1
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 3
- - 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/pecoff/Inputs/secrel2.obj.yaml b/test/pecoff/Inputs/secrel2.obj.yaml
deleted file mode 100644
index 2885fd07bb3a..000000000000
--- a/test/pecoff/Inputs/secrel2.obj.yaml
+++ /dev/null
@@ -1,47 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: 00000000000000000000000000000000
- Relocations:
- - VirtualAddress: 0
- SymbolName: .data
- Type: IMAGE_REL_I386_SECREL
- - Name: .data2
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: 00000000000000000000000000000000
- Relocations:
- - VirtualAddress: 0
- SymbolName: .data2
- Type: IMAGE_REL_I386_SECREL
-symbols:
- - Name: .data
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 4
- NumberOfRelocations: 1
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 1
- - Name: .data2
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 4
- NumberOfRelocations: 1
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 2
-...
diff --git a/test/pecoff/Inputs/seh.c b/test/pecoff/Inputs/seh.c
deleted file mode 100644
index b1c139a58f22..000000000000
--- a/test/pecoff/Inputs/seh.c
+++ /dev/null
@@ -1,13 +0,0 @@
-__declspec(noinline) void triggerSEH() {
- volatile int *p = 0;
- *p = 1;
-}
-
-int main() {
- __try {
- triggerSEH();
- } __except(1) {
- return 42;
- }
- return 0;
-}
diff --git a/test/pecoff/Inputs/seh.obj.yaml b/test/pecoff/Inputs/seh.obj.yaml
deleted file mode 100644
index 6767671cdafe..000000000000
--- a/test/pecoff/Inputs/seh.obj.yaml
+++ /dev/null
@@ -1,387 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .drectve
- Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
- Alignment: 1
- SectionData: 2020202F44454641554C544C49423A22757569642E6C696222202F44454641554C544C49423A22757569642E6C696222202F4641494C49464D49534D415443483A225F4D53435F5645523D3138303022202F4641494C49464D49534D415443483A225F4954455241544F525F44454255475F4C4556454C3D3022202F4641494C49464D49534D415443483A2252756E74696D654C6962726172793D4D445F44796E616D696352656C6561736522202F44454641554C544C49423A226D73766370727422202F44454641554C544C49423A224D535643525422202F44454641554C544C49423A224F4C444E414D45532220
- - Name: '.debug$S'
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
- Alignment: 1
- SectionData: 04000000F1000000600000002200011100000000433A5C63796777696E5C686F6D655C727569755C7365682E6F626A003A003C11012200000700120000000D520100120000000D5201004D6963726F736F667420285229204F7074696D697A696E6720436F6D70696C657200
- - Name: .rdata
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ]
- Alignment: 1
- SectionData: 00
- - Name: .rdata
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ]
- Alignment: 1
- SectionData: 01
- - Name: .rdata
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 54726967676572696E672053454820657863657074696F6E0D0A0000457865637574696E6720534548205F5F65786365707420626C6F636B20696E20666F6F0D0A000000457865637574696E6720534548205F5F65786365707420626C6F636B0D0A00
- - Name: '.text$mn'
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: 558BEC516800000000FF150000000083C404C745FC000000008B45FCC700140000008BE55DC3CCCCCCCCCCCCCCCCCCCC558BEC51E8000000008D4DFFE8000000008BE55DC3CCCCCCCCCCCCCCCCCCCCCC558BEC6AFE6800000000680000000064A1000000005083EC08535657A1000000003145F833C5508D45F064A3000000008965E8C745FC00000000E800000000C745FCFEFFFFFFEB1EB801000000C38B65E86800000000FF150000000083C404C745FCFEFFFFFF8B4DF064890D00000000595F5E5B8BE55DC3CCCCCCCCCCCCCCCC558BEC6AFE6800000000680000000064A1000000005083EC08535657A1000000003145F833C5508D45F064A3000000008965E8C745FC00000000E800000000E800000000C745FCFEFFFFFFEB1EB801000000C38B65E86800000000FF150000000083C404C745FCFEFFFFFF33C08B4DF064890D00000000595F5E5B8BE55DC3
- Relocations:
- - VirtualAddress: 5
- SymbolName: '$SG73531'
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 11
- SymbolName: __imp__printf
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 53
- SymbolName: '?TestCPPEX@@YAXXZ'
- Type: IMAGE_REL_I386_REL32
- - VirtualAddress: 61
- SymbolName: '??1TestClass@@QAE@XZ'
- Type: IMAGE_REL_I386_REL32
- - VirtualAddress: 86
- SymbolName: '__sehtable$?foo@@YAXXZ'
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 91
- SymbolName: __except_handler4
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 109
- SymbolName: ___security_cookie
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 139
- SymbolName: '?TestExceptions@@YAXXZ'
- Type: IMAGE_REL_I386_REL32
- - VirtualAddress: 162
- SymbolName: '$SG73539'
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 168
- SymbolName: __imp__printf
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 214
- SymbolName: '__sehtable$_main'
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 219
- SymbolName: __except_handler4
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 237
- SymbolName: ___security_cookie
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 267
- SymbolName: '?foo@@YAXXZ'
- Type: IMAGE_REL_I386_REL32
- - VirtualAddress: 272
- SymbolName: '?TestExceptions@@YAXXZ'
- Type: IMAGE_REL_I386_REL32
- - VirtualAddress: 295
- SymbolName: '$SG73543'
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 301
- SymbolName: __imp__printf
- Type: IMAGE_REL_I386_DIR32
- - Name: '.text$mn'
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: 558BEC51894DFC6800000000FF150000000083C4048BE55DC3
- Relocations:
- - VirtualAddress: 8
- SymbolName: '??_C@_0BI@BBHGNMOG@Destroying?5TestClass?$CB?$AN?6?$AA@'
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 14
- SymbolName: __imp__printf
- Type: IMAGE_REL_I386_DIR32
- - Name: '.xdata$x'
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
- Alignment: 8
- SectionData: FEFFFFFF00000000D8FFFFFF00000000FEFFFFFF000000000000000000000000FEFFFFFF00000000D8FFFFFF00000000FEFFFFFF0000000000000000
- Relocations:
- - VirtualAddress: 20
- SymbolName: '$LN5'
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 24
- SymbolName: '$LN6'
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 52
- SymbolName: '$LN5'
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 56
- SymbolName: '$LN6'
- Type: IMAGE_REL_I386_DIR32
- - Name: .rdata
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 44657374726F79696E672054657374436C617373210D0A00
- - Name: .sxdata
- Characteristics: [ IMAGE_SCN_LNK_INFO ]
- Alignment: 4
- SectionData: 1B0000001A000000
-symbols:
- - Name: '@comp.id'
- Value: 14766605
- SectionNumber: 65535
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: '@feat.00'
- Value: 2147484049
- SectionNumber: 65535
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .drectve
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 240
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: '.debug$S'
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 108
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: .rdata
- Value: 0
- SectionNumber: 3
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 1
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- Selection: IMAGE_COMDAT_SELECT_ANY
- - Name: '?value@?$integral_constant@_N$0A@@std@@2_NB'
- Value: 0
- SectionNumber: 3
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: .rdata
- Value: 0
- SectionNumber: 4
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 1
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 1996959894
- Number: 0
- Selection: IMAGE_COMDAT_SELECT_ANY
- - Name: '?value@?$integral_constant@_N$00@std@@2_NB'
- Value: 0
- SectionNumber: 4
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: .rdata
- Value: 0
- SectionNumber: 5
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 99
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 2801625422
- Number: 0
- - Name: '$SG73531'
- Value: 0
- SectionNumber: 5
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: '$SG73539'
- Value: 28
- SectionNumber: 5
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: '$SG73543'
- Value: 68
- SectionNumber: 5
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: '.text$mn'
- Value: 0
- SectionNumber: 6
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 335
- NumberOfRelocations: 17
- NumberOfLinenumbers: 0
- CheckSum: 2488225337
- Number: 0
- - Name: '.text$mn'
- Value: 0
- SectionNumber: 7
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 25
- NumberOfRelocations: 2
- NumberOfLinenumbers: 0
- CheckSum: 210566957
- Number: 0
- Selection: IMAGE_COMDAT_SELECT_ANY
- - Name: __imp__printf
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: '??1TestClass@@QAE@XZ'
- Value: 0
- SectionNumber: 7
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: '?TestCPPEX@@YAXXZ'
- Value: 0
- SectionNumber: 6
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: '?TestExceptions@@YAXXZ'
- Value: 48
- SectionNumber: 6
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: '?foo@@YAXXZ'
- Value: 80
- SectionNumber: 6
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _main
- Value: 208
- SectionNumber: 6
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: __except_handler4
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: '$LN5'
- Value: 152
- SectionNumber: 6
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_LABEL
- - Name: '$LN7'
- Value: 157
- SectionNumber: 6
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_LABEL
- - Name: '$LN6'
- Value: 158
- SectionNumber: 6
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_LABEL
- - Name: '$LN5'
- Value: 285
- SectionNumber: 6
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_LABEL
- - Name: '$LN7'
- Value: 290
- SectionNumber: 6
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_LABEL
- - Name: '$LN6'
- Value: 291
- SectionNumber: 6
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_LABEL
- - Name: '.xdata$x'
- Value: 0
- SectionNumber: 8
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 60
- NumberOfRelocations: 4
- NumberOfLinenumbers: 0
- CheckSum: 2900129504
- Number: 0
- - Name: '__sehtable$?foo@@YAXXZ'
- Value: 32
- SectionNumber: 8
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: '__sehtable$_main'
- Value: 0
- SectionNumber: 8
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .rdata
- Value: 0
- SectionNumber: 9
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 24
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 1296623929
- Number: 0
- Selection: IMAGE_COMDAT_SELECT_ANY
- - Name: '??_C@_0BI@BBHGNMOG@Destroying?5TestClass?$CB?$AN?6?$AA@'
- Value: 0
- SectionNumber: 9
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: ___security_cookie
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: .sxdata
- Value: 0
- SectionNumber: 10
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 4
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
-...
diff --git a/test/pecoff/Inputs/static-data1.obj.yaml b/test/pecoff/Inputs/static-data1.obj.yaml
deleted file mode 100644
index 8dbe3e97eb51..000000000000
--- a/test/pecoff/Inputs/static-data1.obj.yaml
+++ /dev/null
@@ -1,67 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: ""
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: 03000000
- - Name: ".debug$S"
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
- Alignment: 1
- SectionData: 04000000F1000000660000002B00011100000000433A5C63796777696E5C686F6D655C727569755C7374617469635C64617461312E6F626A0037003C1103020000030000000000000000000A0000001B9D01004D6963726F736F667420285229204D6163726F20417373656D626C657200000000
-symbols:
- - Name: "@comp.id"
- Value: 10394907
- SectionNumber: 65535
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 0
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: .data
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 4
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: ".debug$S"
- Value: 0
- SectionNumber: 3
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 116
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: _val1
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/static-data2.obj.yaml b/test/pecoff/Inputs/static-data2.obj.yaml
deleted file mode 100644
index 9b368c033887..000000000000
--- a/test/pecoff/Inputs/static-data2.obj.yaml
+++ /dev/null
@@ -1,67 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: ""
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: 04000000
- - Name: ".debug$S"
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
- Alignment: 1
- SectionData: 04000000F1000000660000002B00011100000000433A5C63796777696E5C686F6D655C727569755C7374617469635C64617461322E6F626A0037003C1103020000030000000000000000000A0000001B9D01004D6963726F736F667420285229204D6163726F20417373656D626C657200000000
-symbols:
- - Name: "@comp.id"
- Value: 10394907
- SectionNumber: 65535
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 0
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: .data
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 4
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: ".debug$S"
- Value: 0
- SectionNumber: 3
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 116
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: _val2
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/static.lib b/test/pecoff/Inputs/static.lib
deleted file mode 100644
index 5a631010e1d3..000000000000
--- a/test/pecoff/Inputs/static.lib
+++ /dev/null
Binary files differ
diff --git a/test/pecoff/Inputs/subsystem.main.yaml b/test/pecoff/Inputs/subsystem.main.yaml
deleted file mode 100644
index 25fbe1be0143..000000000000
--- a/test/pecoff/Inputs/subsystem.main.yaml
+++ /dev/null
@@ -1,35 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: B82A000000C3
-symbols:
- - Name: .text
- 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_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _mainCRTStartup
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/subsystem.winmain.yaml b/test/pecoff/Inputs/subsystem.winmain.yaml
deleted file mode 100644
index 7f0381e2dc69..000000000000
--- a/test/pecoff/Inputs/subsystem.winmain.yaml
+++ /dev/null
@@ -1,35 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: B82A000000C3
-symbols:
- - Name: .text
- 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: _WinMain
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _WinMainCRTStartup
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/tlsused.obj.yaml b/test/pecoff/Inputs/tlsused.obj.yaml
deleted file mode 100644
index 6a7880fa7878..000000000000
--- a/test/pecoff/Inputs/tlsused.obj.yaml
+++ /dev/null
@@ -1,29 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: []
-sections:
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: "0000000000000000"
-symbols:
- - Name: .data
- 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: __tls_used
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/unknown-drectve.obj.yaml b/test/pecoff/Inputs/unknown-drectve.obj.yaml
deleted file mode 100644
index 79a12fe7bfa2..000000000000
--- a/test/pecoff/Inputs/unknown-drectve.obj.yaml
+++ /dev/null
@@ -1,42 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: 558BEC56FF15000000008B0D000000008B3103F0FF150000000003C65E5DC3
- - Name: .drectve
- Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
- Alignment: 2147483648
-
- # /nosuchoption:foobar
- SectionData: 2f6e6f737563686f7074696f6e3a666f6f62617200
-
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 31
- NumberOfRelocations: 3
- NumberOfLinenumbers: 0
- CheckSum: 3595596940
- Number: 0
- - Name: .drectve
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 13
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
-...
diff --git a/test/pecoff/Inputs/unwind.obj.yaml b/test/pecoff/Inputs/unwind.obj.yaml
deleted file mode 100644
index 2328cd565601..000000000000
--- a/test/pecoff/Inputs/unwind.obj.yaml
+++ /dev/null
@@ -1,129 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_AMD64
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 4883EC184889742410440F110424534889E3488D235B4883C418C3C34881ECF0FF00004881ECF0FF80004881C4F0FF80004881C4F0FF0000C3
- - Name: .xdata
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 0912080312030F300E880000096402000422001A000000000000000021000000000000001B000000000000000100000000000000010E06000E11F0FF80000701FE1F001A
- Relocations:
- - VirtualAddress: 20
- SymbolName: __C_specific_handler
- Type: IMAGE_REL_AMD64_ADDR32NB
- - VirtualAddress: 32
- SymbolName: func
- Type: IMAGE_REL_AMD64_ADDR32NB
- - VirtualAddress: 36
- SymbolName: func
- Type: IMAGE_REL_AMD64_ADDR32NB
- - VirtualAddress: 40
- SymbolName: .xdata
- Type: IMAGE_REL_AMD64_ADDR32NB
- - Name: .pdata
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 000000001B0000000000000012000000120000001C00000000000000010000002C000000000000001D00000034000000
- Relocations:
- - VirtualAddress: 0
- SymbolName: func
- Type: IMAGE_REL_AMD64_ADDR32NB
- - VirtualAddress: 4
- SymbolName: func
- Type: IMAGE_REL_AMD64_ADDR32NB
- - VirtualAddress: 8
- SymbolName: .xdata
- Type: IMAGE_REL_AMD64_ADDR32NB
- - VirtualAddress: 12
- SymbolName: func
- Type: IMAGE_REL_AMD64_ADDR32NB
- - VirtualAddress: 16
- SymbolName: func
- Type: IMAGE_REL_AMD64_ADDR32NB
- - VirtualAddress: 20
- SymbolName: .xdata
- Type: IMAGE_REL_AMD64_ADDR32NB
- - VirtualAddress: 24
- SymbolName: smallFunc
- Type: IMAGE_REL_AMD64_ADDR32NB
- - VirtualAddress: 28
- SymbolName: smallFunc
- Type: IMAGE_REL_AMD64_ADDR32NB
- - VirtualAddress: 32
- SymbolName: .xdata
- Type: IMAGE_REL_AMD64_ADDR32NB
- - VirtualAddress: 36
- SymbolName: allocFunc
- Type: IMAGE_REL_AMD64_ADDR32NB
- - VirtualAddress: 40
- SymbolName: allocFunc
- Type: IMAGE_REL_AMD64_ADDR32NB
- - VirtualAddress: 44
- SymbolName: .xdata
- Type: IMAGE_REL_AMD64_ADDR32NB
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 57
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 1
- - Name: .xdata
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 68
- NumberOfRelocations: 4
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 2
- - Name: .pdata
- Value: 0
- SectionNumber: 3
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 48
- NumberOfRelocations: 12
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 3
- - Name: func
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: __C_specific_handler
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: smallFunc
- Value: 27
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: allocFunc
- Value: 28
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/vars-main-x64.obj.yaml b/test/pecoff/Inputs/vars-main-x64.obj.yaml
deleted file mode 100644
index c888c28e4a67..000000000000
--- a/test/pecoff/Inputs/vars-main-x64.obj.yaml
+++ /dev/null
@@ -1,63 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_AMD64
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: 558BEC56FF15000000008B0D000000008B3103F0FF150000000003C65E5DC3
- Relocations:
- - VirtualAddress: 6
- SymbolName: __imp_fn
- Type: IMAGE_REL_AMD64_ADDR32
- - VirtualAddress: 12
- SymbolName: __imp_var
- Type: IMAGE_REL_AMD64_ADDR32
- - VirtualAddress: 22
- SymbolName: __imp__name_with_underscore
- Type: IMAGE_REL_AMD64_ADDR32
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 31
- NumberOfRelocations: 3
- NumberOfLinenumbers: 0
- CheckSum: 3595596940
- Number: 0
- - Name: __imp_fn
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: __imp__name_with_underscore
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: main
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: "__delayLoadHelper2"
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: __imp_var
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/vars-main-x86.obj.yaml b/test/pecoff/Inputs/vars-main-x86.obj.yaml
deleted file mode 100644
index fb016828df94..000000000000
--- a/test/pecoff/Inputs/vars-main-x86.obj.yaml
+++ /dev/null
@@ -1,69 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 16
- SectionData: 558BEC56FF15000000008B0D000000008B3103F0FF150000000003C65E5DC3
- Relocations:
- - VirtualAddress: 6
- SymbolName: __imp__fn
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 12
- SymbolName: __imp__var
- Type: IMAGE_REL_I386_DIR32
- - VirtualAddress: 22
- SymbolName: __imp___name_with_underscore
- Type: IMAGE_REL_I386_DIR32
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 31
- NumberOfRelocations: 3
- NumberOfLinenumbers: 0
- CheckSum: 3595596940
- Number: 0
- - Name: __imp__fn
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: __imp___name_with_underscore
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _main
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_FUNCTION
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: "___delayLoadHelper2@8"
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: __imp__var
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: ___ImageBase
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/Inputs/vars-main.c b/test/pecoff/Inputs/vars-main.c
deleted file mode 100644
index d588ca54b88e..000000000000
--- a/test/pecoff/Inputs/vars-main.c
+++ /dev/null
@@ -1,7 +0,0 @@
-__declspec(dllimport) int var;
-__declspec(dllimport) int fn(void);
-__declspec(dllimport) int _name_with_underscore(void);
-
-int main() {
- return var + fn() + _name_with_underscore();
-}
diff --git a/test/pecoff/Inputs/vars.c b/test/pecoff/Inputs/vars.c
deleted file mode 100644
index ae2ec46d1f47..000000000000
--- a/test/pecoff/Inputs/vars.c
+++ /dev/null
@@ -1,20 +0,0 @@
-// cl.exe /c vars.c
-// link /dll /nodefaultlib /entry:dllmain /export:var,@1,NONAME,DATA \
-// /export:fn /export:_name_with_underscore vars.obj
-
-// will be exported by ordinal
-int var = 3;
-
-// will be exported by name
-int fn(void) {
- return 4;
-}
-
-// will be exported by name
-int _name_with_underscore(void) {
- return 5;
-}
-
-int dllmain() {
- return 1;
-}
diff --git a/test/pecoff/Inputs/vars.dll.yaml b/test/pecoff/Inputs/vars.dll.yaml
deleted file mode 100644
index 06f65ced6933..000000000000
--- a/test/pecoff/Inputs/vars.dll.yaml
+++ /dev/null
@@ -1,19 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_32BIT_MACHINE, IMAGE_FILE_DLL ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 2147483648
- SectionData: 558BECB8040000005DC3CCCCCCCCCCCC558BECB8050000005DC3CCCCCCCCCCCC558BECB8010000005DC30000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
- - Name: .rdata
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
- Alignment: 2147483648
- SectionData: 0000000050570852000000004020000001000000030000000200000028200000342000003C200000003000001010000000100000492000005F20000001000200766172732E646C6C005F6E616D655F776974685F756E64657273636F726500666E00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 2147483648
- SectionData: 0300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-symbols:
-...
diff --git a/test/pecoff/Inputs/vars.lib b/test/pecoff/Inputs/vars.lib
deleted file mode 100644
index 2d3aa2af678e..000000000000
--- a/test/pecoff/Inputs/vars.lib
+++ /dev/null
Binary files differ
diff --git a/test/pecoff/Inputs/vars64.lib b/test/pecoff/Inputs/vars64.lib
deleted file mode 100644
index fb48c9ab141e..000000000000
--- a/test/pecoff/Inputs/vars64.lib
+++ /dev/null
Binary files differ
diff --git a/test/pecoff/Inputs/weak-externals.asm b/test/pecoff/Inputs/weak-externals.asm
deleted file mode 100644
index 7a5e918b92e7..000000000000
--- a/test/pecoff/Inputs/weak-externals.asm
+++ /dev/null
@@ -1,25 +0,0 @@
-.386
-.model flat
-
-;; val1 should be linked normally. no_such_symbol1 should be ignored.
-extern _no_such_symbol1 : PROC
-extern _val1 (_no_such_symbol1): PROC
-
-;; no_such_symbol2 should be linked as val2.
-extern _val2 : PROC
-extern _no_such_symbol2 (_val2) : PROC
-
-;; no_such_symbol3 should fail to link.
-extern _no_such_symbol3 : PROC
-
-public _fn1
-.code
-_fn1:
- push ebp
- mov ebp, esp
- call _val1
- call _no_such_symbol2
- call _no_such_symbol3
- pop ebp
- ret 0
-end _fn1
diff --git a/test/pecoff/Inputs/weak-externals.obj.yaml b/test/pecoff/Inputs/weak-externals.obj.yaml
deleted file mode 100644
index ee76936c5326..000000000000
--- a/test/pecoff/Inputs/weak-externals.obj.yaml
+++ /dev/null
@@ -1,91 +0,0 @@
----
-header:
- Machine: IMAGE_FILE_MACHINE_I386
- Characteristics: [ ]
-sections:
- - Name: .text
- Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
- Alignment: 4
- SectionData: 558BECE800000000E800000000E8000000005DC3
- Relocations:
- - VirtualAddress: 4
- SymbolName: _val1
- Type: IMAGE_REL_I386_REL32
- - VirtualAddress: 9
- SymbolName: _no_such_symbol2
- Type: IMAGE_REL_I386_REL32
- - VirtualAddress: 14
- SymbolName: _no_such_symbol3
- Type: IMAGE_REL_I386_REL32
- - Name: .data
- Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
- Alignment: 4
- SectionData: ""
-symbols:
- - Name: .text
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 20
- NumberOfRelocations: 3
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: .data
- Value: 0
- SectionNumber: 2
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_STATIC
- SectionDefinition:
- Length: 0
- NumberOfRelocations: 0
- NumberOfLinenumbers: 0
- CheckSum: 0
- Number: 0
- - Name: _no_such_symbol1
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _val2
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _no_such_symbol3
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
- - Name: _val1
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_WEAK_EXTERNAL
- WeakExternal:
- TagIndex: 4
- Characteristics: IMAGE_WEAK_EXTERN_SEARCH_LIBRARY
- - Name: _no_such_symbol2
- Value: 0
- SectionNumber: 0
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_WEAK_EXTERNAL
- WeakExternal:
- TagIndex: 5
- Characteristics: IMAGE_WEAK_EXTERN_SEARCH_LIBRARY
- - Name: _fn1
- Value: 0
- SectionNumber: 1
- SimpleType: IMAGE_SYM_TYPE_NULL
- ComplexType: IMAGE_SYM_DTYPE_NULL
- StorageClass: IMAGE_SYM_CLASS_EXTERNAL
-...
diff --git a/test/pecoff/alignment.test b/test/pecoff/alignment.test
deleted file mode 100644
index bdf8bbaa2a3e..000000000000
--- a/test/pecoff/alignment.test
+++ /dev/null
@@ -1,22 +0,0 @@
-# RUN: yaml2obj %p/Inputs/alignment.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /force \
-# RUN: /entry:start /opt:noref -- %t.obj
-# RUN: llvm-readobj -sections %t.exe | FileCheck %s
-
-CHECK: Name: .bss (2E 62 73 73 00 00 00 00)
-CHECK: RawDataSize: 0
-
-CHECK: Name: .data (2E 64 61 74 61 00 00 00)
-CHECK-NEXT: VirtualSize: 0x6
-
-CHECK: Name: .text (2E 74 65 78 74 00 00 00)
-CHECK-NEXT: VirtualSize: 0x1001
-
-CHECK: Name: .yyy
-CHECK-NEXT: VirtualSize: 0x2
-CHECK-NEXT: VirtualAddress: 0x5000
-
-CHECK: Name: .zzz
-CHECK-NEXT: VirtualSize: 0x2
-CHECK-NEXT: VirtualAddress: 0x8000
diff --git a/test/pecoff/alternatename.test b/test/pecoff/alternatename.test
deleted file mode 100644
index 926a8eae2876..000000000000
--- a/test/pecoff/alternatename.test
+++ /dev/null
@@ -1,44 +0,0 @@
-# REQUIRES: x86
-
-# RUN: yaml2obj %p/Inputs/alternatename1.obj.yaml > %t1.obj
-# RUN: yaml2obj %p/Inputs/alternatename2.obj.yaml > %t2.obj
-# RUN: yaml2obj %p/Inputs/alternatename3.obj.yaml > %t3.obj
-#
-# RUN: lld -flavor link /force /out:%t1.exe /alternatename:_main=_foo \
-# RUN: /subsystem:console -- %t1.obj
-# RUN: llvm-objdump -d %t1.exe | FileCheck -check-prefix=CHECK1 %s
-#
-# RUN: lld -flavor link /force /out:%t2.exe /alternatename:_main=_foo \
-# RUN: /subsystem:console -- %t1.obj %t2.obj
-# RUN: llvm-objdump -d %t2.exe | FileCheck -check-prefix=CHECK2 %s
-#
-# RUN: lld -flavor link /force /out:%t3.exe /subsystem:console -- %t3.obj
-# RUN: llvm-objdump -d %t3.exe | FileCheck -check-prefix=CHECK3 %s
-#
-# RUN: lld -flavor link /force /out:%t4.exe /alternatename:_main=_foo \
-# RUN: /alternatename:_xyz=_foo /subsystem:console -- %t1.obj
-# RUN: llvm-objdump -d %t4.exe | FileCheck -check-prefix=CHECK4 %s
-
-CHECK1: nop
-CHECK1-NEXT: nop
-CHECK1-NEXT: nop
-CHECK1-NEXT: nop
-CHECK1-NOT: int3
-
-CHECK2: int3
-CHECK2-NEXT: int3
-CHECK2-NEXT: int3
-CHECK2-NEXT: int3
-CHECK2-NOT: nop
-
-CHECK3: nop
-CHECK3-NEXT: nop
-CHECK3-NEXT: nop
-CHECK3-NEXT: nop
-CHECK3-NOT: int3
-
-CHECK4: nop
-CHECK4-NEXT: nop
-CHECK4-NEXT: nop
-CHECK4-NEXT: nop
-CHECK4-NOT: int3
diff --git a/test/pecoff/armnt-ImageBase.test b/test/pecoff/armnt-ImageBase.test
deleted file mode 100644
index b4bf28c5eb81..000000000000
--- a/test/pecoff/armnt-ImageBase.test
+++ /dev/null
@@ -1,14 +0,0 @@
-# RUN: yaml2obj -format coff -o %t.obj %p/Inputs/armnt-ImageBase.obj.yaml
-# RUN: llvm-readobj -r %t.obj | FileCheck %s -check-prefix BEFORE
-# RUN: lld -flavor link /out:%t.exe %t.obj /subsystem:console
-# RUN: llvm-readobj -r %t.exe | FileCheck %s -check-prefix AFTER
-
-BEFORE: Relocations [
-BEFORE: Section {{.*}} .text {
-BEFORE: 0x4 IMAGE_REL_ARM_ADDR32 __ImageBase
-BEFORE: }
-BEFORE: ]
-
-AFTER: Relocations [
-AFTER-NEXT: ]
-
diff --git a/test/pecoff/armnt-addr32-exec.test b/test/pecoff/armnt-addr32-exec.test
deleted file mode 100644
index be223a0e7e5d..000000000000
--- a/test/pecoff/armnt-addr32-exec.test
+++ /dev/null
@@ -1,11 +0,0 @@
-# RUN: yaml2obj -format coff -o %t.obj %p/Inputs/armnt-addr32-exec.obj.yaml
-# RUN: llvm-objdump -s %t.obj | FileCheck %s -check-prefix BEFORE
-# RUN: lld -flavor link /out:%t.exe /entry:function /subsystem:console %t.obj
-# RUN: llvm-objdump -s %t.exe | FileCheck %s -check-prefix AFTER
-
-BEFORE: Contents of section .rdata:
-BEFORE: 0000 00000000
-
-AFTER: Contents of section .rdata:
-AFTER: 1000 01204000
-
diff --git a/test/pecoff/armnt-addr32.test b/test/pecoff/armnt-addr32.test
deleted file mode 100644
index 716217d45758..000000000000
--- a/test/pecoff/armnt-addr32.test
+++ /dev/null
@@ -1,11 +0,0 @@
-# RUN: yaml2obj -format coff -o %t.obj %p/Inputs/armnt-addr32.obj.yaml
-# RUN: llvm-objdump -s %t.obj | FileCheck %s -check-prefix BEFORE
-# RUN: lld -flavor link /entry:is /subsystem:console /out:%t.exe %t.obj
-# RUN: llvm-objdump -s %t.exe | FileCheck %s -check-prefix AFTER
-
-BEFORE: Contents of section .rdata:
-BEFORE: 0000 00000000 00000000
-
-AFTER: Contents of section .rdata:
-AFTER: 1000 00104000 00000000
-
diff --git a/test/pecoff/armnt-address-of-entry-point.test b/test/pecoff/armnt-address-of-entry-point.test
deleted file mode 100644
index 3013b230bbd1..000000000000
--- a/test/pecoff/armnt-address-of-entry-point.test
+++ /dev/null
@@ -1,6 +0,0 @@
-# RUN: yaml2obj -format coff -o %t.obj %p/Inputs/executable.obj.yaml
-# RUN: lld -flavor link /out:%t.exe %t.obj
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-
-# CHECK: AddressOfEntryPoint: 0x1001
-
diff --git a/test/pecoff/armnt-blx23t.test b/test/pecoff/armnt-blx23t.test
deleted file mode 100644
index 56639fa22be9..000000000000
--- a/test/pecoff/armnt-blx23t.test
+++ /dev/null
@@ -1,27 +0,0 @@
-# REQUIRES: arm
-
-# RUN: yaml2obj -format coff -o %t.obj %p/Inputs/armnt-blx23t.obj.yaml
-# RUN: llvm-objdump -d %t.obj | FileCheck %s -check-prefix BEFORE
-# RUN: lld -flavor link /entry:function /subsystem:console /out:%t.exe %t.obj
-# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER
-
-BEFORE: Disassembly of section .text:
-BEFORE: 0: 70 47 bx lr
-BEFORE: 2: 00 bf nop
-BEFORE: 4: 2d e9 00 48 push.w {r11, lr}
-BEFORE: 8: eb 46 mov r11, sp
-BEFORE: a: 20 20 movs r0, #32
-BEFORE: c: 00 f0 00 f8 bl #0
-BEFORE: 10: 01 30 adds r0, #1
-BEFORE: 12: bd e8 00 88 pop.w {r11, pc}
-
-AFTER: Disassembly of section .text:
-AFTER: 1000: 70 47 bx lr
-AFTER: 1002: 00 bf nop
-AFTER: 1004: 2d e9 00 48 push.w {r11, lr}
-AFTER: 1008: eb 46 mov r11, sp
-AFTER: 100a: 20 20 movs r0, #32
-AFTER: 100c: ff f7 f8 ff bl #-16
-AFTER: 1010: 01 30 adds r0, #1
-AFTER: 1012: bd e8 00 88 pop.w {r11, pc}
-
diff --git a/test/pecoff/armnt-branch24t.test b/test/pecoff/armnt-branch24t.test
deleted file mode 100644
index 1a727ed7d725..000000000000
--- a/test/pecoff/armnt-branch24t.test
+++ /dev/null
@@ -1,20 +0,0 @@
-# REQUIRES: arm
-
-# RUN: yaml2obj -format coff -o %t.obj %p/Inputs/armnt-branch24t.obj.yaml
-# RUN: llvm-objdump -d %t.obj | FileCheck %s -check-prefix BEFORE
-# RUN: lld -flavor link /entry:function /subsystem:console /out:%t.exe %t.obj
-# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER
-
-BEFORE: Disassembly of section .text:
-BEFORE: 0: 70 47 bx lr
-BEFORE: 2: 00 bf nop
-BEFORE: 4: 20 20 movs r0, #32
-BEFORE: 6: 00 f0 00 b8 b.w #0
-
-AFTER: Disassembly of section .text:
-AFTER: .text:
-AFTER: 1000: 70 47 bx lr
-AFTER: 1002: 00 bf nop
-AFTER: 1004: 20 20 movs r0, #32
-AFTER: 1006: ff f7 fb bf b.w #-10
-
diff --git a/test/pecoff/armnt-exports.s b/test/pecoff/armnt-exports.s
deleted file mode 100644
index cb500bf02e07..000000000000
--- a/test/pecoff/armnt-exports.s
+++ /dev/null
@@ -1,28 +0,0 @@
-
-# void __declspec(dllexport) function() {}
-# void _DllMainCRTStartup() {}
-
- .syntax unified
- .thumb
- .text
-
- .def function
- .scl 2
- .type 32
- .endef
- .global function
- .align 2
- .thumb_func
-function:
- bx lr
-
- .def _DllMainCRTStartup
- .scl 2
- .type 32
- .endef
- .global _DllMainCRTStartup
- .align 2
- .thumb_func
-_DllMainCRTStartup
- bx lr
-
diff --git a/test/pecoff/armnt-exports.test b/test/pecoff/armnt-exports.test
deleted file mode 100644
index f0aa3eabcacc..000000000000
--- a/test/pecoff/armnt-exports.test
+++ /dev/null
@@ -1,10 +0,0 @@
-# RUN: yaml2obj -format coff -o %t.obj %p/Inputs/armnt-exports.obj.yaml
-# RUN: lld -flavor link /dll /def:%p/Inputs/armnt-exports.def /out:%t.dll %t.obj
-# RUN: llvm-readobj -coff-exports %t.dll | FileCheck %s
-
-CHECK: Export {
-CHECK: Ordinal: 1
-CHECK: Name: function
-CHECK: RVA: 0x2001
-CHECK: }
-
diff --git a/test/pecoff/armnt-imports.test b/test/pecoff/armnt-imports.test
deleted file mode 100644
index 596270909c52..000000000000
--- a/test/pecoff/armnt-imports.test
+++ /dev/null
@@ -1,11 +0,0 @@
-# RUN: yaml2obj -format coff -o %t.obj %p/Inputs/armnt-import.obj.yaml
-# RUN: lld -flavor link /out:%t.exe /subsystem:console %t.obj %p/Inputs/library.lib
-# RUN: llvm-readobj -coff-imports %t.exe | FileCheck %s
-
-CHECK: Import {
-CHECK: Name: library.dll
-CHECK: ImportLookupTableRVA: 0x4000
-CHECK: ImportAddressTableRVA: 0x2000
-CHECK: Symbol: function (0)
-CHECK: }
-
diff --git a/test/pecoff/armnt-mov32t-exec.test b/test/pecoff/armnt-mov32t-exec.test
deleted file mode 100644
index de4feffea0cc..000000000000
--- a/test/pecoff/armnt-mov32t-exec.test
+++ /dev/null
@@ -1,21 +0,0 @@
-# REQUIRES: arm
-
-# RUN: yaml2obj -format coff -o %t.obj %p/Inputs/armnt-mov32t-exec.obj.yaml
-# RUN: llvm-objdump -d %t.obj | FileCheck %s -check-prefix BEFORE
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /entry:get_function %t.obj
-# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER
-
-BEFORE: Disassembly of section .text:
-BEFORE: 0: 70 47 bx lr
-BEFORE: 2: 00 bf nop
-BEFORE: 4: 40 f2 00 00 movw r0, #0
-BEFORE: 8: c0 f2 00 00 movt r0, #0
-BEFORE: c: 70 47 bx lr
-
-AFTER: Disassembly of section .text:
-AFTER: 1000: 70 47 bx lr
-AFTER: 1002: 00 bf nop
-AFTER: 1004: 41 f2 01 00 movw r0, #4097
-AFTER: 1008: c0 f2 40 00 movt r0, #64
-AFTER: 100c: 70 47 bx lr
-
diff --git a/test/pecoff/armnt-movt32t.test b/test/pecoff/armnt-movt32t.test
deleted file mode 100644
index 2ae47ef75846..000000000000
--- a/test/pecoff/armnt-movt32t.test
+++ /dev/null
@@ -1,17 +0,0 @@
-# REQUIRES: arm
-
-# RUN: yaml2obj -format coff -o %t.obj %p/Inputs/armnt-mov32t.obj.yaml
-# RUN: llvm-objdump -d %t.obj | FileCheck %s -check-prefix BEFORE
-# RUN: lld -flavor link /entry:get_buffer /subsystem:console /out:%t.exe %t.obj
-# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER
-
-BEFORE: Disassembly of section .text:
-BEFORE: 0: 40 f2 00 00 movw r0, #0
-BEFORE: 4: c0 f2 00 00 movt r0, #0
-BEFORE: 8: 70 47 bx lr
-
-AFTER: Disassembly of section .text:
-AFTER: 0: 41 f2 00 00 movw r0, #4096
-AFTER: 4: c0 f2 40 00 movt r0, #64
-AFTER: 8: 70 47 bx lr
-
diff --git a/test/pecoff/armnt.test b/test/pecoff/armnt.test
deleted file mode 100644
index 1cf6cd8114a4..000000000000
--- a/test/pecoff/armnt.test
+++ /dev/null
@@ -1,6 +0,0 @@
-# RUN: yaml2obj -format coff -o %t.obj %p/Inputs/armnt-obj.yaml
-# RUN: lld -flavor link /out:%t.dll /subsystem:console /entry:main %t.obj
-# RUN: llvm-readobj -sections %t.dll | FileCheck %s
-
-CHECK: Format: COFF-ARM
-
diff --git a/test/pecoff/associative.test b/test/pecoff/associative.test
deleted file mode 100644
index f998befd007e..000000000000
--- a/test/pecoff/associative.test
+++ /dev/null
@@ -1,10 +0,0 @@
-# RUN: yaml2obj %p/Inputs/associative1.obj.yaml > %t1.obj
-# RUN: yaml2obj %p/Inputs/associative1.obj.yaml > %t2.obj
-# RUN: yaml2obj %p/Inputs/associative3.obj.yaml > %t3.obj
-#
-# RUN: lld -flavor link /machine:x86 /subsystem:console /entry:main \
-# RUN: /out:%t.exe -- %t1.obj %t2.obj %t3.obj
-# RUN: obj2yaml %t.exe | FileCheck %s
-
-CHECK: - Name: .CRT
-CHECK: SectionData: '77777777'
diff --git a/test/pecoff/base-reloc.test b/test/pecoff/base-reloc.test
deleted file mode 100644
index 5bc83de4d1c2..000000000000
--- a/test/pecoff/base-reloc.test
+++ /dev/null
@@ -1,78 +0,0 @@
-# RUN: yaml2obj %p/Inputs/basereloc.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /force /opt:noref \
-# RUN: -- %t.obj
-# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck %s --check-prefix=BASEREL
-#
-# RUN: lld -flavor link /out:%t2.exe /subsystem:console /force /fixed \
-# RUN: /opt:noref -- %t.obj
-# RUN: llvm-readobj -coff-basereloc %t2.exe | FileCheck %s --check-prefix=NOBASEREL
-
-BASEREL: BaseReloc [
-BASEREL-NEXT: Entry {
-BASEREL-NEXT: Type: HIGHLOW
-BASEREL-NEXT: Address: 0x2007
-BASEREL-NEXT: }
-BASEREL-NEXT: Entry {
-BASEREL-NEXT: Type: HIGHLOW
-BASEREL-NEXT: Address: 0x200C
-BASEREL-NEXT: }
-BASEREL-NEXT: Entry {
-BASEREL-NEXT: Type: HIGHLOW
-BASEREL-NEXT: Address: 0x201E
-BASEREL-NEXT: }
-BASEREL-NEXT: Entry {
-BASEREL-NEXT: Type: ABSOLUTE
-BASEREL-NEXT: Address: 0x2000
-BASEREL-NEXT: }
-BASEREL-NEXT: Entry {
-BASEREL-NEXT: Type: HIGHLOW
-BASEREL-NEXT: Address: 0x3007
-BASEREL-NEXT: }
-BASEREL-NEXT: Entry {
-BASEREL-NEXT: Type: HIGHLOW
-BASEREL-NEXT: Address: 0x300C
-BASEREL-NEXT: }
-BASEREL-NEXT: Entry {
-BASEREL-NEXT: Type: HIGHLOW
-BASEREL-NEXT: Address: 0x301E
-BASEREL-NEXT: }
-BASEREL-NEXT: Entry {
-BASEREL-NEXT: Type: ABSOLUTE
-BASEREL-NEXT: Address: 0x3000
-BASEREL-NEXT: }
-BASEREL-NEXT: ]
-
-NOBASEREL: BaseReloc [
-NOBASEREL-NEXT: ]
-
-# RUN: lld -flavor link /out:%t3.exe /subsystem:console /force /opt:noref \
-# RUN: -- %t.obj
-# RUN: llvm-readobj -file-headers -sections %t3.exe | FileCheck %s \
-# RUN: --check-prefix=BASEREL-HEADER
-#
-# RUN: lld -flavor link /out:%t4.exe /subsystem:console /force /opt:noref \
-# RUN: /fixed -- %t.obj
-# RUN: llvm-readobj -file-headers %t4.exe | FileCheck %s \
-# RUN: --check-prefix=NOBASEREL-HEADER
-
-BASEREL-HEADER-NOT: IMAGE_FILE_RELOCS_STRIPPED
-
-NOBASEREL-HEADER: IMAGE_FILE_RELOCS_STRIPPED
-
-BASEREL-HEADER: BaseRelocationTableRVA: 0x4000
-BASEREL-HEADER: BaseRelocationTableSize: 0x20
-BASEREL-HEADER: Name: .reloc (2E 72 65 6C 6F 63 00 00)
-BASEREL-HEADER-NEXT: VirtualSize: 0x20
-BASEREL-HEADER-NEXT: VirtualAddress: 0x4000
-BASEREL-HEADER-NEXT: RawDataSize: 512
-BASEREL-HEADER-NEXT: PointerToRawData: 0xA00
-BASEREL-HEADER-NEXT: PointerToRelocations: 0x0
-BASEREL-HEADER-NEXT: PointerToLineNumbers: 0x0
-BASEREL-HEADER-NEXT: RelocationCount: 0
-BASEREL-HEADER-NEXT: LineNumberCount: 0
-BASEREL-HEADER-NEXT: Characteristics [ (0x42000040)
-BASEREL-HEADER-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-BASEREL-HEADER-NEXT: IMAGE_SCN_MEM_DISCARDABLE (0x2000000)
-BASEREL-HEADER-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-BASEREL-HEADER-NEXT: ]
diff --git a/test/pecoff/baseaddr.test b/test/pecoff/baseaddr.test
deleted file mode 100644
index dbd091bc2e30..000000000000
--- a/test/pecoff/baseaddr.test
+++ /dev/null
@@ -1,18 +0,0 @@
-# RUN: yaml2obj %p/Inputs/nop.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t1.exe /opt:noref /subsystem:console /force \
-# RUN: -- %t.obj
-# RUN: llvm-readobj -file-headers %t1.exe | FileCheck -check-prefix=DEFAULT %s
-#
-# RUN: lld -flavor link /out:%t2.exe /opt:noref /base:8388608 \
-# RUN: /subsystem:console /force -- %t.obj
-# RUN: llvm-readobj -file-headers %t2.exe | FileCheck -check-prefix=BASE %s
-
-DEFAULT: ImageBase: 0x400000
-
-BASE: ImageBase: 0x800000
-
-# RUN: not lld -flavor link /base:3 /subsystem:console -- %t.obj >& %t.log
-# RUN: FileCheck -check-prefix=ERROR %s < %t.log
-
-ERROR: Base address have to be multiple of 64K, but got 3
diff --git a/test/pecoff/bss-section.test b/test/pecoff/bss-section.test
deleted file mode 100644
index 4181e994fbf5..000000000000
--- a/test/pecoff/bss-section.test
+++ /dev/null
@@ -1,21 +0,0 @@
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /force \
-# RUN: -- %p/Inputs/bss.obj
-# RUN: llvm-readobj -sections %t.exe | FileCheck %s
-
-CHECK: Section {
-CHECK: Number: 1
-CHECK-NEXT: Name: .bss
-CHECK-NEXT: VirtualSize: 0x320
-CHECK-NEXT: VirtualAddress: 0x1000
-CHECK-NEXT: RawDataSize: 0
-CHECK-NEXT: PointerToRawData: 0x0
-CHECK-NEXT: PointerToRelocations: 0x0
-CHECK-NEXT: PointerToLineNumbers: 0x0
-CHECK-NEXT: RelocationCount: 0
-CHECK-NEXT: LineNumberCount: 0
-CHECK-NEXT: Characteristics [
-CHECK-NEXT: IMAGE_SCN_CNT_UNINITIALIZED_DATA
-CHECK-NEXT: IMAGE_SCN_MEM_READ
-CHECK-NEXT: IMAGE_SCN_MEM_WRITE
-CHECK-NEXT: ]
-CHECK-NEXT: }
diff --git a/test/pecoff/comdat.test b/test/pecoff/comdat.test
deleted file mode 100644
index d752309d7515..000000000000
--- a/test/pecoff/comdat.test
+++ /dev/null
@@ -1,12 +0,0 @@
-# RUN: yaml2obj %p/Inputs/comdat.obj.yaml > %t1.obj
-# RUN: yaml2obj %p/Inputs/comdat.obj.yaml > %t2.obj
-#
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /opt:noref /force \
-# RUN: -- %t1.obj %t2.obj 2>&1 > %t.log
-#
-# FileCheck complains if the input files is empty, so add a dummy line.
-# RUN: echo foo >> %t.log
-#
-# RUN: FileCheck %s < %t.log
-
-CHECK-NOT: duplicate symbol error
diff --git a/test/pecoff/common-symbol.test b/test/pecoff/common-symbol.test
deleted file mode 100644
index 49d4d8725da4..000000000000
--- a/test/pecoff/common-symbol.test
+++ /dev/null
@@ -1,14 +0,0 @@
-# REQUIRES: x86
-
-# RUN: yaml2obj %p/Inputs/common-symbol.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /machine:x64 /out:%t.exe /subsystem:console /force \
-# RUN: /opt:noref -- %t.obj %t.obj
-# RUN: llvm-objdump -d %t.exe | FileCheck %s
-
-# Operands of B8 (MOV EAX) are common symbols
-CHECK: 3000: b8 00 10 00 40
-CHECK: 3005: b8 04 10 00 40
-CHECK: 300a: b8 20 10 00 40
-CHECK: 300f: b8 60 10 00 40
-CHECK: 3014: b8 80 10 00 40
diff --git a/test/pecoff/conflicting-machine.test b/test/pecoff/conflicting-machine.test
deleted file mode 100644
index 6c71521fe1b7..000000000000
--- a/test/pecoff/conflicting-machine.test
+++ /dev/null
@@ -1,6 +0,0 @@
-# RUN: yaml2obj %p/Inputs/vars-main-x64.obj.yaml > %t-x64.obj
-
-# RUN: not lld -flavor link /machine:x86 /out:%t.exe /entry:main %t-x64.obj 2>&1 \
-# RUN: | FileCheck %s
-
-CHECK: module machine type 'X64' conflicts with target machine type 'X86'
diff --git a/test/pecoff/delayimport.test b/test/pecoff/delayimport.test
deleted file mode 100644
index 89ceb4ad5b20..000000000000
--- a/test/pecoff/delayimport.test
+++ /dev/null
@@ -1,54 +0,0 @@
-# RUN: yaml2obj %p/Inputs/vars-main-x86.obj.yaml > %t-x86.obj
-# RUN: yaml2obj %p/Inputs/vars-main-x64.obj.yaml > %t-x64.obj
-#
-# RUN: lld -flavor link /out:%t1.exe /subsystem:console /entry:main \
-# RUN: /delayload:vars.dll -- %t-x86.obj %p/Inputs/vars.lib
-# RUN: llvm-readobj -coff-imports %t1.exe | FileCheck -check-prefix=X86 %s
-#
-# RUN: lld -flavor link /out:%t2.exe /subsystem:console /entry:main \
-# RUN: /machine:x64 /delayload:vars64.dll -- %t-x64.obj %p/Inputs/vars64.lib
-# RUN: llvm-readobj -coff-imports %t2.exe | FileCheck -check-prefix=X64 %s
-
-X86: DelayImport {
-X86-NEXT: Name: vars.dll
-X86-NEXT: Attributes: 0x1
-X86-NEXT: ModuleHandle: 0x1000
-X86-NEXT: ImportAddressTable: 0x1004
-X86-NEXT: ImportNameTable: 0x2000
-X86-NEXT: BoundDelayImportTable: 0x0
-X86-NEXT: UnloadDelayImportTable: 0x0
-X86-NEXT: Import {
-X86-NEXT: Symbol: _name_with_underscore (0)
-X86-NEXT: Address: 0x40501F
-X86-NEXT: }
-X86-NEXT: Import {
-X86-NEXT: Symbol: fn (1)
-X86-NEXT: Address: 0x405034
-X86-NEXT: }
-X86-NEXT: Import {
-X86-NEXT: Symbol: (1)
-X86-NEXT: Address: 0x405049
-X86-NEXT: }
-X86-NEXT: }
-
-X64: DelayImport {
-X64-NEXT: Name: vars64.dll
-X64-NEXT: Attributes: 0x1
-X64-NEXT: ModuleHandle: 0x1000
-X64-NEXT: ImportAddressTable: 0x1008
-X64-NEXT: ImportNameTable: 0x2000
-X64-NEXT: BoundDelayImportTable: 0x0
-X64-NEXT: UnloadDelayImportTable: 0x0
-X64-NEXT: Import {
-X64-NEXT: Symbol: _name_with_underscore (0)
-X64-NEXT: Address: 0x14000501F
-X64-NEXT: }
-X64-NEXT: Import {
-X64-NEXT: Symbol: fn (1)
-X64-NEXT: Address: 0x140005076
-X64-NEXT: }
-X64-NEXT: Import {
-X64-NEXT: Symbol: (1)
-X64-NEXT: Address: 0x1400050CD
-X64-NEXT: }
-X64-NEXT: }
diff --git a/test/pecoff/dll.test b/test/pecoff/dll.test
deleted file mode 100644
index 666e9f1152b0..000000000000
--- a/test/pecoff/dll.test
+++ /dev/null
@@ -1,7 +0,0 @@
-# RUN: yaml2obj %p/Inputs/nop.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t.exe /subsystem:console \
-# RUN: /entry:start /dll -- %t.obj
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-
-CHECK: IMAGE_FILE_DLL (0x2000)
diff --git a/test/pecoff/dosstub.test b/test/pecoff/dosstub.test
deleted file mode 100644
index f0458501704d..000000000000
--- a/test/pecoff/dosstub.test
+++ /dev/null
@@ -1,11 +0,0 @@
-# RUN: yaml2obj %p/Inputs/nop.obj.yaml > %t.obj
-
-# RUN: echo "MZ Hello world" > %t.stub
-# RUN: lld -flavor link /out:%t.exe /entry:start /subsystem:console \
-# RUN: /stub:%t.stub -- %t.obj
-# RUN: FileCheck -check-prefix=FILE %s < %t.exe
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=READOBJ %s
-
-FILE: MZ Hello world
-
-READOBJ: Format: COFF-i386
diff --git a/test/pecoff/drectve.test b/test/pecoff/drectve.test
deleted file mode 100644
index 258f608e5dff..000000000000
--- a/test/pecoff/drectve.test
+++ /dev/null
@@ -1,39 +0,0 @@
-# Test if the linker can properly parse the .drectve section contents.
-# "drectve.obj" contains "/defaultlib:vars /subsystem:console,42.195 -?foo"
-# in its .drectve section.
-
-# RUN: yaml2obj %p/Inputs/drectve.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t.exe /entry:main /opt:noref /libpath:%p/Inputs \
-# RUN: -- %t.obj >& %t.log
-#
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=HEADER %s
-# RUN: llvm-objdump -p %t.exe | FileCheck -check-prefix=IMPORT %s
-# RUN: echo >> %t.log
-# RUN: FileCheck -check-prefix=ERROR %s < %t.log
-
-HEADER: MajorOperatingSystemVersion: 42
-HEADER: MinorOperatingSystemVersion: 195
-
-IMPORT: DLL Name: vars.dll
-IMPORT-NEXT: Hint/Ord Name
-IMPORT-NEXT: 0 _name_with_underscore
-IMPORT-NEXT: 1 fn
-IMPORT-NEXT: 1
-
-ERROR-NOT: foo
-
-
-# drectve2.obj contains "/include:foo".
-# RUN: yaml2obj %p/Inputs/drectve2.obj.yaml > %t2.obj
-# RUN: not lld -flavor link /out:%t2.exe /entry:main -- %t2.obj >& %t2.log
-# RUN: FileCheck -check-prefix=UNDEF2 %s < %t2.log
-
-UNDEF2: Undefined symbol: {{.*}}: foo
-
-# drectve4.lib contains "/include:bar".
-# RUN: not lld -flavor link /force /out:%t3.exe /entry:main /include:_fn1 -- \
-# RUN: %t2.obj %p/Inputs/drectve3.lib >& %t3.log
-# RUN: FileCheck -check-prefix=UNDEF3 %s < %t3.log
-
-UNDEF3: Undefined symbol: {{.*}}: bar
diff --git a/test/pecoff/dynamic.test b/test/pecoff/dynamic.test
deleted file mode 100644
index 6b9a945b1fc5..000000000000
--- a/test/pecoff/dynamic.test
+++ /dev/null
@@ -1,11 +0,0 @@
-# RUN: yaml2obj %p/Inputs/vars-main-x86.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /entry:main /opt:noref \
-# RUN: -- %t.obj %p/Inputs/vars.lib
-# RUN: llvm-objdump -p %t.exe | FileCheck %s
-
-CHECK: DLL Name: vars.dll
-CHECK-NEXT: Hint/Ord Name
-CHECK-NEXT: 0 _name_with_underscore
-CHECK-NEXT: 1 fn
-CHECK-NEXT: 1
diff --git a/test/pecoff/dynamicbase.test b/test/pecoff/dynamicbase.test
deleted file mode 100644
index 9ed795b99db9..000000000000
--- a/test/pecoff/dynamicbase.test
+++ /dev/null
@@ -1,24 +0,0 @@
-# RUN: yaml2obj %p/Inputs/hello.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t1.exe /subsystem:console /force -- %t.obj
-# RUN: llvm-readobj -file-headers %t1.exe | FileCheck %s \
-# RUN: --check-prefix=DYNAMICBASE
-#
-# RUN: lld -flavor link /out:%t2.exe /subsystem:console /force /dynamicbase:no \
-# RUN: -- %t.obj
-# RUN: llvm-readobj -file-headers %t2.exe | FileCheck %s \
-# RUN: --check-prefix=NODYNAMICBASE
-#
-# RUN: lld -flavor link /out:%t3.exe /subsystem:console /force /fixed -- %t.obj
-# RUN: llvm-readobj -file-headers %t3.exe | FileCheck %s \
-# RUN: --check-prefix=NODYNAMICBASE
-#
-# RUN: not lld -flavor link /out:%t4.exe /subsystem:console /force /fixed \
-# RUN: /dynamicbase -- %t.obj 2> %t.err
-# RUN: FileCheck %s --check-prefix=DYNAMIC-AND-FIXED < %t.err
-
-DYNAMICBASE: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE
-
-NODYNAMICBASE-NOT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE
-
-DYNAMIC-AND-FIXED: /dynamicbase must not be specified with /fixed
diff --git a/test/pecoff/entry.test b/test/pecoff/entry.test
deleted file mode 100644
index b48e5a038293..000000000000
--- a/test/pecoff/entry.test
+++ /dev/null
@@ -1,41 +0,0 @@
-# REQUIRES: asserts
-
-# RUN: yaml2obj %p/Inputs/entry.obj.yaml > %t.obj
-
-# RUN: not lld -flavor link /out:%t.exe /alternatename:_main=_foo \
-# RUN: -- %t.obj 2> %t.log
-# RUN: FileCheck -check-prefix=MAIN %s < %t.log
-
-MAIN: _mainCRTStartup
-
-# RUN: not lld -flavor link /out:%t.exe /alternatename:_wmain=_foo \
-# RUN: -- %t.obj 2> %t.log
-# RUN: FileCheck -check-prefix=WMAIN %s < %t.log
-
-WMAIN: _wmainCRTStartup
-
-# RUN: not lld -flavor link /out:%t.exe /alternatename:_WinMain=_foo \
-# RUN: -- %t.obj 2> %t.log
-# RUN: FileCheck -check-prefix=WINMAIN %s < %t.log
-# RUN: not lld -flavor link /out:%t.exe /alternatename:_WinMain@16=_foo \
-# RUN: -- %t.obj 2> %t.log
-# RUN: FileCheck -check-prefix=WINMAIN %s < %t.log
-
-WINMAIN: _WinMainCRTStartup
-
-# RUN: not lld -flavor link /out:%t.exe /alternatename:_wWinMain=_foo \
-# RUN: -- %t.obj 2> %t.log
-# RUN: FileCheck -check-prefix=WWINMAIN %s < %t.log
-
-WWINMAIN: _wWinMainCRTStartup
-
-# RUN: lld -flavor link /out:%t.exe /alternatename:_main=_foo \
-# RUN: /alternatename:_mainCRTStartup=_bar -- %t.obj
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=MAINADDR %s
-
-MAINADDR: AddressOfEntryPoint: 0x1004
-
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /entry:baz -- %t.obj
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=MANGLE %s
-
-MANGLE: AddressOfEntryPoint: 0x1004
diff --git a/test/pecoff/export-warning.test b/test/pecoff/export-warning.test
deleted file mode 100644
index 5c7647de00bd..000000000000
--- a/test/pecoff/export-warning.test
+++ /dev/null
@@ -1,19 +0,0 @@
-# RUN: yaml2obj %p/Inputs/export.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t1.dll /dll /entry:init \
-# RUN: /export:exportfn1 /export:exportfn1 -- %t.obj 2> %t1.log
-# RUN: echo >> %t1.log
-# RUN: FileCheck -check-prefix=CHECK1 %s < %t1.log
-CHECK1-NOT: Export symbol '_exportfn1' specified more than once.
-
-# RUN: lld -flavor link /out:%t2.dll /dll /entry:init \
-# RUN: /export:exportfn1 /export:exportfn1,@5 -- %t.obj 2> %t2.log
-# RUN: echo >> %t2.log
-# RUN: FileCheck -check-prefix=CHECK2 %s < %t2.log
-CHECK2: Export symbol '_exportfn1' specified more than once.
-
-# RUN: lld -flavor link /out:%t3.dll /dll /entry:init \
-# RUN: /export:exportfn1,@8 /export:exportfn1,@5 -- %t.obj 2> %t3.log
-# RUN: echo >> %t3.log
-# RUN: FileCheck -check-prefix=CHECK3 %s < %t3.log
-CHECK3: Export symbol '_exportfn1' specified more than once.
diff --git a/test/pecoff/export.test b/test/pecoff/export.test
deleted file mode 100644
index 63b8677cd4b7..000000000000
--- a/test/pecoff/export.test
+++ /dev/null
@@ -1,90 +0,0 @@
-# RUN: yaml2obj %p/Inputs/export.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t1.dll /dll /entry:init \
-# RUN: /export:exportfn1 /export:exportfn2 -- %t.obj
-# RUN: llvm-objdump -p %t1.dll | FileCheck -check-prefix=CHECK1 %s
-
-CHECK1: Export Table:
-CHECK1: DLL name: export.test.tmp1.dll
-CHECK1: Ordinal RVA Name
-CHECK1-NEXT: 1 0x2008 exportfn1
-CHECK1-NEXT: 2 0x2010 exportfn2
-
-# RUN: lld -flavor link /out:%t2.dll /dll /subsystem:console /entry:init \
-# RUN: /export:exportfn1,@5 /export:exportfn2 -- %t.obj
-# RUN: llvm-objdump -p %t2.dll | FileCheck -check-prefix=CHECK2 %s
-
-CHECK2: Export Table:
-CHECK2: DLL name: export.test.tmp2.dll
-CHECK2: Ordinal RVA Name
-CHECK2-NEXT: 5 0x2008 exportfn1
-CHECK2-NEXT: 6 0x2010 exportfn2
-
-# RUN: lld -flavor link /out:%t3.dll /dll /subsystem:console /entry:init \
-# RUN: /export:exportfn1,@5,noname /export:exportfn2 -- %t.obj
-# RUN: llvm-objdump -p %t3.dll | FileCheck -check-prefix=CHECK3 %s
-
-CHECK3: Export Table:
-CHECK3: DLL name: export.test.tmp3.dll
-CHECK3: Ordinal RVA Name
-CHECK3-NEXT: 5 0x2008
-CHECK3-NEXT: 6 0x2010 exportfn2
-
-# RUN: lld -flavor link /out:%t4.dll /dll /entry:init \
-# RUN: /def:%p/Inputs/exports.def -- %t.obj
-# RUN: llvm-objdump -p %t4.dll | FileCheck -check-prefix=CHECK4 %s
-
-CHECK4: Export Table:
-CHECK4: DLL name: export.test.tmp4.dll
-CHECK4: Ordinal RVA Name
-CHECK4-NEXT: 5 0x2008 exportfn1
-CHECK4-NEXT: 6 0x2010 exportfn2
-CHECK4-NEXT: 7 0x2010 exportfn3@256
-CHECK4-NEXT: 8 0x2010 exportfn5
-
-# RUN: lld -flavor link /out:%t5.dll /dll /entry:init \
-# RUN: /export:exportfn7 -- %t.obj
-# RUN: llvm-objdump -p %t5.dll | FileCheck -check-prefix=CHECK5 %s
-
-CHECK5: Export Table:
-CHECK5: DLL name: export.test.tmp5.dll
-CHECK5: Ordinal RVA Name
-CHECK5-NEXT: 1 0x2010 exportfn3@256
-CHECK5-NEXT: 2 0x2010 exportfn7
-
-# RUN: lld -flavor link /out:%t6.dll /dll /entry:init \
-# RUN: /export:exportfn8 -- %t.obj
-# RUN: llvm-objdump -p %t6.dll | FileCheck -check-prefix=CHECK6 %s
-
-CHECK6: Export Table:
-CHECK6: DLL name: export.test.tmp6.dll
-CHECK6: Ordinal RVA Name
-CHECK6-NEXT: 1 0x2010 exportfn3@256
-CHECK6-NEXT: 2 0x2010 exportfn8
-
-# RUN: lld -flavor link /out:%t7.dll /dll /entry:init \
-# RUN: /export:exportfn7 /export:exportfn7@8 \
-# RUN: /export:exportfn8 /export:exportfn8 /export:exportfn3 -- %t.obj
-# RUN: llvm-objdump -p %t7.dll | FileCheck -check-prefix=DUP %s
-
-DUP: Export Table:
-DUP: DLL name: export.test.tmp7.dll
-DUP: Ordinal RVA Name
-DUP-NEXT: 1 0x2010 exportfn3
-DUP-NEXT: 2 0x2010 exportfn7
-DUP-NEXT: 3 0x2010 exportfn8
-DUP-NOT: ?exportfn8@@YAXXZ
-DUP-NOT: exportfn3@256
-
-# RUN: yaml2obj %p/Inputs/export.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t8.dll /dll /entry:init \
-# RUN: /export:f1=exportfn1 /export:f2@4=exportfn2,private -- %t.obj
-# RUN: llvm-objdump -p %t8.dll | FileCheck -check-prefix=EQUAL %s
-
-EQUAL: Export Table:
-EQUAL: DLL name: export.test.tmp8.dll
-EQUAL: Ordinal RVA Name
-EQUAL-NEXT: 1 0x2010 exportfn3@256
-EQUAL-NEXT: 2 0x2008 f1
-EQUAL-NEXT: 3 0x2010 f2{{$}}
diff --git a/test/pecoff/exportlib.test b/test/pecoff/exportlib.test
deleted file mode 100644
index b65751cfebd7..000000000000
--- a/test/pecoff/exportlib.test
+++ /dev/null
@@ -1,32 +0,0 @@
-# REQUIRES: winlib
-
-# RUN: yaml2obj %p/Inputs/export.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t.dll /dll /entry:init \
-# RUN: /export:exportfn1 /export:exportfn2 -- %t.obj
-# RUN: llvm-readobj %t.lib | FileCheck %s
-
-CHECK: File: exportlib.test.tmp.dll
-CHECK: Format: COFF-i386
-CHECK: Arch: i386
-CHECK: AddressSize: 32bit
-
-CHECK: File: exportlib.test.tmp.dll
-CHECK: Format: COFF-i386
-CHECK: Arch: i386
-CHECK: AddressSize: 32bit
-
-CHECK: File: exportlib.test.tmp.dll
-CHECK: Format: COFF-i386
-CHECK: Arch: i386
-CHECK: AddressSize: 32bit
-
-CHECK: File: exportlib.test.tmp.dll
-CHECK: Format: COFF-<unknown arch>
-CHECK: Arch: unknown
-CHECK: AddressSize: 32bit
-
-CHECK: File: exportlib.test.tmp.dll
-CHECK: Format: COFF-<unknown arch>
-CHECK: Arch: unknown
-CHECK: AddressSize: 32bit
diff --git a/test/pecoff/exportlib2.test b/test/pecoff/exportlib2.test
deleted file mode 100644
index e846b0bdd064..000000000000
--- a/test/pecoff/exportlib2.test
+++ /dev/null
@@ -1,21 +0,0 @@
-# RUN: yaml2obj %p/Inputs/export.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t.dll /dll /entry:init \
-# RUN: /export:exportfn1 /export:exportfn2 /lldmoduledeffile:%t1.def -- %t.obj
-# RUN: FileCheck -check-prefix=CHECK1 %s < %t1.def
-
-CHECK1: LIBRARY "exportlib2.test.tmp.dll"
-CHECK1: EXPORTS
-CHECK1: exportfn1 @1
-CHECK1: exportfn2 @2
-CHECK1: exportfn3@256 @3
-
-# RUN: lld -flavor link /out:%t.dll /dll /entry:init \
-# RUN: /def:%p/Inputs/exports2.def /lldmoduledeffile:%t2.def -- %t.obj
-# RUN: FileCheck -check-prefix=CHECK2 %s < %t2.def
-
-CHECK2: LIBRARY "exportlib2.test.tmp.dll"
-CHECK2: EXPORTS
-CHECK2: exportfn1 @5
-CHECK2: exportfn3@256 @6
-CHECK2: exportfn7@8 @7
diff --git a/test/pecoff/grouped-sections.test b/test/pecoff/grouped-sections.test
deleted file mode 100644
index 40ae1478997e..000000000000
--- a/test/pecoff/grouped-sections.test
+++ /dev/null
@@ -1,17 +0,0 @@
-# RUN: yaml2obj %p/Inputs/grouped-sections.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /entry:main -- %t.obj
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-#
-# The file "grouped-sections.obj" has three data sections in the following
-# order:
-#
-# .data$2
-# .data$1
-# .data
-#
-# If all the sections will be merged correctly, the resulting ".data"
-# section will have the string "Hello, world".
-
-CHECK: Contents of section .data:
-CHECK-NEXT: Hello, world
diff --git a/test/pecoff/hello.test b/test/pecoff/hello.test
deleted file mode 100644
index 679b8b3ad984..000000000000
--- a/test/pecoff/hello.test
+++ /dev/null
@@ -1,51 +0,0 @@
-# RUN: yaml2obj %p/Inputs/hello.obj.yaml > %t.obj
-
-# RUN: lld -flavor link /out:%t1.exe /subsystem:console /force -- %t.obj
-# RUN: llvm-readobj -file-headers %t1.exe | FileCheck -check-prefix=FILE %s
-
-FILE: ImageOptionalHeader {
-FILE: SizeOfInitializedData: 1024
-FILE: SizeOfHeaders: 512
-FILE: }
-
-# RUN: lld -flavor link /out:%t2.exe /subsystem:console /force -- %t.obj
-# RUN: llvm-readobj -sections %t2.exe | FileCheck -check-prefix=SECTIONS %s
-
-SECTIONS: Format: COFF-i386
-SECTIONS-NEXT: Arch: i386
-SECTIONS-NEXT: AddressSize: 32bit
-SECTIONS-NEXT: Sections [
-SECTIONS-NEXT: Section {
-SECTIONS-NEXT: Number: 1
-SECTIONS-NEXT: Name: .data
-SECTIONS-NEXT: VirtualSize: 0x12
-SECTIONS-NEXT: VirtualAddress: 0x1000
-SECTIONS-NEXT: RawDataSize: 512
-SECTIONS-NEXT: PointerToRawData: 0x200
-SECTIONS-NEXT: PointerToRelocations: 0x0
-SECTIONS-NEXT: PointerToLineNumbers: 0x0
-SECTIONS-NEXT: RelocationCount: 0
-SECTIONS-NEXT: LineNumberCount: 0
-SECTIONS-NEXT: Characteristics [
-SECTIONS-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA
-SECTIONS-NEXT: IMAGE_SCN_MEM_READ
-SECTIONS-NEXT: IMAGE_SCN_MEM_WRITE
-SECTIONS-NEXT: ]
-SECTIONS-NEXT: }
-SECTIONS-NEXT: Section {
-SECTIONS-NEXT: Number: 2
-SECTIONS-NEXT: Name: .text (2E 74 65 78 74 00 00 00)
-SECTIONS-NEXT: VirtualSize: 0x1C
-SECTIONS-NEXT: VirtualAddress: 0x2000
-SECTIONS-NEXT: RawDataSize: 512
-SECTIONS-NEXT: PointerToRawData: 0x400
-SECTIONS-NEXT: PointerToRelocations: 0x0
-SECTIONS-NEXT: PointerToLineNumbers: 0x0
-SECTIONS-NEXT: RelocationCount: 0
-SECTIONS-NEXT: LineNumberCount: 0
-SECTIONS-NEXT: Characteristics [
-SECTIONS-NEXT: IMAGE_SCN_CNT_CODE
-SECTIONS-NEXT: IMAGE_SCN_MEM_EXECUTE
-SECTIONS-NEXT: IMAGE_SCN_MEM_READ
-SECTIONS-NEXT: ]
-SECTIONS-NEXT: }
diff --git a/test/pecoff/hello64.test b/test/pecoff/hello64.test
deleted file mode 100644
index 7536e5a8fd26..000000000000
--- a/test/pecoff/hello64.test
+++ /dev/null
@@ -1,22 +0,0 @@
-# REQUIRES: x86
-
-# RUN: yaml2obj %p/Inputs/hello64.obj.yaml > %t.obj
-
-# RUN: lld -flavor link /out:%t.exe /subsystem:windows /machine:x64 \
-# RUN: /entry:main -- %t.obj %p/Inputs/hello64lib.lib
-# RUN: llvm-objdump -disassemble %t.exe | FileCheck %s
-
-CHECK: 6000: 48 83 ec 28 subq $40, %rsp
-CHECK: 6004: 48 c7 c1 00 00 00 00 movq $0, %rcx
-CHECK: 600b: 48 8d 15 f4 af ff ff leaq -20492(%rip), %rdx
-CHECK: 6012: 4c 8d 05 e7 af ff ff leaq -20505(%rip), %r8
-CHECK: 6019: 41 b9 00 00 00 00 movl $0, %r9d
-CHECK: 601f: e8 12 00 00 00 callq 18
-CHECK: 6024: b9 00 00 00 00 movl $0, %ecx
-CHECK: 6029: e8 00 00 00 00 callq 0
-CHECK: 602e: ff 25 cc cf ff ff jmpq *-12340(%rip)
-CHECK: 6034: cc int3
-CHECK: 6035: cc int3
-CHECK: 6036: ff 25 cc cf ff ff jmpq *-12340(%rip)
-CHECK: 603c: cc int3
-CHECK: 603d: cc int3
diff --git a/test/pecoff/help.test b/test/pecoff/help.test
deleted file mode 100644
index f5e9c358f1a8..000000000000
--- a/test/pecoff/help.test
+++ /dev/null
@@ -1,4 +0,0 @@
-# RUN: not lld -flavor link /help | FileCheck %s
-# RUN: not lld -flavor link '/?' | FileCheck %s
-
-CHECK: USAGE
diff --git a/test/pecoff/imagebase.test b/test/pecoff/imagebase.test
deleted file mode 100644
index bb83e6b66124..000000000000
--- a/test/pecoff/imagebase.test
+++ /dev/null
@@ -1,15 +0,0 @@
-# REQUIRES: x86
-
-# RUN: yaml2obj %p/Inputs/imagebase.obj.yaml > %t.obj
-
-# RUN: lld -flavor link /out:%t1.exe /subsystem:console /entry:_start \
-# RUN: /opt:noref -- %t.obj
-# RUN: llvm-objdump -disassemble %t1.exe | FileCheck -check-prefix=DEFAULT %s
-
-DEFAULT: a1 00 00 40 00 movl 4194304, %eax
-
-# RUN: lld -flavor link /out:%t2.exe /subsystem:console /entry:_start \
-# RUN: /base:65536 /opt:noref -- %t.obj
-# RUN: llvm-objdump -disassemble %t2.exe | FileCheck -check-prefix=BASE %s
-
-BASE: a1 00 00 01 00 movl 65536, %eax
diff --git a/test/pecoff/importlib.test b/test/pecoff/importlib.test
deleted file mode 100644
index 28e74f9dc78d..000000000000
--- a/test/pecoff/importlib.test
+++ /dev/null
@@ -1,55 +0,0 @@
-# REQUIRES: x86
-
-# Verify that lld can handle .lib files. "main.obj" refers "var" and
-# "fn" defined in "vars.lib".
-#
-# RUN: yaml2obj %p/Inputs/vars-main-x86.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t1.exe /subsystem:console /entry:main /opt:noref \
-# RUN: -- %t.obj %p/Inputs/vars.lib
-# RUN: llvm-objdump -d %t1.exe | FileCheck -check-prefix=TEXT %s
-# RUN: llvm-readobj -coff-imports %t1.exe | FileCheck -check-prefix=IMPORT %s
-#
-# RUN: lld -flavor link /out:%t2.exe /subsystem:console /entry:main /opt:noref \
-# RUN: /libpath:%p/Inputs -- %t.obj vars.lib
-# RUN: llvm-objdump -d %t2.exe | FileCheck -check-prefix=TEXT %s
-# RUN: llvm-readobj -coff-imports %t2.exe | FileCheck -check-prefix=IMPORT %s
-#
-# RUN: lld -flavor link /out:%t3.exe /subsystem:console /entry:main /opt:noref \
-# RUN: /libpath:%p/Inputs /defaultlib:vars.lib -- %t.obj
-# RUN: llvm-objdump -d %t3.exe | FileCheck -check-prefix=TEXT %s
-# RUN: llvm-readobj -coff-imports %t3.exe | FileCheck -check-prefix=IMPORT %s
-#
-# RUN: env LIB=%p/Inputs lld -flavor link /out:%t4.exe /subsystem:console \
-# RUN: /opt:noref /entry:main -- %t.obj vars.lib
-# RUN: llvm-objdump -d %t4.exe | FileCheck -check-prefix=TEXT %s
-# RUN: llvm-readobj -coff-imports %t4.exe | FileCheck -check-prefix=IMPORT %s
-#
-# RUN: env LINK="/out:%t5.exe /subsystem:console /entry:main /opt:noref \
-# RUN: -- %t.obj" lld -flavor link %p/Inputs/vars.lib
-# RUN: llvm-objdump -d %t5.exe | FileCheck -check-prefix=TEXT %s
-# RUN: llvm-readobj -coff-imports %t5.exe | FileCheck -check-prefix=IMPORT %s
-
-TEXT: Disassembly of section .text:
-TEXT-NEXT: .text:
-TEXT-NEXT: pushl %ebp
-TEXT-NEXT: movl %esp, %ebp
-TEXT-NEXT: pushl %esi
-TEXT-NEXT: calll *{{[0-9]+}}
-TEXT-NEXT: movl {{[0-9]+}}, %ecx
-TEXT-NEXT: movl (%ecx), %esi
-TEXT-NEXT: addl %eax, %esi
-TEXT-NEXT: calll *{{[0-9]+}}
-TEXT-NEXT: addl %esi, %eax
-TEXT-NEXT: popl %esi
-TEXT-NEXT: popl %ebp
-TEXT-NEXT: ret
-
-IMPORT: Import {
-IMPORT-NEXT: Name: vars.dll
-IMPORT-NEXT: ImportLookupTableRVA: 0x4000
-IMPORT-NEXT: ImportAddressTableRVA: 0x2000
-IMPORT-NEXT: Symbol: _name_with_underscore (0)
-IMPORT-NEXT: Symbol: fn (1)
-IMPORT-NEXT: Symbol: (1)
-IMPORT-NEXT: }
diff --git a/test/pecoff/include.test b/test/pecoff/include.test
deleted file mode 100644
index bee1f48bf1a7..000000000000
--- a/test/pecoff/include.test
+++ /dev/null
@@ -1,8 +0,0 @@
-# RUN: yaml2obj %p/Inputs/nop.obj.yaml > %t.obj
-#
-# RUN: not lld -flavor link /out:%t.exe /include:sym1 /include:sym2 \
-# RUN: /subsystem:console -- %t.obj 2> %t.log
-# RUN: FileCheck %s < %t.log
-
-CHECK: Undefined symbol: <command line option /include>: sym1
-CHECK: Undefined symbol: <command line option /include>: sym2
diff --git a/test/pecoff/lib.test b/test/pecoff/lib.test
deleted file mode 100644
index f435c117bc46..000000000000
--- a/test/pecoff/lib.test
+++ /dev/null
@@ -1,15 +0,0 @@
-# REQUIRES: x86
-
-# Verify that lld can handle a library file.
-#
-# RUN: yaml2obj %p/Inputs/main.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /entry:main /opt:noref \
-# RUN: -- %t.obj %p/Inputs/static.lib
-# RUN: llvm-objdump -d %t.exe | FileCheck %s
-
-CHECK: Disassembly of section .text:
-CHECK-NEXT: .text:
-CHECK-NEXT: movl 4198400, %eax
-CHECK-NEXT: addl 4198404, %eax
-CHECK-NEXT: ret
diff --git a/test/pecoff/libarg.test b/test/pecoff/libarg.test
deleted file mode 100644
index 314f030c4fe0..000000000000
--- a/test/pecoff/libarg.test
+++ /dev/null
@@ -1,9 +0,0 @@
-# REQUIRES: winlib
-#
-# If argv[1] == "/lib", link.exe morphs into lib.exe.
-#
-# RUN: lld -flavor link /lib >& %t.log
-# RUN: FileCheck %s < %t.log
-
-CHECK-NOT: unrecognized option '/lib'
-CHECK: usage: LIB
diff --git a/test/pecoff/localyimported.test b/test/pecoff/localyimported.test
deleted file mode 100644
index 52b32d7b80bd..000000000000
--- a/test/pecoff/localyimported.test
+++ /dev/null
@@ -1,15 +0,0 @@
-# RUN: yaml2obj %p/Inputs/hello.obj.yaml > %t.obj
-#
-# RUN: not lld -flavor link /out:%t.exe /include:__imp__nosuchsym %t.obj \
-# RUN: >& %t.log
-# RUN: FileCheck -check-prefix=X86 %s < %t.log
-
-X86: Undefined symbol: __imp__nosuchsym: _nosuchsym
-
-# RUN: yaml2obj %p/Inputs/hello64.obj.yaml > %t2.obj
-#
-# RUN: not lld -flavor link /out:%t2.exe /include:__imp__nosuchsym %t2.obj \
-# RUN: /machine:x64 >& %t2.log
-# RUN: FileCheck -check-prefix=X64 %s < %t2.log
-
-X64: Undefined symbol: __imp__nosuchsym: _nosuchsym
diff --git a/test/pecoff/long-section-name.test b/test/pecoff/long-section-name.test
deleted file mode 100644
index e6721c28302f..000000000000
--- a/test/pecoff/long-section-name.test
+++ /dev/null
@@ -1,7 +0,0 @@
-# RUN: yaml2obj %p/Inputs/nop.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /entry:start \
-# RUN: /merge:.text=.longsectionname -- %t.obj
-# RUN: llvm-readobj -sections %t.exe | FileCheck %s
-
-CHECK: Name: .longsectionname (2F 34 00 00 00 00 00 00)
diff --git a/test/pecoff/machinetype.test b/test/pecoff/machinetype.test
deleted file mode 100644
index 5d387f3b0393..000000000000
--- a/test/pecoff/machinetype.test
+++ /dev/null
@@ -1,13 +0,0 @@
-# RUN: yaml2obj %p/Inputs/machine-type-unknown.obj.yaml > %t1.obj
-# RUN: yaml2obj %p/Inputs/hello.obj.yaml > %t2.obj
-# RUN: yaml2obj %p/Inputs/hello64.obj.yaml > %t3.obj
-
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /force -- %t1.obj %t2.obj
-# RUN: llvm-readobj %t.exe | FileCheck -check-prefix=X86 %s
-
-X86: Arch: i386
-
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /force -- %t1.obj %t3.obj
-# RUN: llvm-readobj %t.exe | FileCheck -check-prefix=X64 %s
-
-X64: Arch: x86_64
diff --git a/test/pecoff/manifest.test b/test/pecoff/manifest.test
deleted file mode 100644
index 33229a45516b..000000000000
--- a/test/pecoff/manifest.test
+++ /dev/null
@@ -1,63 +0,0 @@
-# RUN: yaml2obj %p/Inputs/nop.obj.yaml > %t.obj
-
-# RUN: lld -flavor link /out:%t1.exe /subsystem:console /force \
-# RUN: -- %t.obj
-# RUN: FileCheck -check-prefix=MANIFEST %s < %t1.exe.manifest
-
-MANIFEST: <?xml version="1.0" standalone="yes"?>
-MANIFEST: <assembly xmlns="urn:schemas-microsoft-com:asm.v1"
-MANIFEST: manifestVersion="1.0">
-MANIFEST: <trustInfo>
-MANIFEST: <security>
-MANIFEST: <requestedPrivileges>
-MANIFEST: <requestedExecutionLevel level='asInvoker' uiAccess='false'/>
-MANIFEST: </requestedPrivileges>
-MANIFEST: </security>
-MANIFEST: </trustInfo>
-MANIFEST: </assembly>
-
-# RUN: lld -flavor link /out:%t2.exe /subsystem:console /force \
-# RUN: /manifestuac:"level='requireAdministrator' uiAccess='true'" -- %t.obj
-# RUN: FileCheck -check-prefix=UAC %s < %t2.exe.manifest
-
-UAC: <?xml version="1.0" standalone="yes"?>
-UAC: <assembly xmlns="urn:schemas-microsoft-com:asm.v1"
-UAC: manifestVersion="1.0">
-UAC: <trustInfo>
-UAC: <security>
-UAC: <requestedPrivileges>
-UAC: <requestedExecutionLevel level='requireAdministrator' uiAccess='true'/>
-UAC: </requestedPrivileges>
-UAC: </security>
-UAC: </trustInfo>
-UAC: </assembly>
-
-# RUN: lld -flavor link /out:%t3.exe /subsystem:console /force \
-# RUN: /manifestdependency:"foo='bar'" -- %t.obj
-# RUN: FileCheck -check-prefix=DEPENDENCY %s < %t3.exe.manifest
-
-DEPENDENCY: <?xml version="1.0" standalone="yes"?>
-DEPENDENCY: <assembly xmlns="urn:schemas-microsoft-com:asm.v1"
-DEPENDENCY: manifestVersion="1.0">
-DEPENDENCY: <trustInfo>
-DEPENDENCY: <security>
-DEPENDENCY: <requestedPrivileges>
-DEPENDENCY: <requestedExecutionLevel level='asInvoker' uiAccess='false'/>
-DEPENDENCY: </requestedPrivileges>
-DEPENDENCY: </security>
-DEPENDENCY: </trustInfo>
-DEPENDENCY: <dependency>
-DEPENDENCY: <dependentAssembly>
-DEPENDENCY: <assemblyIdentity foo='bar' />
-DEPENDENCY: </dependentAssembly>
-DEPENDENCY: </dependency>
-DEPENDENCY: </assembly>
-
-# RUN: lld -flavor link /out:%t4.exe /subsystem:console /force \
-# RUN: /manifestuac:no -- %t.obj
-# RUN: FileCheck -check-prefix=NOUAC %s < %t4.exe.manifest
-
-NOUAC: <?xml version="1.0" standalone="yes"?>
-NOUAC: <assembly xmlns="urn:schemas-microsoft-com:asm.v1"
-NOUAC: manifestVersion="1.0">
-NOUAC: </assembly>
diff --git a/test/pecoff/merge-largest.test b/test/pecoff/merge-largest.test
deleted file mode 100644
index c3ee96ca9c53..000000000000
--- a/test/pecoff/merge-largest.test
+++ /dev/null
@@ -1,24 +0,0 @@
-# RUN: yaml2obj %p/Inputs/merge-largest1.obj.yaml > %t1.obj
-# RUN: yaml2obj %p/Inputs/merge-largest2.obj.yaml > %t2.obj
-#
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /opt:noref /force \
-# RUN: -- %t1.obj %t2.obj 2>&1 > %t.log
-#
-# FileCheck complains if the input files is empty, so add a dummy line.
-# RUN: echo foo >> %t.log
-# RUN: FileCheck -check-prefix=STDERR %s < %t.log
-#
-# RUN: llvm-readobj -sections %t.exe | FileCheck -check-prefix=READOBJ %s
-
-STDERR-NOT: duplicate symbol error
-
-READOBJ: Format: COFF-i386
-READOBJ-NEXT: Arch: i386
-READOBJ-NEXT: AddressSize: 32bit
-READOBJ-NEXT: Sections [
-READOBJ-NEXT: Section {
-READOBJ-NEXT: Number: 1
-READOBJ-NEXT: Name: .text (2E 74 65 78 74 00 00 00)
-READOBJ-NEXT: VirtualSize: 0x8
-READOBJ-NEXT: VirtualAddress: 0x1000
-READOBJ-NEXT: RawDataSize: 512
diff --git a/test/pecoff/merge-same-size.test b/test/pecoff/merge-same-size.test
deleted file mode 100644
index c2918a2bc1a4..000000000000
--- a/test/pecoff/merge-same-size.test
+++ /dev/null
@@ -1,32 +0,0 @@
-# RUN: yaml2obj %p/Inputs/merge-same-size1.obj.yaml > %t1.obj
-# RUN: yaml2obj %p/Inputs/merge-same-size2.obj.yaml > %t2.obj
-# RUN: yaml2obj %p/Inputs/merge-same-size3.obj.yaml > %t3.obj
-#
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /opt:noref /force \
-# RUN: -- %t1.obj %t2.obj > %t1.log 2>&1
-#
-# FileCheck complains if the input files is empty, so add a dummy line.
-# RUN: echo foo >> %t1.log
-# RUN: FileCheck -check-prefix=SAMESIZE %s < %t1.log
-#
-# RUN: not lld -flavor link /out:%t.exe /subsystem:console /opt:noref /force \
-# RUN: -- %t1.obj %t3.obj > %t2.log 2>&1
-# RUN: FileCheck -check-prefix=DIFFERENT %s < %t2.log
-#
-# RUN: llvm-readobj -sections %t.exe | FileCheck -check-prefix=READOBJ %s
-
-SAMESIZE-NOT: duplicate symbol error
-
-DIFFERENT: Size mismatch
-DIFFERENT: duplicate symbol error
-
-READOBJ: Format: COFF-i386
-READOBJ-NEXT: Arch: i386
-READOBJ-NEXT: AddressSize: 32bit
-READOBJ-NEXT: Sections [
-READOBJ-NEXT: Section {
-READOBJ-NEXT: Number: 1
-READOBJ-NEXT: Name: .text (2E 74 65 78 74 00 00 00)
-READOBJ-NEXT: VirtualSize: 0x7
-READOBJ-NEXT: VirtualAddress: 0x1000
-READOBJ-NEXT: RawDataSize: 512
diff --git a/test/pecoff/multi.test b/test/pecoff/multi.test
deleted file mode 100644
index e0bfdba6dda4..000000000000
--- a/test/pecoff/multi.test
+++ /dev/null
@@ -1,17 +0,0 @@
-# REQUIRES: x86
-
-# Verify that lld can handle multiple input files.
-#
-# RUN: yaml2obj %p/Inputs/main.obj.yaml > %t1.obj
-# RUN: yaml2obj %p/Inputs/static-data1.obj.yaml > %t2.obj
-# RUN: yaml2obj %p/Inputs/static-data2.obj.yaml > %t3.obj
-#
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /entry:main /opt:noref \
-# RUN: -- %t1.obj %t2.obj %t3.obj
-# RUN: llvm-objdump -d %t.exe | FileCheck %s
-
-CHECK: Disassembly of section .text:
-CHECK: .text:
-CHECK: movl {{[0-9]+}}, %eax
-CHECK: addl {{[0-9]+}}, %eax
-CHECK: ret
diff --git a/test/pecoff/noentry.test b/test/pecoff/noentry.test
deleted file mode 100644
index 55b326dd84cb..000000000000
--- a/test/pecoff/noentry.test
+++ /dev/null
@@ -1,10 +0,0 @@
-# RUN: yaml2obj %p/Inputs/nop.obj.yaml > %t.obj
-# RUN: lld -flavor link /out:%t.exe /noentry /dll -- %t.obj
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-
-CHECK: AddressOfEntryPoint: 0x0
-
-# RUN: not lld -flavor link /out:%t.exe /noentry -- %t.obj >& %t.log
-# RUN: FileCheck --check-prefix=ERROR %s < %t.log
-
-ERROR: /noentry must be specified with /dll
diff --git a/test/pecoff/nonstandard-sections.test b/test/pecoff/nonstandard-sections.test
deleted file mode 100644
index 2ca181629230..000000000000
--- a/test/pecoff/nonstandard-sections.test
+++ /dev/null
@@ -1,75 +0,0 @@
-# RUN: yaml2obj %p/Inputs/nonstandard-sections.obj.yaml > %t.obj
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /force -- %t.obj
-# RUN: llvm-readobj -sections %t.exe | FileCheck %s
-
-CHECK: Arch: i386
-CHECK-NEXT: AddressSize: 32bit
-CHECK-NEXT: Sections [
-CHECK-NEXT: Section {
-CHECK-NEXT: Number: 1
-CHECK-NEXT: Name: .bar (2E 62 61 72 00 00 00 00)
-CHECK-NEXT: VirtualSize: 0x4
-CHECK-NEXT: VirtualAddress: 0x1000
-CHECK-NEXT: RawDataSize: 512
-CHECK-NEXT: PointerToRawData: 0x400
-CHECK-NEXT: PointerToRelocations: 0x0
-CHECK-NEXT: PointerToLineNumbers: 0x0
-CHECK-NEXT: RelocationCount: 0
-CHECK-NEXT: LineNumberCount: 0
-CHECK-NEXT: Characteristics [ (0x40000040)
-CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-CHECK-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-CHECK-NEXT: ]
-CHECK-NEXT: }
-CHECK-NEXT: Section {
-CHECK-NEXT: Number: 2
-CHECK-NEXT: Name: .data (2E 64 61 74 61 00 00 00)
-CHECK-NEXT: VirtualSize: 0x4
-CHECK-NEXT: VirtualAddress: 0x2000
-CHECK-NEXT: RawDataSize: 512
-CHECK-NEXT: PointerToRawData: 0x600
-CHECK-NEXT: PointerToRelocations: 0x0
-CHECK-NEXT: PointerToLineNumbers: 0x0
-CHECK-NEXT: RelocationCount: 0
-CHECK-NEXT: LineNumberCount: 0
-CHECK-NEXT: Characteristics [ (0xC0000040)
-CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-CHECK-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-CHECK-NEXT: IMAGE_SCN_MEM_WRITE (0x80000000)
-CHECK-NEXT: ]
-CHECK-NEXT: }
-CHECK-NEXT: Section {
-CHECK-NEXT: Number: 3
-CHECK-NEXT: Name: .foo (2E 66 6F 6F 00 00 00 00)
-CHECK-NEXT: VirtualSize: 0x4
-CHECK-NEXT: VirtualAddress: 0x3000
-CHECK-NEXT: RawDataSize: 512
-CHECK-NEXT: PointerToRawData: 0x800
-CHECK-NEXT: PointerToRelocations: 0x0
-CHECK-NEXT: PointerToLineNumbers: 0x0
-CHECK-NEXT: RelocationCount: 0
-CHECK-NEXT: LineNumberCount: 0
-CHECK-NEXT: Characteristics [ (0xC0000040)
-CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-CHECK-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-CHECK-NEXT: IMAGE_SCN_MEM_WRITE (0x80000000)
-CHECK-NEXT: ]
-CHECK-NEXT: }
-CHECK-NEXT: Section {
-CHECK-NEXT: Number: 4
-CHECK-NEXT: Name: .text (2E 74 65 78 74 00 00 00)
-CHECK-NEXT: VirtualSize: 0x4
-CHECK-NEXT: VirtualAddress: 0x4000
-CHECK-NEXT: RawDataSize: 512
-CHECK-NEXT: PointerToRawData: 0xA00
-CHECK-NEXT: PointerToRelocations: 0x0
-CHECK-NEXT: PointerToLineNumbers: 0x0
-CHECK-NEXT: RelocationCount: 0
-CHECK-NEXT: LineNumberCount: 0
-CHECK-NEXT: Characteristics [ (0x60000020)
-CHECK-NEXT: IMAGE_SCN_CNT_CODE (0x20)
-CHECK-NEXT: IMAGE_SCN_MEM_EXECUTE (0x20000000)
-CHECK-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-CHECK-NEXT: ]
-CHECK-NEXT: }
-CHECK-NEXT: ]
diff --git a/test/pecoff/options.test b/test/pecoff/options.test
deleted file mode 100644
index 3aca2c9fcc91..000000000000
--- a/test/pecoff/options.test
+++ /dev/null
@@ -1,40 +0,0 @@
-# Tests for miscellaneous command line options.
-
-# RUN: yaml2obj %p/Inputs/nop.obj.yaml > %t-x86.obj
-# RUN: yaml2obj %p/Inputs/nop64.obj.yaml > %t-x64.obj
-
-# RUN: lld -flavor link /align:8192 /out:%t.exe /entry:start \
-# RUN: /subsystem:console -- %t-x86.obj
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=ALIGN %s
-ALIGN: SectionAlignment: 8192
-
-# RUN: lld -flavor link /allowbind:no /out:%t.exe /entry:start \
-# RUN: /subsystem:console -- %t-x86.obj
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NOBIND %s
-NOBIND: IMAGE_DLL_CHARACTERISTICS_NO_BIND
-
-# RUN: lld -flavor link /allowisolation:no /out:%t.exe /entry:start \
-# RUN: /subsystem:console -- %t-x86.obj
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NOISO %s
-NOISO: IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION
-
-# RUN: lld -flavor link /swaprun:cd /out:%t.exe /entry:start \
-# RUN: /subsystem:console -- %t-x86.obj
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=RUNCD %s
-RUNCD: IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP
-
-# RUN: lld -flavor link /swaprun:net /out:%t.exe /entry:start \
-# RUN: /subsystem:console -- %t-x86.obj
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=RUNNET %s
-RUNNET: IMAGE_FILE_NET_RUN_FROM_SWAP
-
-# RUN: lld -flavor link /machine:x64 /force /highentropyva /out:%t.exe \
-# RUN: /entry:start /subsystem:console -- %t-x64.obj
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=ENT %s
-ENT: IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA
-
-# RUN: lld -flavor link /machine:x64 /force /highentropyva:no /out:%t.exe \
-# RUN: /entry:start /subsystem:console -- %t-x64.obj
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NOENT %s
-NOENT-NOT: IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA
-
diff --git a/test/pecoff/pe32plus.test b/test/pecoff/pe32plus.test
deleted file mode 100644
index 1c64e184cbaf..000000000000
--- a/test/pecoff/pe32plus.test
+++ /dev/null
@@ -1,87 +0,0 @@
-# RUN: yaml2obj %p/Inputs/nop64.obj.yaml > %t.obj
-
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /entry:start \
-# RUN: /machine:x64 -- %t.obj %p/Inputs/vars.lib
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-
-CHECK: Format: COFF-x86-64
-CHECK-NEXT: Arch: x86_64
-CHECK-NEXT: AddressSize: 64bit
-CHECK-NEXT: ImageFileHeader {
-CHECK-NEXT: Machine: IMAGE_FILE_MACHINE_AMD64 (0x8664)
-CHECK-NEXT: SectionCount: 5
-CHECK-NEXT: TimeDateStamp:
-CHECK-NEXT: PointerToSymbolTable: 0x0
-CHECK-NEXT: SymbolCount: 0
-CHECK-NEXT: OptionalHeaderSize: 240
-CHECK-NEXT: Characteristics [ (0x22)
-CHECK-NEXT: IMAGE_FILE_EXECUTABLE_IMAGE (0x2)
-CHECK-NEXT: IMAGE_FILE_LARGE_ADDRESS_AWARE (0x20)
-CHECK-NEXT: ]
-CHECK-NEXT: }
-CHECK-NEXT: ImageOptionalHeader {
-CHECK-NEXT: MajorLinkerVersion: 0
-CHECK-NEXT: MinorLinkerVersion: 0
-CHECK-NEXT: SizeOfCode: 512
-CHECK-NEXT: SizeOfInitializedData: 2048
-CHECK-NEXT: SizeOfUninitializedData: 0
-CHECK-NEXT: AddressOfEntryPoint: 0x5000
-CHECK-NEXT: BaseOfCode: 0x5000
-CHECK-NEXT: ImageBase: 0x140000000
-CHECK-NEXT: SectionAlignment: 4096
-CHECK-NEXT: FileAlignment: 512
-CHECK-NEXT: MajorOperatingSystemVersion: 6
-CHECK-NEXT: MinorOperatingSystemVersion: 0
-CHECK-NEXT: MajorImageVersion: 0
-CHECK-NEXT: MinorImageVersion: 0
-CHECK-NEXT: MajorSubsystemVersion: 6
-CHECK-NEXT: MinorSubsystemVersion: 0
-CHECK-NEXT: SizeOfImage: 24576
-CHECK-NEXT: SizeOfHeaders: 1024
-CHECK-NEXT: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3)
-CHECK-NEXT: Characteristics [ (0x8160)
-CHECK-NEXT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE (0x40)
-CHECK-NEXT: IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA (0x20)
-CHECK-NEXT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT (0x100)
-CHECK-NEXT: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE (0x8000)
-CHECK-NEXT: ]
-CHECK-NEXT: SizeOfStackReserve: 1048576
-CHECK-NEXT: SizeOfStackCommit: 4096
-CHECK-NEXT: SizeOfHeapReserve: 1048576
-CHECK-NEXT: SizeOfHeapCommit: 4096
-CHECK-NEXT: NumberOfRvaAndSize: 16
-CHECK-NEXT: DataDirectory {
-CHECK-NEXT: ExportTableRVA: 0x0
-CHECK-NEXT: ExportTableSize: 0x0
-CHECK-NEXT: ImportTableRVA: 0x3000
-CHECK-NEXT: ImportTableSize: 0x28
-CHECK-NEXT: ResourceTableRVA: 0x0
-CHECK-NEXT: ResourceTableSize: 0x0
-CHECK-NEXT: ExceptionTableRVA: 0x0
-CHECK-NEXT: ExceptionTableSize: 0x0
-CHECK-NEXT: CertificateTableRVA: 0x0
-CHECK-NEXT: CertificateTableSize: 0x0
-CHECK-NEXT: BaseRelocationTableRVA: 0x0
-CHECK-NEXT: BaseRelocationTableSize: 0x0
-CHECK-NEXT: DebugRVA: 0x0
-CHECK-NEXT: DebugSize: 0x0
-CHECK-NEXT: ArchitectureRVA: 0x0
-CHECK-NEXT: ArchitectureSize: 0x0
-CHECK-NEXT: GlobalPtrRVA: 0x0
-CHECK-NEXT: GlobalPtrSize: 0x0
-CHECK-NEXT: TLSTableRVA: 0x0
-CHECK-NEXT: TLSTableSize: 0x0
-CHECK-NEXT: LoadConfigTableRVA: 0x0
-CHECK-NEXT: LoadConfigTableSize: 0x0
-CHECK-NEXT: BoundImportRVA: 0x0
-CHECK-NEXT: BoundImportSize: 0x0
-CHECK-NEXT: IATRVA: 0x2000
-CHECK-NEXT: IATSize: 0x10
-CHECK-NEXT: DelayImportDescriptorRVA: 0x0
-CHECK-NEXT: DelayImportDescriptorSize: 0x0
-CHECK-NEXT: CLRRuntimeHeaderRVA: 0x0
-CHECK-NEXT: CLRRuntimeHeaderSize: 0x0
-CHECK-NEXT: ReservedRVA: 0x0
-CHECK-NEXT: ReservedSize: 0x0
-CHECK-NEXT: }
-CHECK-NEXT: }
diff --git a/test/pecoff/reloc.test b/test/pecoff/reloc.test
deleted file mode 100644
index 5a969e9beaa0..000000000000
--- a/test/pecoff/reloc.test
+++ /dev/null
@@ -1,16 +0,0 @@
-# REQUIRES: x86
-
-# RUN: yaml2obj %p/Inputs/reloc.obj.yaml > %t1.obj
-# RUN: yaml2obj %p/Inputs/abs.obj.yaml > %t2.obj
-#
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /force /opt:noref \
-# RUN: -- %t1.obj %t2.obj
-# RUN: llvm-objdump -d %t.exe | FileCheck %s
-
-CHECK: .text:
-CHECK: 3000: 68 02 00 00 00
-CHECK: 3005: 68 05 00 00 00
-CHECK: 300a: 68 00 10 40 00
-CHECK: 300f: 68 00 10 40 00
-CHECK: 3014: 68 00 20 40 00
-CHECK: 3019: 68 ef be ad de
diff --git a/test/pecoff/reloc64.test b/test/pecoff/reloc64.test
deleted file mode 100644
index fc38bff03275..000000000000
--- a/test/pecoff/reloc64.test
+++ /dev/null
@@ -1,20 +0,0 @@
-# REQUIRES: x86
-
-# RUN: yaml2obj %p/Inputs/reloc64.obj.yaml > %t.obj
-
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /machine:x64 \
-# RUN: /entry:entry -- %t.obj
-# RUN: llvm-objdump -d %t.exe | FileCheck %s
-
-CHECK: Disassembly of section .text:
-CHECK-NEXT: .text:
-CHECK-NEXT: 1000: 48 b8 28 10 00 40 01 00 00 ff
-CHECK-NEXT: 100a: e8 19 00 00 ff
-CHECK-NEXT: 100f: e8 13 00 00 ff
-CHECK-NEXT: 1014: e8 0d 00 00 ff
-CHECK-NEXT: 1019: e8 07 00 00 ff
-CHECK-NEXT: 101e: e8 01 00 00 ff
-CHECK-NEXT: 1023: e8 fb ff ff fe
-CHECK-NEXT: 1028: e8 01 00 00 ff
-CHECK-NEXT: 102d: e8 28 00 00 ff
-CHECK-NEXT: 1032: c3
diff --git a/test/pecoff/resource.test b/test/pecoff/resource.test
deleted file mode 100644
index 8cdc9a5bf83f..000000000000
--- a/test/pecoff/resource.test
+++ /dev/null
@@ -1,16 +0,0 @@
-# REQUIRES: winres
-
-# RUN: yaml2obj %p/Inputs/nop.obj.yaml > %t.obj
-
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /entry:start /opt:noref \
-# RUN: -- %t.obj %p/Inputs/resource.res
-
-# Check if the binary contains UTF-16LE string "Hello" copied from resource.res.
-# RUN: cat %t.exe | grep 'H.e.l.l.o'
-
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /entry:start /opt:noref \
-# RUN: /manifest:embed -- %t.obj %p/Inputs/resource.res
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
-
-CHECK: ResourceTableRVA: 0x1000
-CHECK: ResourceTableSize: 0x208
diff --git a/test/pecoff/responsefile.test b/test/pecoff/responsefile.test
deleted file mode 100644
index 6a5da298e730..000000000000
--- a/test/pecoff/responsefile.test
+++ /dev/null
@@ -1,7 +0,0 @@
-# RUN: yaml2obj %p/Inputs/hello.obj.yaml > %t.obj
-# RUN: not lld -flavor link /verbose @%p/Inputs/responsefile.txt >& %t.log
-# RUN: FileCheck %s < %t.log
-
-CHECK: warning: ignoring unknown argument: -foo
-CHECK: warning: ignoring unknown argument: -bar\baz
-Command line: link /verbose -foo -bar\baz
diff --git a/test/pecoff/safeseh.test b/test/pecoff/safeseh.test
deleted file mode 100644
index 78b1b0b53ac1..000000000000
--- a/test/pecoff/safeseh.test
+++ /dev/null
@@ -1,9 +0,0 @@
-# "hello.obj" does not have the symbol "@feat.00", so it's not
-# compatible with SEH.
-
-# RUN: yaml2obj %p/Inputs/hello.obj.yaml > %t1.obj
-# RUN: not lld -flavor link /safeseh /out:%t1.exe /subsystem:console \
-# RUN: -- %t1.obj 2> %t1.err
-# RUN: FileCheck -check-prefix=INCOMPAT %s < %t1.err
-
-INCOMPAT: /SAFESEH is specified, but {{.*}} is not compatible with SEH.
diff --git a/test/pecoff/secrel.test b/test/pecoff/secrel.test
deleted file mode 100644
index 05014c47af48..000000000000
--- a/test/pecoff/secrel.test
+++ /dev/null
@@ -1,16 +0,0 @@
-# RUN: yaml2obj %p/Inputs/secrel1.obj.yaml > %t1.obj
-# RUN: yaml2obj %p/Inputs/secrel2.obj.yaml > %t2.obj
-# RUN: yaml2obj %p/Inputs/secrel2.obj.yaml > %t3.obj
-#
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /entry:main \
-# RUN: -- %t1.obj %t2.obj %t3.obj
-# RUN: llvm-objdump -s %t.exe | FileCheck %s
-
-CHECK: Contents of section .data:
-CHECK: 1000 00000000 00000000 00000000 00000000
-CHECK: 1010 10000000 00000000 00000000 00000000
-CHECK: 1020 20000000 00000000 00000000 00000000
-CHECK: Contents of section .data2:
-CHECK: 2000 00000000 00000000 00000000 00000000
-CHECK: 2010 10000000 00000000 00000000 00000000
-CHECK: 2020 20000000 00000000 00000000 00000000
diff --git a/test/pecoff/section-attribute.test b/test/pecoff/section-attribute.test
deleted file mode 100644
index a5e71625df99..000000000000
--- a/test/pecoff/section-attribute.test
+++ /dev/null
@@ -1,45 +0,0 @@
-# RUN: yaml2obj %p/Inputs/nonstandard-sections.obj.yaml > %t.obj
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /force \
-# RUN: /section:.foo,d /section:.bar,rw /section:.text,rwe -- %t.obj
-# RUN: llvm-readobj -sections %t.exe | FileCheck %s
-
-CHECK: Sections [
-CHECK: Section {
-CHECK: Number: 1
-CHECK: Name: .bar (2E 62 61 72 00 00 00 00)
-CHECK: Characteristics [ (0xC0000040)
-CHECK: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-CHECK: IMAGE_SCN_MEM_READ (0x40000000)
-CHECK: IMAGE_SCN_MEM_WRITE (0x80000000)
-CHECK: ]
-CHECK: }
-CHECK: Section {
-CHECK: Number: 2
-CHECK: Name: .data (2E 64 61 74 61 00 00 00)
-CHECK: Characteristics [ (0xC0000040)
-CHECK: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-CHECK: IMAGE_SCN_MEM_READ (0x40000000)
-CHECK: IMAGE_SCN_MEM_WRITE (0x80000000)
-CHECK: ]
-CHECK: }
-CHECK: Section {
-CHECK: Number: 3
-CHECK: Name: .foo (2E 66 6F 6F 00 00 00 00)
-CHECK: Characteristics [ (0xC2000040)
-CHECK: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-CHECK: IMAGE_SCN_MEM_DISCARDABLE (0x2000000)
-CHECK: IMAGE_SCN_MEM_READ (0x40000000)
-CHECK: IMAGE_SCN_MEM_WRITE (0x80000000)
-CHECK: ]
-CHECK: }
-CHECK: Section {
-CHECK: Number: 4
-CHECK: Name: .text (2E 74 65 78 74 00 00 00)
-CHECK: Characteristics [ (0xE0000020)
-CHECK: IMAGE_SCN_CNT_CODE (0x20)
-CHECK: IMAGE_SCN_MEM_EXECUTE (0x20000000)
-CHECK: IMAGE_SCN_MEM_READ (0x40000000)
-CHECK: IMAGE_SCN_MEM_WRITE (0x80000000)
-CHECK: ]
-CHECK: }
-CHECK: ]
diff --git a/test/pecoff/section-renaming.test b/test/pecoff/section-renaming.test
deleted file mode 100644
index d4fc154693af..000000000000
--- a/test/pecoff/section-renaming.test
+++ /dev/null
@@ -1,61 +0,0 @@
-# RUN: yaml2obj %p/Inputs/nonstandard-sections.obj.yaml > %t.obj
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /force \
-# RUN: /merge:.foo=.hoge /merge:.bar=.text -- %t.obj
-# RUN: llvm-readobj -sections %t.exe | FileCheck %s
-
-CHECK: Format: COFF-i386
-CHECK-NEXT: Arch: i386
-CHECK-NEXT: AddressSize: 32bit
-CHECK-NEXT: Sections [
-CHECK-NEXT: Section {
-CHECK-NEXT: Number: 1
-CHECK-NEXT: Name: .data (2E 64 61 74 61 00 00 00)
-CHECK-NEXT: VirtualSize: 0x4
-CHECK-NEXT: VirtualAddress: 0x1000
-CHECK-NEXT: RawDataSize: 512
-CHECK-NEXT: PointerToRawData: 0x200
-CHECK-NEXT: PointerToRelocations: 0x0
-CHECK-NEXT: PointerToLineNumbers: 0x0
-CHECK-NEXT: RelocationCount: 0
-CHECK-NEXT: LineNumberCount: 0
-CHECK-NEXT: Characteristics [ (0xC0000040)
-CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-CHECK-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-CHECK-NEXT: IMAGE_SCN_MEM_WRITE (0x80000000)
-CHECK-NEXT: ]
-CHECK-NEXT: }
-CHECK-NEXT: Section {
-CHECK-NEXT: Number: 2
-CHECK-NEXT: Name: .hoge (2E 68 6F 67 65 00 00 00)
-CHECK-NEXT: VirtualSize: 0x4
-CHECK-NEXT: VirtualAddress: 0x2000
-CHECK-NEXT: RawDataSize: 512
-CHECK-NEXT: PointerToRawData: 0x400
-CHECK-NEXT: PointerToRelocations: 0x0
-CHECK-NEXT: PointerToLineNumbers: 0x0
-CHECK-NEXT: RelocationCount: 0
-CHECK-NEXT: LineNumberCount: 0
-CHECK-NEXT: Characteristics [ (0xC0000040)
-CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA (0x40)
-CHECK-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-CHECK-NEXT: IMAGE_SCN_MEM_WRITE (0x80000000)
-CHECK-NEXT: ]
-CHECK-NEXT: }
-CHECK-NEXT: Section {
-CHECK-NEXT: Number: 3
-CHECK-NEXT: Name: .text (2E 74 65 78 74 00 00 00)
-CHECK-NEXT: VirtualSize: 0x8
-CHECK-NEXT: VirtualAddress: 0x3000
-CHECK-NEXT: RawDataSize: 512
-CHECK-NEXT: PointerToRawData: 0x600
-CHECK-NEXT: PointerToRelocations: 0x0
-CHECK-NEXT: PointerToLineNumbers: 0x0
-CHECK-NEXT: RelocationCount: 0
-CHECK-NEXT: LineNumberCount: 0
-CHECK-NEXT: Characteristics [ (0x60000020)
-CHECK-NEXT: IMAGE_SCN_CNT_CODE (0x20)
-CHECK-NEXT: IMAGE_SCN_MEM_EXECUTE (0x20000000)
-CHECK-NEXT: IMAGE_SCN_MEM_READ (0x40000000)
-CHECK-NEXT: ]
-CHECK-NEXT: }
-CHECK-NEXT: ]
diff --git a/test/pecoff/seh.test b/test/pecoff/seh.test
deleted file mode 100644
index c563dc3f31e0..000000000000
--- a/test/pecoff/seh.test
+++ /dev/null
@@ -1,31 +0,0 @@
-# RUN: yaml2obj %p/Inputs/seh.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /force /nodefaultlib \
-# RUN: -- %t.obj
-# RUN: llvm-objdump -private-headers %t.exe | FileCheck %s
-
-CHECK: Load configuration:
-CHECK: Timestamp: 0
-CHECK: Major Version: 0
-CHECK: Minor Version: 0
-CHECK: GlobalFlags Clear: 0
-CHECK: GlobalFlags Set: 0
-CHECK: Critical Section Default Timeout: 0
-CHECK: Decommit Free Block Threshold: 0
-CHECK: Decommit Total Free Threshold: 0
-CHECK: Lock Prefix Table: 0
-CHECK: Maximum Allocation Size: 0
-CHECK: Virtual Memory Threshold: 0
-CHECK: Process Affinity Mask: 0
-CHECK: Process Heap Flags: 0
-CHECK: CSD Version: 0
-CHECK: Security Cookie: 0
-CHECK: SEH Table: 4206592
-CHECK: SEH Count: 2
-CHECK: SEH Table: 0x{{[0-9a-f]+}} 0x{{[0-9a-f]+}}
-
-# RUN: lld -flavor link /out:%t.exe /subsystem:console /force /nodefaultlib \
-# RUN: /safeseh:no -- %t.obj
-# RUN: llvm-objdump -private-headers %t.exe | FileCheck -check-prefix=NOSEH %s
-
-NOSEH-NOT: SEH Table:
diff --git a/test/pecoff/seh64.test b/test/pecoff/seh64.test
deleted file mode 100644
index 664ec29e5258..000000000000
--- a/test/pecoff/seh64.test
+++ /dev/null
@@ -1,57 +0,0 @@
-# RUN: yaml2obj %p/Inputs/unwind.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /machine:x64 /out:%t.exe /subsystem:console /force \
-# RUN: /nodefaultlib -- %t.obj
-# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=HEADER %s
-# RUN: llvm-objdump -unwind-info %t.exe | FileCheck -check-prefix=UNWIND %s
-
-HEADER: ExceptionTableRVA: 0x1000
-
-UNWIND: Function Table:
-UNWIND: Start Address: 0x2000
-UNWIND: End Address: 0x201b
-UNWIND: Unwind Info Address: 0x3000
-UNWIND: Version: 1
-UNWIND: Flags: 1 UNW_ExceptionHandler
-UNWIND: Size of prolog: 18
-UNWIND: Number of Codes: 8
-UNWIND: Frame register: RBX
-UNWIND: Frame offset: 0
-UNWIND: Unwind Codes:
-UNWIND: 0x12: UOP_SetFPReg
-UNWIND: 0x0f: UOP_PushNonVol RBX
-UNWIND: 0x0e: UOP_SaveXMM128 XMM8 [0x0000]
-UNWIND: 0x09: UOP_SaveNonVol RSI [0x0010]
-UNWIND: 0x04: UOP_AllocSmall 24
-UNWIND: 0x00: UOP_PushMachFrame w/o error code
-UNWIND: Function Table:
-UNWIND: Start Address: 0x2012
-UNWIND: End Address: 0x2012
-UNWIND: Unwind Info Address: 0x301c
-UNWIND: Version: 1
-UNWIND: Flags: 4 UNW_ChainInfo
-UNWIND: Size of prolog: 0
-UNWIND: Number of Codes: 0
-UNWIND: No frame pointer used
-UNWIND: Function Table:
-UNWIND: Start Address: 0x201b
-UNWIND: End Address: 0x201c
-UNWIND: Unwind Info Address: 0x302c
-UNWIND: Version: 1
-UNWIND: Flags: 0
-UNWIND: Size of prolog: 0
-UNWIND: Number of Codes: 0
-UNWIND: No frame pointer used
-UNWIND: Function Table:
-UNWIND: Start Address: 0x201c
-UNWIND: End Address: 0x2039
-UNWIND: Unwind Info Address: 0x3034
-UNWIND: Version: 1
-UNWIND: Flags: 0
-UNWIND: Size of prolog: 14
-UNWIND: Number of Codes: 6
-UNWIND: No frame pointer used
-UNWIND: Unwind Codes:
-UNWIND: 0x0e: UOP_AllocLarge 8454128
-UNWIND: 0x07: UOP_AllocLarge 8190
-UNWIND: 0x00: UOP_PushMachFrame w/o error code
diff --git a/test/pecoff/subsystem.test b/test/pecoff/subsystem.test
deleted file mode 100644
index 3ed3572bf231..000000000000
--- a/test/pecoff/subsystem.test
+++ /dev/null
@@ -1,12 +0,0 @@
-# RUN: yaml2obj %p/Inputs/subsystem.main.yaml > %t.main.obj
-# RUN: yaml2obj %p/Inputs/subsystem.winmain.yaml > %t.winmain.obj
-#
-# RUN: lld -flavor link /out:%t.main.exe -- %t.main.obj
-# RUN: llvm-readobj -file-headers %t.main.exe | FileCheck -check-prefix=MAIN %s
-#
-# RUN: lld -flavor link /out:%t.winmain.exe -- %t.winmain.obj
-# RUN: llvm-readobj -file-headers %t.winmain.exe | \
-# RUN: FileCheck -check-prefix=WINMAIN %s
-
-MAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
-WINMAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI
diff --git a/test/pecoff/tls.test b/test/pecoff/tls.test
deleted file mode 100644
index 7e400ff60a0b..000000000000
--- a/test/pecoff/tls.test
+++ /dev/null
@@ -1,14 +0,0 @@
-# RUN: yaml2obj %p/Inputs/hello.obj.yaml > %t1.obj
-# RUN: yaml2obj %p/Inputs/tlsused.obj.yaml > %t2.obj
-
-# RUN: lld -flavor link /out:%t1.exe /subsystem:console /force -- %t1.obj
-# RUN: llvm-readobj -file-headers %t1.exe | FileCheck -check-prefix=NOTLS %s
-
-# RUN: lld -flavor link /out:%t2.exe /subsystem:console /force -- %t1.obj %t2.obj
-# RUN: llvm-readobj -file-headers %t2.exe | FileCheck -check-prefix=TLS %s
-
-NOTLS: TLSTableRVA: 0x0
-NOTLS: TLSTableSize: 0x0
-
-TLS: TLSTableRVA: 0x1014
-TLS: TLSTableSize: 0x18
diff --git a/test/pecoff/trivial.test b/test/pecoff/trivial.test
deleted file mode 100644
index b1960f632813..000000000000
--- a/test/pecoff/trivial.test
+++ /dev/null
@@ -1,103 +0,0 @@
-# Checks functionality of PECOFF writer. "nop.obj" is an object that has only
-# text section. Other data, including data sections, relocations, symbol
-# tables are not present in nop.obj.
-#
-# RUN: yaml2obj %p/Inputs/nop.obj.yaml > %t.obj
-#
-# RUN: lld -flavor link /out:%t1.exe /subsystem:console,3.11 /version:1.25 \
-# RUN: /entry:start /opt:noref -- %t.obj
-# RUN: llvm-readobj -file-headers %t1.exe | FileCheck -check-prefix=FILE %s
-#
-# RUN: lld -flavor link /out:%t2.exe /subsystem:console /entry:start \
-# RUN: /opt:noref -- %t.obj
-# RUN: llvm-readobj -sections %t2.exe | FileCheck -check-prefix=SECTIONS %s
-
-FILE: Format: COFF-i386
-FILE-NEXT: Arch: i386
-FILE-NEXT: AddressSize: 32bit
-FILE-NEXT: ImageFileHeader {
-FILE-NEXT: Machine: IMAGE_FILE_MACHINE_I386 (0x14C)
-FILE-NEXT: SectionCount: 1
-FILE-NEXT: TimeDateStamp:
-FILE-NEXT: PointerToSymbolTable: 0x0
-FILE-NEXT: SymbolCount: 0
-FILE-NEXT: OptionalHeaderSize: 224
-FILE-NEXT: Characteristics [ (0x102)
-FILE-NEXT: IMAGE_FILE_32BIT_MACHINE (0x100)
-FILE-NEXT: IMAGE_FILE_EXECUTABLE_IMAGE (0x2)
-FILE-NEXT: ]
-FILE-NEXT: }
-FILE-NEXT: ImageOptionalHeader {
-FILE-NEXT: MajorLinkerVersion: 0
-FILE-NEXT: MinorLinkerVersion: 0
-FILE-NEXT: SizeOfCode: 512
-FILE-NEXT: SizeOfInitializedData: 0
-FILE-NEXT: SizeOfUninitializedData: 0
-FILE-NEXT: AddressOfEntryPoint: 0x1000
-FILE-NEXT: BaseOfCode: 0x1000
-FILE-NEXT: BaseOfData: 0
-FILE-NEXT: ImageBase: 0x400000
-FILE-NEXT: SectionAlignment: 4096
-FILE-NEXT: FileAlignment: 512
-FILE-NEXT: MajorOperatingSystemVersion: 3
-FILE-NEXT: MinorOperatingSystemVersion: 11
-FILE-NEXT: MajorImageVersion: 1
-FILE-NEXT: MinorImageVersion: 25
-FILE-NEXT: MajorSubsystemVersion: 3
-FILE-NEXT: MinorSubsystemVersion: 11
-FILE-NEXT: SizeOfImage: 8192
-FILE-NEXT: SizeOfHeaders: 512
-FILE-NEXT: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3)
-FILE-NEXT: Characteristics [ (0x8540)
-FILE-NEXT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE (0x40)
-FILE-NEXT: IMAGE_DLL_CHARACTERISTICS_NO_SEH (0x400)
-FILE-NEXT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT (0x100)
-FILE-NEXT: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE (0x8000)
-FILE-NEXT: ]
-FILE-NEXT: SizeOfStackReserve: 1048576
-FILE-NEXT: SizeOfStackCommit: 4096
-FILE-NEXT: SizeOfHeapReserve: 1048576
-FILE-NEXT: SizeOfHeapCommit: 4096
-FILE-NEXT: NumberOfRvaAndSize: 16
-FILE: DOSHeader {
-FILE-NEXT: Magic: MZ
-FILE-NEXT: UsedBytesInTheLastPage: 0
-FILE-NEXT: FileSizeInPages: 0
-FILE-NEXT: NumberOfRelocationItems: 0
-FILE-NEXT: HeaderSizeInParagraphs: 0
-FILE-NEXT: MinimumExtraParagraphs: 0
-FILE-NEXT: MaximumExtraParagraphs: 0
-FILE-NEXT: InitialRelativeSS: 0
-FILE-NEXT: InitialSP: 0
-FILE-NEXT: Checksum: 0
-FILE-NEXT: InitialIP: 0
-FILE-NEXT: InitialRelativeCS: 0
-FILE-NEXT: AddressOfRelocationTable: 64
-FILE-NEXT: OverlayNumber: 0
-FILE-NEXT: OEMid: 0
-FILE-NEXT: OEMinfo: 0
-FILE-NEXT: AddressOfNewExeHeader: 128
-FILE-NEXT: }
-
-SECTIONS: Format: COFF-i386
-SECTIONS-NEXT: Arch: i386
-SECTIONS-NEXT: AddressSize: 32bit
-SECTIONS-NEXT: Sections [
-SECTIONS-NEXT: Section {
-SECTIONS-NEXT: Number: 1
-SECTIONS-NEXT: Name: .text (2E 74 65 78 74 00 00 00)
-SECTIONS-NEXT: VirtualSize: 0x6
-SECTIONS-NEXT: VirtualAddress: 0x1000
-SECTIONS-NEXT: RawDataSize: 512
-SECTIONS-NEXT: PointerToRawData: 0x200
-SECTIONS-NEXT: PointerToRelocations: 0x0
-SECTIONS-NEXT: PointerToLineNumbers: 0x0
-SECTIONS-NEXT: RelocationCount: 0
-SECTIONS-NEXT: LineNumberCount: 0
-SECTIONS-NEXT: Characteristics [
-SECTIONS-NEXT: IMAGE_SCN_CNT_CODE
-SECTIONS-NEXT: IMAGE_SCN_MEM_EXECUTE
-SECTIONS-NEXT: IMAGE_SCN_MEM_READ
-SECTIONS-NEXT: ]
-SECTIONS-NEXT: }
-SECTIONS-NEXT: ]
diff --git a/test/pecoff/unknown-drectve.test b/test/pecoff/unknown-drectve.test
deleted file mode 100644
index 2c687c5d9163..000000000000
--- a/test/pecoff/unknown-drectve.test
+++ /dev/null
@@ -1,6 +0,0 @@
-# RUN: yaml2obj %p/Inputs/unknown-drectve.obj.yaml > %t.obj
-#
-# RUN: not lld -flavor link /out:%t.exe -- %t.obj >& %t.log
-# RUN: FileCheck -check-prefix=ERROR %s < %t.log
-
-ERROR: Cannot open /nosuchoption:foobar
diff --git a/test/pecoff/weak-external.test b/test/pecoff/weak-external.test
deleted file mode 100644
index ff7492dcfd5e..000000000000
--- a/test/pecoff/weak-external.test
+++ /dev/null
@@ -1,9 +0,0 @@
-# RUN: yaml2obj %p/Inputs/weak-externals.obj.yaml > %t.obj
-
-# RUN: lld -flavor link /force /out:%t.exe /subsystem:console \
-# RUN: /entry:fn -- %t.obj %p/Inputs/static.lib 2> %t2.log
-# RUN: FileCheck %s < %t2.log
-
-CHECK: _no_such_symbol1
-CHECK-NOT: _no_such_symbol2
-CHECK: _no_such_symbol3
diff --git a/tools/Makefile b/tools/Makefile
deleted file mode 100644
index 93d2a58c3068..000000000000
--- a/tools/Makefile
+++ /dev/null
@@ -1,17 +0,0 @@
-##===- tools/Makefile --------------------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL := ..
-LEVEL := $(LLD_LEVEL)/../..
-
-include $(LLD_LEVEL)/../../Makefile.config
-
-PARALLEL_DIRS := linker-script-test lld
-
-include $(LLD_LEVEL)/Makefile
diff --git a/tools/linker-script-test/Makefile b/tools/linker-script-test/Makefile
deleted file mode 100644
index fd1b61accc07..000000000000
--- a/tools/linker-script-test/Makefile
+++ /dev/null
@@ -1,24 +0,0 @@
-##===-------------- linker-script-test/Makefile ----------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===--------------------------------------------------------------------===##
-
-LLD_LEVEL := ../..
-
-TOOLNAME = linker-script-test
-
-# No plugins, optimize startup time.
-TOOL_NO_EXPORTS = 1
-
-#include /Makefile.config
-LEVEL := $(LLD_LEVEL)/../..
-include $(LEVEL)/Makefile.config
-
-LINK_COMPONENTS := $(TARGETS_TO_BUILD)
-USEDLIBS = lldReaderWriter.a lldCore.a LLVMSupport.a
-
-include $(LLD_LEVEL)/Makefile
diff --git a/tools/lld/CMakeLists.txt b/tools/lld/CMakeLists.txt
index 47f26b5300c2..5a0736e4c1e9 100644
--- a/tools/lld/CMakeLists.txt
+++ b/tools/lld/CMakeLists.txt
@@ -4,22 +4,20 @@ add_llvm_executable(lld
target_link_libraries(lld
lldDriver
+ lldCOFF
LLVMSupport
)
install(TARGETS lld
RUNTIME DESTINATION bin)
-# Create the lld-link[.exe] symlink in the build directory. If symlink is not
-# supported by the operating system, create a copy instead.
-if(UNIX)
- set(command create_symlink)
- # Make relative symlink
- set(src "lld${CMAKE_EXECUTABLE_SUFFIX}")
-else()
- set(command copy)
- set(src "${LLVM_RUNTIME_OUTPUT_INTDIR}/lld${CMAKE_EXECUTABLE_SUFFIX}")
+if(NOT LLD_SYMLINKS_TO_CREATE)
+ set(LLD_SYMLINKS_TO_CREATE lld-link ld.lld)
endif()
-set(dst "${LLVM_RUNTIME_OUTPUT_INTDIR}/lld-link${CMAKE_EXECUTABLE_SUFFIX}")
-add_custom_command(TARGET lld POST_BUILD
- COMMAND ${CMAKE_COMMAND} -E ${command} ${src} ${dst})
+
+foreach(link ${LLD_SYMLINKS_TO_CREATE})
+ add_llvm_tool_symlink(${link} lld ALWAYS_GENERATE)
+ # Always generate install targets
+ llvm_install_symlink(${link} lld ALWAYS_GENERATE)
+endforeach()
+
diff --git a/tools/lld/Makefile b/tools/lld/Makefile
deleted file mode 100644
index 77b0abbef9d0..000000000000
--- a/tools/lld/Makefile
+++ /dev/null
@@ -1,30 +0,0 @@
-##===------- lld/Makefile --------------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===--------------------------------------------------------------------===##
-
-LLD_LEVEL := ../..
-
-TOOLNAME = lld
-
-# No plugins, optimize startup time.
-TOOL_NO_EXPORTS = 1
-
-#include /Makefile.config
-LEVEL := $(LLD_LEVEL)/../..
-include $(LEVEL)/Makefile.config
-
-LINK_COMPONENTS := $(TARGETS_TO_BUILD)
-USEDLIBS = lldDriver.a lldConfig.a \
- lldELF.a lldMachO.a lldPECOFF.a lldYAML.a \
- lldReaderWriter.a lldCore.a lldNative.a \
- lldHexagonELFTarget.a lldMipsELFTarget.a \
- lldX86ELFTarget.a lldExampleSubTarget.a lldX86_64ELFTarget.a \
- lldAArch64ELFTarget.a lldARMELFTarget.a \
- LLVMOption.a
-
-include $(LLD_LEVEL)/Makefile
diff --git a/tools/lld/lld.cpp b/tools/lld/lld.cpp
index 24c3a66a3ac3..eb0903660dbd 100644
--- a/tools/lld/lld.cpp
+++ b/tools/lld/lld.cpp
@@ -23,7 +23,7 @@
using namespace lld;
-/// Universal linker main(). This linker eumulates the gnu, darwin, or
+/// 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[]) {
@@ -32,5 +32,6 @@ int main(int argc, const char *argv[]) {
llvm::PrettyStackTraceProgram stackPrinter(argc, argv);
llvm::llvm_shutdown_obj shutdown;
- return UniversalDriver::link(argc, argv) ? 0 : 1;
+ return !UniversalDriver::link(
+ llvm::MutableArrayRef<const char *>(argv, argc));
}
diff --git a/unittests/CoreTests/Makefile b/unittests/CoreTests/Makefile
deleted file mode 100644
index 366df01a08cc..000000000000
--- a/unittests/CoreTests/Makefile
+++ /dev/null
@@ -1,14 +0,0 @@
-##===- unittests/CoreTests/Makefile ----------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-LLD_LEVEL = ../..
-TESTNAME = CoreTest
-LLVMLIBS = gtest.a LLVMOption.a LLVMSupport.a
-
-include $(LLD_LEVEL)/unittests/Makefile
diff --git a/unittests/DriverTests/CMakeLists.txt b/unittests/DriverTests/CMakeLists.txt
index 59d56d459582..0378e6164429 100644
--- a/unittests/DriverTests/CMakeLists.txt
+++ b/unittests/DriverTests/CMakeLists.txt
@@ -2,13 +2,11 @@ add_lld_unittest(DriverTests
UniversalDriverTest.cpp
GnuLdDriverTest.cpp
DarwinLdDriverTest.cpp
- WinLinkDriverTest.cpp
- WinLinkModuleDefTest.cpp
)
target_link_libraries(DriverTests
lldDriver
+ lldCOFF
lldCore
- lldPECOFF
lldMachO
)
diff --git a/unittests/DriverTests/DarwinLdDriverTest.cpp b/unittests/DriverTests/DarwinLdDriverTest.cpp
index 1c77a05f5856..e2809c44984d 100644
--- a/unittests/DriverTests/DarwinLdDriverTest.cpp
+++ b/unittests/DriverTests/DarwinLdDriverTest.cpp
@@ -231,10 +231,10 @@ TEST_F(DarwinLdParserTest, deadStrippableDylibInvalidType) {
}
TEST_F(DarwinLdParserTest, llvmOptions) {
- EXPECT_TRUE(parse("ld", "-mllvm", "-debug-only", "-mllvm", "foo", "a.o",
+ 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],"-debug-only"), 0);
- EXPECT_EQ(strcmp(options[1],"foo"), 0);
+ EXPECT_EQ(strcmp(options[0],"-enable-tbaa"), 0);
+ EXPECT_EQ(strcmp(options[1],"-enable-misched"), 0);
}
diff --git a/unittests/DriverTests/DriverTest.h b/unittests/DriverTests/DriverTest.h
index 2349132ee2ce..65af7cac3139 100644
--- a/unittests/DriverTests/DriverTest.h
+++ b/unittests/DriverTests/DriverTest.h
@@ -51,7 +51,7 @@ protected:
// Call the parser.
raw_string_ostream os(_errorMessage);
- return D::parse(vec.size(), &vec[0], _ctx, os);
+ return D::parse(vec, _ctx, os);
}
T _ctx;
diff --git a/unittests/DriverTests/GnuLdDriverTest.cpp b/unittests/DriverTests/GnuLdDriverTest.cpp
index 92eb920f0180..13d20a4411a1 100644
--- a/unittests/DriverTests/GnuLdDriverTest.cpp
+++ b/unittests/DriverTests/GnuLdDriverTest.cpp
@@ -31,7 +31,7 @@ class LinkerScriptTest : public testing::Test {
protected:
void SetUp() override {
llvm::Triple triple(llvm::sys::getDefaultTargetTriple());
- _ctx = std::move(GnuLdDriver::createELFLinkingContext(triple));
+ _ctx = GnuLdDriver::createELFLinkingContext(triple);
}
void parse(StringRef script, bool nostdlib = false) {
@@ -42,7 +42,7 @@ protected:
std::error_code ec =
GnuLdDriver::evalLinkerScript(*_ctx, std::move(mb), out, nostdlib);
EXPECT_FALSE(ec);
- };
+ }
std::unique_ptr<ELFLinkingContext> _ctx;
};
@@ -199,6 +199,22 @@ TEST_F(GnuLdParserTest, 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) {
@@ -281,4 +297,3 @@ TEST_F(LinkerScriptTest, ExprEval) {
EXPECT_EQ(0x14000, result);
EXPECT_EQ(0, sa2->symbol().compare(StringRef(".")));
}
-
diff --git a/unittests/DriverTests/Makefile b/unittests/DriverTests/Makefile
deleted file mode 100644
index ae97fb01adbf..000000000000
--- a/unittests/DriverTests/Makefile
+++ /dev/null
@@ -1,20 +0,0 @@
-##===---- unittests/DriverTests/Makefile ----------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===-------------------------------------------------------------------===##
-
-LLD_LEVEL = ../..
-TESTNAME = DriverTests
-USEDLIBS = lldDriver.a lldConfig.a \
- lldELF.a lldMachO.a lldPECOFF.a \
- lldCore.a lldNative.a lldReaderWriter.a \
- lldHexagonELFTarget.a lldMipsELFTarget.a \
- lldX86ELFTarget.a lldExampleSubTarget.a lldX86_64ELFTarget.a \
- lldYAML.a lldAArch64ELFTarget.a lldARMELFTarget.a \
- LLVMObject.a LLVMMCParser.a LLVMMC.a LLVMBitReader.a \
- LLVMCore.a LLVMOption.a LLVMSupport.a
-include $(LLD_LEVEL)/unittests/Makefile
diff --git a/unittests/DriverTests/UniversalDriverTest.cpp b/unittests/DriverTests/UniversalDriverTest.cpp
index 8e90ca4d5867..0a464d3038c6 100644
--- a/unittests/DriverTests/UniversalDriverTest.cpp
+++ b/unittests/DriverTests/UniversalDriverTest.cpp
@@ -21,11 +21,11 @@ using namespace llvm;
using namespace lld;
TEST(UniversalDriver, flavor) {
- const char *args[] = { "gnu-ld" };
+ const char *args[] = {"ld", "-flavor", "old-gnu"};
std::string diags;
raw_string_ostream os(diags);
- UniversalDriver::link(array_lengthof(args), args, os);
+ 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"),
diff --git a/unittests/DriverTests/WinLinkDriverTest.cpp b/unittests/DriverTests/WinLinkDriverTest.cpp
deleted file mode 100644
index c2bc455aa81f..000000000000
--- a/unittests/DriverTests/WinLinkDriverTest.cpp
+++ /dev/null
@@ -1,728 +0,0 @@
-//===- lld/unittest/WinLinkDriverTest.cpp ---------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-///
-/// \file
-/// \brief Windows link.exe driver tests.
-///
-//===----------------------------------------------------------------------===//
-
-#include "DriverTest.h"
-#include "lld/ReaderWriter/PECOFFLinkingContext.h"
-#include "llvm/ADT/Optional.h"
-#include "llvm/Support/COFF.h"
-#include <set>
-#include <vector>
-
-using namespace llvm;
-using namespace lld;
-
-namespace {
-class WinLinkParserTest
- : public ParserTest<WinLinkDriver, PECOFFLinkingContext> {
-protected:
- const LinkingContext *linkingContext() override { return &_ctx; }
-};
-}
-
-TEST_F(WinLinkParserTest, Basic) {
- EXPECT_TRUE(parse("link.exe", "/subsystem:console", "/out:a.exe",
- "-entry:start", "a.obj", "b.obj", "c.obj", nullptr));
- EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI, _ctx.getSubsystem());
- EXPECT_EQ(llvm::COFF::IMAGE_FILE_MACHINE_I386, _ctx.getMachineType());
- EXPECT_EQ("a.exe", _ctx.outputPath());
- EXPECT_EQ("start", _ctx.getEntrySymbolName());
- EXPECT_EQ(4, inputFileCount());
- EXPECT_EQ("a.obj", inputFile(0));
- EXPECT_EQ("b.obj", inputFile(1));
- EXPECT_EQ("c.obj", inputFile(2));
- EXPECT_TRUE(_ctx.getInputSearchPaths().empty());
-
- // Unspecified flags will have default values.
- EXPECT_FALSE(_ctx.isDll());
- EXPECT_EQ(6, _ctx.getMinOSVersion().majorVersion);
- EXPECT_EQ(0, _ctx.getMinOSVersion().minorVersion);
- EXPECT_EQ(0x400000U, _ctx.getBaseAddress());
- EXPECT_EQ(1024 * 1024U, _ctx.getStackReserve());
- EXPECT_EQ(4096U, _ctx.getStackCommit());
- EXPECT_EQ(4096U, _ctx.getSectionDefaultAlignment());
- EXPECT_FALSE(_ctx.allowRemainingUndefines());
- EXPECT_TRUE(_ctx.isNxCompat());
- EXPECT_FALSE(_ctx.getLargeAddressAware());
- EXPECT_TRUE(_ctx.getAllowBind());
- EXPECT_TRUE(_ctx.getAllowIsolation());
- EXPECT_FALSE(_ctx.getSwapRunFromCD());
- EXPECT_FALSE(_ctx.getSwapRunFromNet());
- EXPECT_TRUE(_ctx.getBaseRelocationEnabled());
- EXPECT_TRUE(_ctx.isTerminalServerAware());
- EXPECT_TRUE(_ctx.getDynamicBaseEnabled());
- EXPECT_TRUE(_ctx.getCreateManifest());
- EXPECT_EQ("", _ctx.getManifestDependency());
- EXPECT_FALSE(_ctx.getEmbedManifest());
- EXPECT_EQ(1, _ctx.getManifestId());
- EXPECT_TRUE(_ctx.getManifestUAC());
- EXPECT_EQ("'asInvoker'", _ctx.getManifestLevel());
- EXPECT_EQ("'false'", _ctx.getManifestUiAccess());
- EXPECT_TRUE(_ctx.deadStrip());
- EXPECT_FALSE(_ctx.logInputFiles());
-}
-
-TEST_F(WinLinkParserTest, StartsWithHyphen) {
- EXPECT_TRUE(
- parse("link.exe", "-subsystem:console", "-out:a.exe", "a.obj", nullptr));
- EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI, _ctx.getSubsystem());
- EXPECT_EQ("a.exe", _ctx.outputPath());
- EXPECT_EQ(2, inputFileCount());
- EXPECT_EQ("a.obj", inputFile(0));
-}
-
-TEST_F(WinLinkParserTest, UppercaseOption) {
- EXPECT_TRUE(
- parse("link.exe", "/SUBSYSTEM:CONSOLE", "/OUT:a.exe", "a.obj", nullptr));
- EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI, _ctx.getSubsystem());
- EXPECT_EQ("a.exe", _ctx.outputPath());
- EXPECT_EQ(2, inputFileCount());
- EXPECT_EQ("a.obj", inputFile(0));
-}
-
-TEST_F(WinLinkParserTest, Mllvm) {
- EXPECT_TRUE(parse("link.exe", "/mllvm:-debug", "a.obj", nullptr));
- const std::vector<const char *> &options = _ctx.llvmOptions();
- EXPECT_EQ(1U, options.size());
- EXPECT_STREQ("-debug", options[0]);
-}
-
-TEST_F(WinLinkParserTest, NoInputFiles) {
- EXPECT_FALSE(parse("link.exe", nullptr));
- EXPECT_EQ("No input files\n", errorMessage());
-}
-
-//
-// Tests for implicit file extension interpolation.
-//
-
-TEST_F(WinLinkParserTest, NoFileExtension) {
- EXPECT_TRUE(parse("link.exe", "foo", "bar", nullptr));
- EXPECT_EQ("foo.exe", _ctx.outputPath());
- EXPECT_EQ(3, inputFileCount());
- EXPECT_EQ("foo.obj", inputFile(0));
- EXPECT_EQ("bar.obj", inputFile(1));
-}
-
-TEST_F(WinLinkParserTest, NonStandardFileExtension) {
- EXPECT_TRUE(parse("link.exe", "foo.o", nullptr));
- EXPECT_EQ("foo.exe", _ctx.outputPath());
- EXPECT_EQ(2, inputFileCount());
- EXPECT_EQ("foo.o", inputFile(0));
-}
-
-TEST_F(WinLinkParserTest, Libpath) {
- EXPECT_TRUE(
- parse("link.exe", "/libpath:dir1", "/libpath:dir2", "a.obj", nullptr));
- const std::vector<StringRef> &paths = _ctx.getInputSearchPaths();
- EXPECT_EQ(2U, paths.size());
- EXPECT_EQ("dir1", paths[0]);
- EXPECT_EQ("dir2", paths[1]);
-}
-
-//
-// Tests for input file order
-//
-
-TEST_F(WinLinkParserTest, InputOrder) {
- EXPECT_TRUE(parse("link.exe", "a.lib", "b.obj", "c.obj", "a.lib", "d.obj",
- nullptr));
- EXPECT_EQ(5, inputFileCount());
- EXPECT_EQ("b.obj", inputFile(0));
- EXPECT_EQ("c.obj", inputFile(1));
- EXPECT_EQ("d.obj", inputFile(2));
- EXPECT_EQ("a.lib", inputFile(3));
-}
-
-//
-// Tests for command line options that take values.
-//
-
-TEST_F(WinLinkParserTest, AlternateName) {
- EXPECT_TRUE(parse("link.exe", "/alternatename:sym1=sym",
- "/alternatename:sym2=sym", "a.out", nullptr));
- const std::set<std::string> &aliases = _ctx.getAlternateNames("sym");
- EXPECT_EQ(2U, aliases.size());
- auto it = aliases.begin();
- EXPECT_EQ("sym1", *it++);
- EXPECT_EQ("sym2", *it++);
-}
-
-TEST_F(WinLinkParserTest, Export) {
- EXPECT_TRUE(parse("link.exe", "/export:foo", "a.out", nullptr));
- const std::vector<PECOFFLinkingContext::ExportDesc> &exports =
- _ctx.getDllExports();
- EXPECT_EQ(1U, exports.size());
- EXPECT_EQ("_foo", exports[0].name);
- EXPECT_EQ(-1, exports[0].ordinal);
- EXPECT_FALSE(exports[0].noname);
- EXPECT_FALSE(exports[0].isData);
-}
-
-TEST_F(WinLinkParserTest, ExportWithOptions) {
- EXPECT_TRUE(parse("link.exe", "/export:foo,@8,noname,data",
- "/export:bar,@10,data", "a.out", nullptr));
- const std::vector<PECOFFLinkingContext::ExportDesc> &exports =
- _ctx.getDllExports();
- EXPECT_EQ(2U, exports.size());
- EXPECT_EQ("_foo", exports[0].name);
- EXPECT_EQ(8, exports[0].ordinal);
- EXPECT_TRUE(exports[0].noname);
- EXPECT_TRUE(exports[0].isData);
- EXPECT_EQ("_bar", exports[1].name);
- EXPECT_EQ(10, exports[1].ordinal);
- EXPECT_FALSE(exports[1].noname);
- EXPECT_TRUE(exports[1].isData);
-}
-
-TEST_F(WinLinkParserTest, ExportDuplicateExports) {
- EXPECT_TRUE(
- parse("link.exe", "/export:foo", "/export:foo,@2", "a.out", nullptr));
- const std::vector<PECOFFLinkingContext::ExportDesc> &exports =
- _ctx.getDllExports();
- EXPECT_EQ(1U, exports.size());
- EXPECT_EQ("_foo", exports[0].name);
- EXPECT_EQ(-1, exports[0].ordinal);
-}
-
-TEST_F(WinLinkParserTest, ExportDuplicateOrdinals) {
- EXPECT_FALSE(
- parse("link.exe", "/export:foo,@1", "/export:bar,@1", "a.out", nullptr));
-}
-
-TEST_F(WinLinkParserTest, ExportInvalid1) {
- EXPECT_FALSE(parse("link.exe", "/export:foo,@0", "a.out", nullptr));
-}
-
-TEST_F(WinLinkParserTest, ExportInvalid2) {
- EXPECT_FALSE(parse("link.exe", "/export:foo,@65536", "a.out", nullptr));
-}
-
-TEST_F(WinLinkParserTest, MachineX86) {
- EXPECT_TRUE(parse("link.exe", "/machine:x86", "a.obj", nullptr));
- EXPECT_EQ(llvm::COFF::IMAGE_FILE_MACHINE_I386, _ctx.getMachineType());
-}
-
-TEST_F(WinLinkParserTest, MachineX64) {
- EXPECT_TRUE(parse("link.exe", "/machine:x64", "a.obj", nullptr));
- EXPECT_EQ(llvm::COFF::IMAGE_FILE_MACHINE_AMD64, _ctx.getMachineType());
-}
-
-TEST_F(WinLinkParserTest, MachineArm) {
- EXPECT_TRUE(parse("link.exe", "/machine:arm", "a.obj", nullptr));
- EXPECT_EQ(llvm::COFF::IMAGE_FILE_MACHINE_ARMNT, _ctx.getMachineType());
-}
-
-TEST_F(WinLinkParserTest, MachineUnknown) {
- EXPECT_FALSE(parse("link.exe", "/machine:nosucharch", "a.obj", nullptr));
- EXPECT_EQ("error: unknown machine type: nosucharch\n", errorMessage());
-}
-
-TEST_F(WinLinkParserTest, MajorImageVersion) {
- EXPECT_TRUE(parse("link.exe", "/version:7", "foo.o", nullptr));
- EXPECT_EQ(7, _ctx.getImageVersion().majorVersion);
- EXPECT_EQ(0, _ctx.getImageVersion().minorVersion);
-}
-
-TEST_F(WinLinkParserTest, MajorMinorImageVersion) {
- EXPECT_TRUE(parse("link.exe", "/version:72.35", "foo.o", nullptr));
- EXPECT_EQ(72, _ctx.getImageVersion().majorVersion);
- EXPECT_EQ(35, _ctx.getImageVersion().minorVersion);
-}
-
-TEST_F(WinLinkParserTest, MinMajorOSVersion) {
- EXPECT_TRUE(parse("link.exe", "/subsystem:windows,3", "foo.o", nullptr));
- EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI, _ctx.getSubsystem());
- EXPECT_EQ(3, _ctx.getMinOSVersion().majorVersion);
- EXPECT_EQ(0, _ctx.getMinOSVersion().minorVersion);
-}
-
-TEST_F(WinLinkParserTest, MinMajorMinorOSVersion) {
- EXPECT_TRUE(parse("link.exe", "/subsystem:windows,3.1", "foo.o", nullptr));
- EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_GUI, _ctx.getSubsystem());
- EXPECT_EQ(3, _ctx.getMinOSVersion().majorVersion);
- EXPECT_EQ(1, _ctx.getMinOSVersion().minorVersion);
-}
-
-TEST_F(WinLinkParserTest, Base) {
- EXPECT_TRUE(parse("link.exe", "/base:8388608", "a.obj", nullptr));
- EXPECT_EQ(0x800000U, _ctx.getBaseAddress());
-}
-
-TEST_F(WinLinkParserTest, InvalidBase) {
- EXPECT_FALSE(parse("link.exe", "/base:1234", "a.obj", nullptr));
- EXPECT_TRUE(StringRef(errorMessage())
- .startswith("Base address have to be multiple of 64K"));
-}
-
-TEST_F(WinLinkParserTest, StackReserve) {
- EXPECT_TRUE(parse("link.exe", "/stack:8192", "a.obj", nullptr));
- EXPECT_EQ(8192U, _ctx.getStackReserve());
- EXPECT_EQ(4096U, _ctx.getStackCommit());
-}
-
-TEST_F(WinLinkParserTest, StackReserveAndCommit) {
- EXPECT_TRUE(parse("link.exe", "/stack:16384,8192", "a.obj", nullptr));
- EXPECT_EQ(16384U, _ctx.getStackReserve());
- EXPECT_EQ(8192U, _ctx.getStackCommit());
-}
-
-TEST_F(WinLinkParserTest, InvalidStackSize) {
- EXPECT_FALSE(parse("link.exe", "/stack:8192,16384", "a.obj", nullptr));
- EXPECT_TRUE(StringRef(errorMessage()).startswith("Invalid stack size"));
-}
-
-TEST_F(WinLinkParserTest, HeapReserve) {
- EXPECT_TRUE(parse("link.exe", "/heap:8192", "a.obj", nullptr));
- EXPECT_EQ(8192U, _ctx.getHeapReserve());
- EXPECT_EQ(4096U, _ctx.getHeapCommit());
-}
-
-TEST_F(WinLinkParserTest, HeapReserveAndCommit) {
- EXPECT_TRUE(parse("link.exe", "/heap:16384,8192", "a.obj", nullptr));
- EXPECT_EQ(16384U, _ctx.getHeapReserve());
- EXPECT_EQ(8192U, _ctx.getHeapCommit());
-}
-
-TEST_F(WinLinkParserTest, InvalidHeapSize) {
- EXPECT_FALSE(parse("link.exe", "/heap:8192,16384", "a.obj", nullptr));
- EXPECT_TRUE(StringRef(errorMessage()).startswith("Invalid heap size"));
-}
-
-TEST_F(WinLinkParserTest, SectionAlignment) {
- EXPECT_TRUE(parse("link.exe", "/align:8192", "a.obj", nullptr));
- EXPECT_EQ(8192U, _ctx.getSectionDefaultAlignment());
-}
-
-TEST_F(WinLinkParserTest, InvalidAlignment) {
- EXPECT_FALSE(parse("link.exe", "/align:1000", "a.obj", nullptr));
- EXPECT_EQ("Section alignment must be a power of 2, but got 1000\n",
- errorMessage());
-}
-
-TEST_F(WinLinkParserTest, Include) {
- EXPECT_TRUE(parse("link.exe", "/include:foo", "a.out", nullptr));
- auto symbols = _ctx.initialUndefinedSymbols();
- EXPECT_FALSE(symbols.empty());
- EXPECT_EQ("foo", symbols[0]);
-}
-
-TEST_F(WinLinkParserTest, Merge) {
- EXPECT_TRUE(parse("link.exe", "/merge:.foo=.bar", "/merge:.bar=.baz",
- "a.out", nullptr));
- EXPECT_EQ(".baz", _ctx.getOutputSectionName(".foo"));
- EXPECT_EQ(".baz", _ctx.getOutputSectionName(".bar"));
- EXPECT_EQ(".abc", _ctx.getOutputSectionName(".abc"));
-}
-
-TEST_F(WinLinkParserTest, Merge_Circular) {
- EXPECT_FALSE(parse("link.exe", "/merge:.foo=.bar", "/merge:.bar=.foo",
- "a.out", nullptr));
-}
-
-TEST_F(WinLinkParserTest, Implib) {
- EXPECT_TRUE(parse("link.exe", "/implib:foo.dll.lib", "a.out", nullptr));
- EXPECT_EQ("foo.dll.lib", _ctx.getOutputImportLibraryPath());
-}
-
-TEST_F(WinLinkParserTest, ImplibDefault) {
- EXPECT_TRUE(parse("link.exe", "/out:foobar.dll", "a.out", nullptr));
- EXPECT_EQ("foobar.lib", _ctx.getOutputImportLibraryPath());
-}
-
-//
-// Tests for /section
-//
-
-namespace {
-const uint32_t discardable = llvm::COFF::IMAGE_SCN_MEM_DISCARDABLE;
-const uint32_t not_cached = llvm::COFF::IMAGE_SCN_MEM_NOT_CACHED;
-const uint32_t not_paged = llvm::COFF::IMAGE_SCN_MEM_NOT_PAGED;
-const uint32_t shared = llvm::COFF::IMAGE_SCN_MEM_SHARED;
-const uint32_t execute = llvm::COFF::IMAGE_SCN_MEM_EXECUTE;
-const uint32_t read = llvm::COFF::IMAGE_SCN_MEM_READ;
-const uint32_t write = llvm::COFF::IMAGE_SCN_MEM_WRITE;
-
-#define TEST_SECTION(testname, arg, expect) \
- TEST_F(WinLinkParserTest, testname) { \
- EXPECT_TRUE(parse("link.exe", "/section:.text," arg, "a.obj", nullptr)); \
- EXPECT_EQ(expect, _ctx.getSectionAttributes(".text", execute | read)); \
- }
-
-TEST_SECTION(SectionD, "d", execute | read | discardable)
-TEST_SECTION(SectionE, "e", execute)
-TEST_SECTION(SectionK, "k", execute | read | not_cached)
-TEST_SECTION(SectionP, "p", execute | read | not_paged)
-TEST_SECTION(SectionR, "r", read)
-TEST_SECTION(SectionS, "s", execute | read | shared)
-TEST_SECTION(SectionW, "w", write)
-
-#undef TEST_SECTION
-
-TEST_F(WinLinkParserTest, Section) {
- EXPECT_TRUE(parse("link.exe", "/section:.text,dekprsw",
- "/section:.text,!dekprsw", "a.obj", nullptr));
- EXPECT_EQ(0U, _ctx.getSectionAttributes(".text", execute | read));
-}
-
-TEST_F(WinLinkParserTest, SectionNegate) {
- EXPECT_TRUE(parse("link.exe", "/section:.text,!e", "a.obj", nullptr));
- EXPECT_EQ(read, _ctx.getSectionAttributes(".text", execute | read));
-}
-
-TEST_F(WinLinkParserTest, SectionMultiple) {
- EXPECT_TRUE(parse("link.exe", "/section:.foo,e", "/section:.foo,rw",
- "/section:.foo,!d", "a.obj", nullptr));
- uint32_t flags = execute | read | not_paged | discardable;
- uint32_t expected = execute | read | write | not_paged;
- EXPECT_EQ(expected, _ctx.getSectionAttributes(".foo", flags));
-}
-
-} // end anonymous namespace
-
-//
-// Tests for /defaultlib and /nodefaultlib.
-//
-
-TEST_F(WinLinkParserTest, DefaultLib) {
- EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
- "/defaultlib:kernel32", "a.obj", nullptr));
- EXPECT_EQ(4, inputFileCount());
- EXPECT_EQ("a.obj", inputFile(0));
- EXPECT_EQ("user32.lib", inputFile(1));
- EXPECT_EQ("kernel32.lib", inputFile(2));
-}
-
-TEST_F(WinLinkParserTest, DefaultLibDuplicates) {
- EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
- "/defaultlib:user32.lib", "a.obj", nullptr));
- EXPECT_EQ(3, inputFileCount());
- EXPECT_EQ("a.obj", inputFile(0));
- EXPECT_EQ("user32.lib", inputFile(1));
-}
-
-TEST_F(WinLinkParserTest, NoDefaultLib) {
- EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
- "/defaultlib:kernel32", "/nodefaultlib:user32.lib", "a.obj",
- nullptr));
- EXPECT_EQ(3, inputFileCount());
- EXPECT_EQ("a.obj", inputFile(0));
- EXPECT_EQ("kernel32.lib", inputFile(1));
-}
-
-TEST_F(WinLinkParserTest, NoDefaultLibCase) {
- EXPECT_TRUE(parse("link.exe", "/defaultlib:user32",
- "/defaultlib:kernel32", "/nodefaultlib:USER32.LIB", "a.obj",
- nullptr));
- EXPECT_EQ(3, inputFileCount());
- EXPECT_EQ("a.obj", inputFile(0));
- EXPECT_EQ("kernel32.lib", inputFile(1));
-}
-
-TEST_F(WinLinkParserTest, NoDefaultLibAll) {
- EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
- "/defaultlib:kernel32", "/nodefaultlib", "a.obj", nullptr));
- EXPECT_EQ(2, inputFileCount());
- EXPECT_EQ("a.obj", inputFile(0));
-}
-
-TEST_F(WinLinkParserTest, DisallowLib) {
- EXPECT_TRUE(parse("link.exe", "/defaultlib:user32.lib",
- "/defaultlib:kernel32", "/disallowlib:user32.lib", "a.obj",
- nullptr));
- EXPECT_EQ(3, inputFileCount());
- EXPECT_EQ("a.obj", inputFile(0));
- EXPECT_EQ("kernel32.lib", inputFile(1));
-}
-
-//
-// Tests for DLL.
-//
-
-TEST_F(WinLinkParserTest, NoEntry) {
- EXPECT_TRUE(parse("link.exe", "/noentry", "/dll", "a.obj", nullptr));
- EXPECT_TRUE(_ctx.isDll());
- EXPECT_EQ(0x10000000U, _ctx.getBaseAddress());
- EXPECT_EQ("", _ctx.entrySymbolName());
-}
-
-TEST_F(WinLinkParserTest, NoEntryError) {
- // /noentry without /dll is an error.
- EXPECT_FALSE(parse("link.exe", "/noentry", "a.obj", nullptr));
- EXPECT_EQ("/noentry must be specified with /dll\n", errorMessage());
-}
-
-//
-// Tests for DELAYLOAD.
-//
-
-TEST_F(WinLinkParserTest, DelayLoad) {
- EXPECT_TRUE(parse("link.exe", "/delayload:abc.dll", "/delayload:def.dll",
- "a.obj", nullptr));
- EXPECT_TRUE(_ctx.isDelayLoadDLL("abc.dll"));
- EXPECT_TRUE(_ctx.isDelayLoadDLL("DEF.DLL"));
- EXPECT_FALSE(_ctx.isDelayLoadDLL("xyz.dll"));
-}
-
-//
-// Tests for SEH.
-//
-
-TEST_F(WinLinkParserTest, SafeSEH) {
- EXPECT_TRUE(parse("link.exe", "/safeseh", "a.obj", nullptr));
- EXPECT_TRUE(_ctx.requireSEH());
- EXPECT_FALSE(_ctx.noSEH());
-}
-
-TEST_F(WinLinkParserTest, NoSafeSEH) {
- EXPECT_TRUE(parse("link.exe", "/safeseh:no", "a.obj", nullptr));
- EXPECT_FALSE(_ctx.requireSEH());
- EXPECT_TRUE(_ctx.noSEH());
-}
-
-//
-// Tests for boolean flags.
-//
-
-TEST_F(WinLinkParserTest, Force) {
- EXPECT_TRUE(parse("link.exe", "/force", "a.obj", nullptr));
- EXPECT_TRUE(_ctx.allowRemainingUndefines());
-}
-
-TEST_F(WinLinkParserTest, ForceUnresolved) {
- EXPECT_TRUE(parse("link.exe", "/force:unresolved", "a.obj", nullptr));
- EXPECT_TRUE(_ctx.allowRemainingUndefines());
-}
-
-TEST_F(WinLinkParserTest, NoNxCompat) {
- EXPECT_TRUE(parse("link.exe", "/nxcompat:no", "a.obj", nullptr));
- EXPECT_FALSE(_ctx.isNxCompat());
-}
-
-TEST_F(WinLinkParserTest, LargeAddressAware) {
- EXPECT_TRUE(parse("link.exe", "/largeaddressaware", "a.obj", nullptr));
- EXPECT_TRUE(_ctx.getLargeAddressAware());
-}
-
-TEST_F(WinLinkParserTest, NoLargeAddressAware) {
- EXPECT_TRUE(parse("link.exe", "/largeaddressaware:no", "a.obj", nullptr));
- EXPECT_FALSE(_ctx.getLargeAddressAware());
-}
-
-TEST_F(WinLinkParserTest, AllowBind) {
- EXPECT_TRUE(parse("link.exe", "/allowbind", "a.obj", nullptr));
- EXPECT_TRUE(_ctx.getAllowBind());
-}
-
-TEST_F(WinLinkParserTest, NoAllowBind) {
- EXPECT_TRUE(parse("link.exe", "/allowbind:no", "a.obj", nullptr));
- EXPECT_FALSE(_ctx.getAllowBind());
-}
-
-TEST_F(WinLinkParserTest, AllowIsolation) {
- EXPECT_TRUE(parse("link.exe", "/allowisolation", "a.obj", nullptr));
- EXPECT_TRUE(_ctx.getAllowIsolation());
-}
-
-TEST_F(WinLinkParserTest, NoAllowIsolation) {
- EXPECT_TRUE(parse("link.exe", "/allowisolation:no", "a.obj", nullptr));
- EXPECT_FALSE(_ctx.getAllowIsolation());
-}
-
-TEST_F(WinLinkParserTest, SwapRunFromCD) {
- EXPECT_TRUE(parse("link.exe", "/swaprun:cd", "a.obj", nullptr));
- EXPECT_TRUE(_ctx.getSwapRunFromCD());
-}
-
-TEST_F(WinLinkParserTest, SwapRunFromNet) {
- EXPECT_TRUE(parse("link.exe", "/swaprun:net", "a.obj", nullptr));
- EXPECT_TRUE(_ctx.getSwapRunFromNet());
-}
-
-TEST_F(WinLinkParserTest, Debug) {
- EXPECT_TRUE(parse("link.exe", "/debug", "a.obj", nullptr));
- EXPECT_TRUE(_ctx.deadStrip());
- EXPECT_TRUE(_ctx.getDebug());
- EXPECT_EQ("a.pdb", _ctx.getPDBFilePath());
-}
-
-TEST_F(WinLinkParserTest, PDB) {
- EXPECT_TRUE(parse("link.exe", "/debug", "/pdb:foo.pdb", "a.obj", nullptr));
- EXPECT_TRUE(_ctx.getDebug());
- EXPECT_EQ("foo.pdb", _ctx.getPDBFilePath());
-}
-
-TEST_F(WinLinkParserTest, Fixed) {
- EXPECT_TRUE(parse("link.exe", "/fixed", "a.out", nullptr));
- EXPECT_FALSE(_ctx.getBaseRelocationEnabled());
- EXPECT_FALSE(_ctx.getDynamicBaseEnabled());
-}
-
-TEST_F(WinLinkParserTest, NoFixed) {
- EXPECT_TRUE(parse("link.exe", "/fixed:no", "a.out", nullptr));
- EXPECT_TRUE(_ctx.getBaseRelocationEnabled());
-}
-
-TEST_F(WinLinkParserTest, TerminalServerAware) {
- EXPECT_TRUE(parse("link.exe", "/tsaware", "a.out", nullptr));
- EXPECT_TRUE(_ctx.isTerminalServerAware());
-}
-
-TEST_F(WinLinkParserTest, NoTerminalServerAware) {
- EXPECT_TRUE(parse("link.exe", "/tsaware:no", "a.out", nullptr));
- EXPECT_FALSE(_ctx.isTerminalServerAware());
-}
-
-TEST_F(WinLinkParserTest, DynamicBase) {
- EXPECT_TRUE(parse("link.exe", "/dynamicbase", "a.out", nullptr));
- EXPECT_TRUE(_ctx.getDynamicBaseEnabled());
-}
-
-TEST_F(WinLinkParserTest, NoDynamicBase) {
- EXPECT_TRUE(parse("link.exe", "/dynamicbase:no", "a.out", nullptr));
- EXPECT_FALSE(_ctx.getDynamicBaseEnabled());
-}
-
-//
-// Test for /failifmismatch
-//
-
-TEST_F(WinLinkParserTest, FailIfMismatch_Match) {
- EXPECT_TRUE(parse("link.exe", "/failifmismatch:foo=bar",
- "/failifmismatch:foo=bar", "/failifmismatch:abc=def",
- "a.out", nullptr));
-}
-
-TEST_F(WinLinkParserTest, FailIfMismatch_Mismatch) {
- EXPECT_FALSE(parse("link.exe", "/failifmismatch:foo=bar",
- "/failifmismatch:foo=baz", "a.out", nullptr));
-}
-
-//
-// Tests for /manifest, /manifestuac, /manifestfile, and /manifestdependency.
-//
-TEST_F(WinLinkParserTest, Manifest_Default) {
- EXPECT_TRUE(parse("link.exe", "/manifest", "a.out", nullptr));
- EXPECT_TRUE(_ctx.getCreateManifest());
- EXPECT_FALSE(_ctx.getEmbedManifest());
- EXPECT_EQ(1, _ctx.getManifestId());
- EXPECT_EQ("'asInvoker'", _ctx.getManifestLevel());
- EXPECT_EQ("'false'", _ctx.getManifestUiAccess());
-}
-
-TEST_F(WinLinkParserTest, Manifest_No) {
- EXPECT_TRUE(parse("link.exe", "/manifest:no", "a.out", nullptr));
- EXPECT_FALSE(_ctx.getCreateManifest());
-}
-
-TEST_F(WinLinkParserTest, Manifestuac_no) {
- EXPECT_TRUE(parse("link.exe", "/manifestuac:NO", "a.out", nullptr));
- EXPECT_FALSE(_ctx.getManifestUAC());
-}
-
-TEST_F(WinLinkParserTest, Manifestuac_Level) {
- EXPECT_TRUE(parse("link.exe", "/manifestuac:level='requireAdministrator'",
- "a.out", nullptr));
- EXPECT_EQ("'requireAdministrator'", _ctx.getManifestLevel());
- EXPECT_EQ("'false'", _ctx.getManifestUiAccess());
-}
-
-TEST_F(WinLinkParserTest, Manifestuac_UiAccess) {
- EXPECT_TRUE(parse("link.exe", "/manifestuac:uiAccess='true'", "a.out", nullptr));
- EXPECT_EQ("'asInvoker'", _ctx.getManifestLevel());
- EXPECT_EQ("'true'", _ctx.getManifestUiAccess());
-}
-
-TEST_F(WinLinkParserTest, Manifestuac_LevelAndUiAccess) {
- EXPECT_TRUE(parse("link.exe",
- "/manifestuac:level='requireAdministrator' uiAccess='true'",
- "a.out", nullptr));
- EXPECT_EQ("'requireAdministrator'", _ctx.getManifestLevel());
- EXPECT_EQ("'true'", _ctx.getManifestUiAccess());
-}
-
-TEST_F(WinLinkParserTest, Manifestfile) {
- EXPECT_TRUE(parse("link.exe", "/manifestfile:bar.manifest",
- "a.out", nullptr));
- EXPECT_EQ("bar.manifest", _ctx.getManifestOutputPath());
-}
-
-TEST_F(WinLinkParserTest, Manifestdependency) {
- EXPECT_TRUE(parse("link.exe", "/manifestdependency:foo bar", "a.out",
- nullptr));
- EXPECT_EQ("foo bar", _ctx.getManifestDependency());
-}
-
-//
-// Test for /OPT
-//
-
-TEST_F(WinLinkParserTest, OptNoRef) {
- EXPECT_TRUE(parse("link.exe", "/opt:noref", "a.obj", nullptr));
- EXPECT_FALSE(_ctx.deadStrip());
-}
-
-TEST_F(WinLinkParserTest, OptIgnore) {
- EXPECT_TRUE(parse("link.exe", "/opt:ref", "/opt:icf", "/opt:noicf",
- "/opt:icf=foo", "/opt:lbr", "/opt:nolbr", "a.obj",
- nullptr));
-}
-
-TEST_F(WinLinkParserTest, OptUnknown) {
- EXPECT_FALSE(parse("link.exe", "/opt:foo", "a.obj", nullptr));
-}
-
-//
-// Test for /PROFILE
-//
-
-TEST_F(WinLinkParserTest, Profile) {
- EXPECT_TRUE(parse("link.exe", "/profile", "a.obj", nullptr));
- EXPECT_TRUE(_ctx.deadStrip());
- EXPECT_TRUE(_ctx.getBaseRelocationEnabled());
- EXPECT_TRUE(_ctx.getDynamicBaseEnabled());
-}
-
-//
-// Test for command line flags that are ignored.
-//
-
-TEST_F(WinLinkParserTest, Ignore) {
- // There are some no-op command line options that are recognized for
- // compatibility with link.exe.
- EXPECT_TRUE(parse("link.exe", "/nologo", "/errorreport:prompt",
- "/incremental", "/incremental:no", "/delay:unload",
- "/disallowlib:foo", "/pdbaltpath:bar",
- "/wx", "/wx:no", "/tlbid:1", "/tlbout:foo", "/idlout:foo",
- "/ignore:4000", "/ignoreidl", "/implib:foo", "/safeseh",
- "/safeseh:no", "/functionpadmin", "/maxilksize:1024",
- "a.obj", nullptr));
- EXPECT_EQ("", errorMessage());
- EXPECT_EQ(2, inputFileCount());
- EXPECT_EQ("a.obj", inputFile(0));
-}
-
-//
-// Test for "--"
-//
-
-TEST_F(WinLinkParserTest, DashDash) {
- EXPECT_TRUE(parse("link.exe", "/subsystem:console", "/out:a.exe", "a.obj",
- "--", "b.obj", "-c.obj", nullptr));
- EXPECT_EQ(llvm::COFF::IMAGE_SUBSYSTEM_WINDOWS_CUI, _ctx.getSubsystem());
- EXPECT_EQ("a.exe", _ctx.outputPath());
- EXPECT_EQ(4, inputFileCount());
- EXPECT_EQ("a.obj", inputFile(0));
- EXPECT_EQ("b.obj", inputFile(1));
- EXPECT_EQ("-c.obj", inputFile(2));
-}
diff --git a/unittests/DriverTests/WinLinkModuleDefTest.cpp b/unittests/DriverTests/WinLinkModuleDefTest.cpp
deleted file mode 100644
index 6762fd4b2ea6..000000000000
--- a/unittests/DriverTests/WinLinkModuleDefTest.cpp
+++ /dev/null
@@ -1,155 +0,0 @@
-//===- lld/unittest/WinLinkModuleDefTest.cpp ------------------------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-
-#include "gtest/gtest.h"
-#include "lld/Driver/WinLinkModuleDef.h"
-#include "llvm/Support/MemoryBuffer.h"
-#include <memory>
-
-using namespace llvm;
-using namespace lld;
-
-class ParserTest : public testing::Test {
-protected:
- std::vector<moduledef::Directive *> _dirs;
-
- void parse(const char *contents) {
- auto membuf =
- std::unique_ptr<MemoryBuffer>(MemoryBuffer::getMemBuffer(contents));
- moduledef::Lexer lexer(std::move(membuf));
- moduledef::Parser parser(lexer, _alloc);
- EXPECT_TRUE(parser.parse(_dirs));
- EXPECT_TRUE(!_dirs.empty());
- }
-
- void verifyExportDesc(const PECOFFLinkingContext::ExportDesc &exp,
- StringRef sym, int ordinal, bool noname, bool isData) {
- EXPECT_EQ(sym, exp.name);
- EXPECT_EQ(ordinal, exp.ordinal);
- EXPECT_EQ(noname, exp.noname);
- EXPECT_EQ(isData, exp.isData);
- }
-
-private:
- llvm::BumpPtrAllocator _alloc;
-};
-
-TEST_F(ParserTest, Exports) {
- parse("EXPORTS\n"
- " sym1\n"
- " sym2 @5\n"
- " sym3 @8 NONAME\n"
- " sym4 DATA\n"
- " sym5 @10 NONAME DATA\n");
- EXPECT_EQ(1U, _dirs.size());
- const std::vector<PECOFFLinkingContext::ExportDesc> &exports =
- cast<moduledef::Exports>(_dirs[0])->getExports();
- EXPECT_EQ(5U, exports.size());
- verifyExportDesc(exports[0], "sym1", -1, false, false);
- verifyExportDesc(exports[1], "sym2", 5, false, false);
- verifyExportDesc(exports[2], "sym3", 8, true, false);
- verifyExportDesc(exports[3], "sym4", -1, false, true);
- verifyExportDesc(exports[4], "sym5", 10, true, true);
-}
-
-TEST_F(ParserTest, Heapsize) {
- parse("HEAPSIZE 65536");
- EXPECT_EQ(1U, _dirs.size());
- auto *heapsize = cast<moduledef::Heapsize>(_dirs[0]);
- EXPECT_EQ(65536U, heapsize->getReserve());
- EXPECT_EQ(0U, heapsize->getCommit());
-}
-
-TEST_F(ParserTest, HeapsizeWithCommit) {
- parse("HEAPSIZE 65536, 8192");
- EXPECT_EQ(1U, _dirs.size());
- auto *heapsize = cast<moduledef::Heapsize>(_dirs[0]);
- EXPECT_EQ(65536U, heapsize->getReserve());
- EXPECT_EQ(8192U, heapsize->getCommit());
-}
-
-TEST_F(ParserTest, StacksizeBasic) {
- parse("STACKSIZE 65536");
- EXPECT_EQ(1U, _dirs.size());
- auto *stacksize = cast<moduledef::Stacksize>(_dirs[0]);
- EXPECT_EQ(65536U, stacksize->getReserve());
- EXPECT_EQ(0U, stacksize->getCommit());
-}
-
-TEST_F(ParserTest, StacksizeWithCommit) {
- parse("STACKSIZE 65536, 8192");
- EXPECT_EQ(1U, _dirs.size());
- auto *stacksize = cast<moduledef::Stacksize>(_dirs[0]);
- EXPECT_EQ(65536U, stacksize->getReserve());
- EXPECT_EQ(8192U, stacksize->getCommit());
-}
-
-TEST_F(ParserTest, Library) {
- parse("LIBRARY foo.dll");
- EXPECT_EQ(1U, _dirs.size());
- auto *lib = cast<moduledef::Library>(_dirs[0]);
- EXPECT_EQ("foo.dll", lib->getName());
-}
-
-TEST_F(ParserTest, NameBasic) {
- parse("NAME foo.exe");
- EXPECT_EQ(1U, _dirs.size());
- auto *name = cast<moduledef::Name>(_dirs[0]);
- EXPECT_EQ("foo.exe", name->getOutputPath());
- EXPECT_EQ(0U, name->getBaseAddress());
-}
-
-TEST_F(ParserTest, NameWithBase) {
- parse("NAME foo.exe BASE=4096");
- EXPECT_EQ(1U, _dirs.size());
- auto *name = cast<moduledef::Name>(_dirs[0]);
- EXPECT_EQ("foo.exe", name->getOutputPath());
- EXPECT_EQ(4096U, name->getBaseAddress());
-}
-
-TEST_F(ParserTest, NameLongFileName) {
- parse("NAME \"a long file name.exe\"");
- EXPECT_EQ(1U, _dirs.size());
- auto *name = cast<moduledef::Name>(_dirs[0]);
- EXPECT_EQ("a long file name.exe", name->getOutputPath());
- EXPECT_EQ(0U, name->getBaseAddress());
-}
-
-TEST_F(ParserTest, VersionMajor) {
- parse("VERSION 12");
- EXPECT_EQ(1U, _dirs.size());
- auto *ver = cast<moduledef::Version>(_dirs[0]);
- EXPECT_EQ(12, ver->getMajorVersion());
- EXPECT_EQ(0, ver->getMinorVersion());
-}
-
-TEST_F(ParserTest, VersionMajorMinor) {
- parse("VERSION 12.34");
- EXPECT_EQ(1U, _dirs.size());
- auto *ver = cast<moduledef::Version>(_dirs[0]);
- EXPECT_EQ(12, ver->getMajorVersion());
- EXPECT_EQ(34, ver->getMinorVersion());
-}
-
-TEST_F(ParserTest, Multiple) {
- parse("LIBRARY foo\n"
- "EXPORTS sym\n"
- "VERSION 12");
- EXPECT_EQ(3U, _dirs.size());
- auto *lib = cast<moduledef::Library>(_dirs[0]);
- EXPECT_EQ("foo.dll", lib->getName());
-
- const std::vector<PECOFFLinkingContext::ExportDesc> &exports =
- cast<moduledef::Exports>(_dirs[1])->getExports();
- EXPECT_EQ(1U, exports.size());
- verifyExportDesc(exports[0], "sym", -1, false, false);
-
- auto *ver = cast<moduledef::Version>(_dirs[2]);
- EXPECT_EQ(12, ver->getMajorVersion());
-}
diff --git a/unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp b/unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp
index 22ed3f15b3e6..6827a732fbd8 100644
--- a/unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp
+++ b/unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp
@@ -273,7 +273,7 @@ TEST(BinaryReaderTest, hello_obj_x86_64) {
EXPECT_EQ(text.type, S_REGULAR);
EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
| S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ(text.alignment, 4U);
+ EXPECT_EQ((uint16_t)text.alignment, 16U);
EXPECT_EQ(text.address, Hex64(0x0));
EXPECT_EQ(text.content.size(), 45UL);
EXPECT_EQ((int)(text.content[0]), 0x55);
@@ -298,7 +298,7 @@ TEST(BinaryReaderTest, hello_obj_x86_64) {
EXPECT_TRUE(cstring.sectionName.equals("__cstring"));
EXPECT_EQ(cstring.type, S_CSTRING_LITERALS);
EXPECT_EQ(cstring.attributes, SectionAttr(0));
- EXPECT_EQ(cstring.alignment, 0U);
+ EXPECT_EQ((uint16_t)cstring.alignment, 1U);
EXPECT_EQ(cstring.address, Hex64(0x02D));
EXPECT_EQ(cstring.content.size(), 7UL);
EXPECT_EQ((int)(cstring.content[0]), 0x68);
@@ -399,7 +399,7 @@ TEST(BinaryReaderTest, hello_obj_x86) {
EXPECT_EQ(text.type, S_REGULAR);
EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
| S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ(text.alignment, 4U);
+ EXPECT_EQ((uint16_t)text.alignment, 16U);
EXPECT_EQ(text.address, Hex64(0x0));
EXPECT_EQ(text.content.size(), 48UL);
EXPECT_EQ((int)(text.content[0]), 0x55);
@@ -434,7 +434,7 @@ TEST(BinaryReaderTest, hello_obj_x86) {
EXPECT_TRUE(cstring.sectionName.equals("__cstring"));
EXPECT_EQ(cstring.type, S_CSTRING_LITERALS);
EXPECT_EQ(cstring.attributes, SectionAttr(0));
- EXPECT_EQ(cstring.alignment, 0U);
+ EXPECT_EQ((uint16_t)cstring.alignment, 1U);
EXPECT_EQ(cstring.address, Hex64(0x030));
EXPECT_EQ(cstring.content.size(), 7UL);
EXPECT_EQ((int)(cstring.content[0]), 0x68);
@@ -532,7 +532,7 @@ TEST(BinaryReaderTest, hello_obj_armv7) {
EXPECT_EQ(text.type, S_REGULAR);
EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
| S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ(text.alignment, 2U);
+ EXPECT_EQ((uint16_t)text.alignment, 4U);
EXPECT_EQ(text.address, Hex64(0x0));
EXPECT_EQ(text.content.size(), 42UL);
EXPECT_EQ((int)(text.content[0]), 0x80);
@@ -576,7 +576,7 @@ TEST(BinaryReaderTest, hello_obj_armv7) {
EXPECT_TRUE(cstring.sectionName.equals("__cstring"));
EXPECT_EQ(cstring.type, S_CSTRING_LITERALS);
EXPECT_EQ(cstring.attributes, SectionAttr(0));
- EXPECT_EQ(cstring.alignment, 0U);
+ EXPECT_EQ((uint16_t)cstring.alignment, 1U);
EXPECT_EQ(cstring.address, Hex64(0x02A));
EXPECT_EQ(cstring.content.size(), 7UL);
EXPECT_EQ((int)(cstring.content[0]), 0x68);
@@ -677,7 +677,7 @@ TEST(BinaryReaderTest, hello_obj_ppc) {
EXPECT_EQ(text.type, S_REGULAR);
EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
| S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ(text.alignment, 2U);
+ EXPECT_EQ((uint16_t)text.alignment, 4U);
EXPECT_EQ(text.address, Hex64(0x0));
EXPECT_EQ(text.content.size(), 68UL);
EXPECT_EQ((int)(text.content[0]), 0x7C);
@@ -720,7 +720,7 @@ TEST(BinaryReaderTest, hello_obj_ppc) {
EXPECT_TRUE(cstring.sectionName.equals("__cstring"));
EXPECT_EQ(cstring.type, S_CSTRING_LITERALS);
EXPECT_EQ(cstring.attributes, SectionAttr(0));
- EXPECT_EQ(cstring.alignment, 2U);
+ EXPECT_EQ((uint16_t)cstring.alignment, 4U);
EXPECT_EQ(cstring.address, Hex64(0x044));
EXPECT_EQ(cstring.content.size(), 7UL);
EXPECT_EQ((int)(cstring.content[0]), 0x68);
diff --git a/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp b/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp
index d79c6d62a847..87c527233cb1 100644
--- a/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp
+++ b/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp
@@ -123,7 +123,7 @@ TEST(BinaryWriterTest, obj_relocs_x86_64) {
text.type = S_REGULAR;
text.attributes = SectionAttr(S_ATTR_PURE_INSTRUCTIONS
| S_ATTR_SOME_INSTRUCTIONS);
- text.alignment = 4;
+ text.alignment = 16;
text.address = 0;
const uint8_t textBytes[] = {
0xe8, 0x00, 0x00, 0x00, 0x00, 0x48, 0x8b, 0x05,
@@ -179,7 +179,7 @@ TEST(BinaryWriterTest, obj_relocs_x86_64) {
EXPECT_EQ(S_REGULAR, text.type);
EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
| S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ(text.alignment, 4U);
+ EXPECT_EQ((uint16_t)text.alignment, 16U);
EXPECT_EQ(text.address, Hex64(0x0));
EXPECT_EQ(48UL, text.content.size());
const Relocation& call = text.relocations[0];
@@ -240,7 +240,7 @@ TEST(BinaryWriterTest, obj_relocs_x86) {
text.type = S_REGULAR;
text.attributes = SectionAttr(S_ATTR_PURE_INSTRUCTIONS
| S_ATTR_SOME_INSTRUCTIONS);
- text.alignment = 4;
+ text.alignment = 16;
text.address = 0;
const uint8_t textBytes[] = {
0xe8, 0xfb, 0xff, 0xff, 0xff, 0xa1, 0x00, 0x00,
@@ -290,7 +290,7 @@ TEST(BinaryWriterTest, obj_relocs_x86) {
EXPECT_EQ(S_REGULAR, text.type);
EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
| S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ(text.alignment, 4U);
+ EXPECT_EQ((uint16_t)text.alignment, 16U);
EXPECT_EQ(text.address, Hex64(0x0));
EXPECT_EQ(22UL, text.content.size());
const Relocation& call = text.relocations[0];
@@ -350,7 +350,7 @@ TEST(BinaryWriterTest, obj_relocs_armv7) {
text.type = S_REGULAR;
text.attributes = SectionAttr(S_ATTR_PURE_INSTRUCTIONS
| S_ATTR_SOME_INSTRUCTIONS);
- text.alignment = 2;
+ text.alignment = 4;
text.address = 0;
const uint8_t textBytes[] = {
0xff, 0xf7, 0xfe, 0xef, 0x40, 0xf2, 0x05, 0x01,
@@ -415,7 +415,7 @@ TEST(BinaryWriterTest, obj_relocs_armv7) {
EXPECT_EQ(S_REGULAR, text.type);
EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
| S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ(text.alignment, 2U);
+ EXPECT_EQ((uint16_t)text.alignment, 4U);
EXPECT_EQ(text.address, Hex64(0x0));
EXPECT_EQ(18UL, text.content.size());
const Relocation& blx = text.relocations[0];
@@ -479,7 +479,7 @@ TEST(BinaryWriterTest, obj_relocs_ppc) {
text.type = S_REGULAR;
text.attributes = SectionAttr(S_ATTR_PURE_INSTRUCTIONS
| S_ATTR_SOME_INSTRUCTIONS);
- text.alignment = 2;
+ text.alignment = 4;
text.address = 0;
const uint8_t textBytes[] = {
0x48, 0x00, 0x00, 0x01, 0x40, 0x82, 0xff, 0xfc,
@@ -571,7 +571,7 @@ TEST(BinaryWriterTest, obj_relocs_ppc) {
EXPECT_EQ(S_REGULAR, text.type);
EXPECT_EQ(text.attributes,SectionAttr(S_ATTR_PURE_INSTRUCTIONS
| S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ(text.alignment, 2U);
+ EXPECT_EQ((uint16_t)text.alignment, 4U);
EXPECT_EQ(text.address, Hex64(0x0));
EXPECT_EQ(44UL, text.content.size());
const Relocation& br24 = text.relocations[0];
@@ -690,4 +690,3 @@ TEST(BinaryWriterTest, obj_relocs_ppc) {
std::error_code ec = llvm::sys::fs::remove(Twine(tmpFl));
EXPECT_FALSE(ec);
}
-
diff --git a/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp b/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp
index 16ef88aa4a40..7def86c87929 100644
--- a/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp
+++ b/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp
@@ -66,7 +66,7 @@ TEST(ToAtomsTest, basic_obj_x86_64) {
EXPECT_FALSE(!atom_f);
const lld::File &file = **atom_f;
EXPECT_EQ(3U, file.defined().size());
- lld::File::defined_iterator it = file.defined().begin();
+ auto it = file.defined().begin();
const lld::DefinedAtom *atom1 = *it;
++it;
const lld::DefinedAtom *atom2 = *it;
diff --git a/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp b/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp
index 562dae60049d..d13e360b41a5 100644
--- a/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp
+++ b/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp
@@ -197,7 +197,7 @@ TEST(ObjectFileYAML, oneSection) {
" section: __text\n"
" type: S_REGULAR\n"
" attributes: [ S_ATTR_PURE_INSTRUCTIONS ]\n"
- " alignment: 1\n"
+ " alignment: 2\n"
" address: 0x12345678\n"
" content: [ 0x90, 0x90 ]\n"
"...\n");
@@ -213,7 +213,7 @@ TEST(ObjectFileYAML, oneSection) {
EXPECT_EQ((uint32_t)(sect.type), (uint32_t)(llvm::MachO::S_REGULAR));
EXPECT_EQ((uint32_t)(sect.attributes),
(uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS));
- EXPECT_EQ(sect.alignment, 1U);
+ EXPECT_EQ((uint16_t)sect.alignment, 2U);
EXPECT_EQ((uint64_t)sect.address, 0x12345678ULL);
EXPECT_EQ(sect.content.size(), 2UL);
EXPECT_EQ((int)(sect.content[0]), 0x90);
@@ -232,7 +232,7 @@ TEST(ObjectFileYAML, hello_x86_64) {
" section: __text\n"
" type: S_REGULAR\n"
" attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS]\n"
- " alignment: 0\n"
+ " alignment: 1\n"
" address: 0x0000\n"
" content: [ 0x55, 0x48, 0x89, 0xe5, 0x48, 0x8d, 0x3d, 0x00,\n"
" 0x00, 0x00, 0x00, 0x30, 0xc0, 0xe8, 0x00, 0x00,\n"
@@ -254,7 +254,7 @@ TEST(ObjectFileYAML, hello_x86_64) {
" section: __cstring\n"
" type: S_CSTRING_LITERALS\n"
" attributes: [ ]\n"
- " alignment: 0\n"
+ " alignment: 1\n"
" address: 0x0016\n"
" content: [ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x00 ]\n"
"global-symbols:\n"
@@ -286,7 +286,7 @@ TEST(ObjectFileYAML, hello_x86_64) {
EXPECT_EQ((uint32_t)(sect1.attributes),
(uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS
| llvm::MachO::S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ(sect1.alignment, 0U);
+ EXPECT_EQ((uint16_t)sect1.alignment, 1U);
EXPECT_EQ((uint64_t)sect1.address, 0x0ULL);
EXPECT_EQ(sect1.content.size(), 22UL);
EXPECT_EQ((int)(sect1.content[0]), 0x55);
@@ -316,7 +316,7 @@ TEST(ObjectFileYAML, hello_x86_64) {
EXPECT_TRUE(sect2.sectionName.equals("__cstring"));
EXPECT_EQ((uint32_t)(sect2.type), (uint32_t)(llvm::MachO::S_CSTRING_LITERALS));
EXPECT_EQ((uint32_t)(sect2.attributes), 0U);
- EXPECT_EQ(sect2.alignment, 0U);
+ EXPECT_EQ((uint16_t)sect2.alignment, 1U);
EXPECT_EQ((uint64_t)sect2.address, 0x016ULL);
EXPECT_EQ(sect2.content.size(), 7UL);
EXPECT_EQ((int)(sect2.content[0]), 0x68);
@@ -361,7 +361,7 @@ TEST(ObjectFileYAML, hello_x86) {
" section: __text\n"
" type: S_REGULAR\n"
" attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS]\n"
- " alignment: 0\n"
+ " alignment: 1\n"
" address: 0x0000\n"
" content: [ 0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, 0xe8, 0x00,\n"
" 0x00, 0x00, 0x00, 0x58, 0x8d, 0x80, 0x16, 0x00,\n"
@@ -391,7 +391,7 @@ TEST(ObjectFileYAML, hello_x86) {
" section: __cstring\n"
" type: S_CSTRING_LITERALS\n"
" attributes: [ ]\n"
- " alignment: 0\n"
+ " alignment: 1\n"
" address: 0x0021\n"
" content: [ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x00 ]\n"
"global-symbols:\n"
@@ -417,7 +417,7 @@ TEST(ObjectFileYAML, hello_x86) {
EXPECT_EQ((uint32_t)(sect1.attributes),
(uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS
| llvm::MachO::S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ(sect1.alignment, 0U);
+ EXPECT_EQ((uint16_t)sect1.alignment, 1U);
EXPECT_EQ((uint64_t)sect1.address, 0x0ULL);
EXPECT_EQ(sect1.content.size(), 33UL);
EXPECT_EQ((int)(sect1.content[0]), 0x55);
@@ -454,7 +454,7 @@ TEST(ObjectFileYAML, hello_x86) {
EXPECT_TRUE(sect2.sectionName.equals("__cstring"));
EXPECT_EQ((uint32_t)(sect2.type), (uint32_t)(llvm::MachO::S_CSTRING_LITERALS));
EXPECT_EQ((uint32_t)(sect2.attributes), 0U);
- EXPECT_EQ(sect2.alignment, 0U);
+ EXPECT_EQ((uint16_t)sect2.alignment, 1U);
EXPECT_EQ((uint64_t)sect2.address, 0x021ULL);
EXPECT_EQ(sect2.content.size(), 7UL);
EXPECT_EQ((int)(sect2.content[0]), 0x68);
@@ -490,7 +490,7 @@ TEST(ObjectFileYAML, hello_armv6) {
" section: __text\n"
" type: S_REGULAR\n"
" attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS]\n"
- " alignment: 2\n"
+ " alignment: 4\n"
" address: 0x0000\n"
" content: [ 0x80, 0x40, 0x2d, 0xe9, 0x10, 0x00, 0x9f, 0xe5,\n"
" 0x0d, 0x70, 0xa0, 0xe1, 0x00, 0x00, 0x8f, 0xe0,\n"
@@ -519,7 +519,7 @@ TEST(ObjectFileYAML, hello_armv6) {
" section: __cstring\n"
" type: S_CSTRING_LITERALS\n"
" attributes: [ ]\n"
- " alignment: 0\n"
+ " alignment: 1\n"
" address: 0x0020\n"
" content: [ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x00 ]\n"
"global-symbols:\n"
@@ -545,7 +545,7 @@ TEST(ObjectFileYAML, hello_armv6) {
EXPECT_EQ((uint32_t)(sect1.attributes),
(uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS
| llvm::MachO::S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ(sect1.alignment, 2U);
+ EXPECT_EQ((uint16_t)sect1.alignment, 4U);
EXPECT_EQ((uint64_t)sect1.address, 0x0ULL);
EXPECT_EQ(sect1.content.size(), 32UL);
EXPECT_EQ((int)(sect1.content[0]), 0x80);
@@ -582,7 +582,7 @@ TEST(ObjectFileYAML, hello_armv6) {
EXPECT_TRUE(sect2.sectionName.equals("__cstring"));
EXPECT_EQ((uint32_t)(sect2.type), (uint32_t)(llvm::MachO::S_CSTRING_LITERALS));
EXPECT_EQ((uint32_t)(sect2.attributes), 0U);
- EXPECT_EQ(sect2.alignment, 0U);
+ EXPECT_EQ((uint16_t)sect2.alignment, 1U);
EXPECT_EQ((uint64_t)sect2.address, 0x020ULL);
EXPECT_EQ(sect2.content.size(), 7UL);
EXPECT_EQ((int)(sect2.content[0]), 0x68);
@@ -620,7 +620,7 @@ TEST(ObjectFileYAML, hello_armv7) {
" section: __text\n"
" type: S_REGULAR\n"
" attributes: [ S_ATTR_PURE_INSTRUCTIONS, S_ATTR_SOME_INSTRUCTIONS]\n"
- " alignment: 1\n"
+ " alignment: 2\n"
" address: 0x0000\n"
" content: [ 0x80, 0xb5, 0x40, 0xf2, 0x06, 0x00, 0x6f, 0x46,\n"
" 0xc0, 0xf2, 0x00, 0x00, 0x78, 0x44, 0xff, 0xf7,\n"
@@ -660,7 +660,7 @@ TEST(ObjectFileYAML, hello_armv7) {
" section: __cstring\n"
" type: S_CSTRING_LITERALS\n"
" attributes: [ ]\n"
- " alignment: 0\n"
+ " alignment: 1\n"
" address: 0x0016\n"
" content: [ 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x0a, 0x00 ]\n"
"global-symbols:\n"
@@ -687,7 +687,7 @@ TEST(ObjectFileYAML, hello_armv7) {
EXPECT_EQ((uint32_t)(sect1.attributes),
(uint32_t)(llvm::MachO::S_ATTR_PURE_INSTRUCTIONS
| llvm::MachO::S_ATTR_SOME_INSTRUCTIONS));
- EXPECT_EQ(sect1.alignment, 1U);
+ EXPECT_EQ((uint16_t)sect1.alignment, 2U);
EXPECT_EQ((uint64_t)sect1.address, 0x0ULL);
EXPECT_EQ(sect1.content.size(), 22UL);
EXPECT_EQ((int)(sect1.content[0]), 0x80);
@@ -740,7 +740,7 @@ TEST(ObjectFileYAML, hello_armv7) {
EXPECT_TRUE(sect2.sectionName.equals("__cstring"));
EXPECT_EQ((uint32_t)(sect2.type), (uint32_t)(llvm::MachO::S_CSTRING_LITERALS));
EXPECT_EQ((uint32_t)(sect2.attributes), 0U);
- EXPECT_EQ(sect2.alignment, 0U);
+ EXPECT_EQ((uint16_t)sect2.alignment, 1U);
EXPECT_EQ((uint64_t)sect2.address, 0x016ULL);
EXPECT_EQ(sect2.content.size(), 7UL);
EXPECT_EQ((int)(sect2.content[0]), 0x68);
diff --git a/unittests/Makefile b/unittests/Makefile
deleted file mode 100644
index 0fbb17d48289..000000000000
--- a/unittests/Makefile
+++ /dev/null
@@ -1,31 +0,0 @@
-##===- unittests/Makefile ----------------------------------*- Makefile -*-===##
-#
-# The LLVM Compiler Infrastructure
-#
-# This file is distributed under the University of Illinois Open Source
-# License. See LICENSE.TXT for details.
-#
-##===----------------------------------------------------------------------===##
-
-# If LLD_LEVEL is not set, then we are the top-level Makefile. Otherwise, we
-# are being included from a subdirectory makefile.
-
-ifndef LLD_LEVEL
-
-IS_UNITTEST_LEVEL := 1
-LLD_LEVEL := ..
-
-PARALLEL_DIRS = CoreTests DriverTests
-
-include $(LLD_LEVEL)/../../Makefile.config
-
-endif # LLD_LEVEL
-
-include $(LLD_LEVEL)/Makefile
-
-ifndef IS_UNITTEST_LEVEL
-
-MAKEFILE_UNITTEST_NO_INCLUDE_COMMON := 1
-include $(LLVM_SRC_ROOT)/unittests/Makefile.unittest
-
-endif # IS_UNITTEST_LEVEL
diff --git a/utils/astyle-options b/utils/astyle-options
deleted file mode 100644
index 53c496bfebc0..000000000000
--- a/utils/astyle-options
+++ /dev/null
@@ -1,7 +0,0 @@
-style=java
-indent=spaces=2
-pad-oper
-pad-header
-unpad-paren
-convert-tabs
-align-pointer=name