aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2016-07-23 20:48:50 +0000
committerDimitry Andric <dim@FreeBSD.org>2016-07-23 20:48:50 +0000
commit1c98619801a5705c688e683be3ef9d70169a0686 (patch)
tree8422105cd1a94c368315f2db16b9ac746cf7c000
parentf4f3ce4613680903220815690ad79fc7ba0a2e26 (diff)
downloadsrc-1c98619801a5705c688e683be3ef9d70169a0686.tar.gz
src-1c98619801a5705c688e683be3ef9d70169a0686.zip
Vendor import of lld release_39 branch r276489:vendor/lld/lld-release_39-r276489
Notes
Notes: svn path=/vendor/lld/dist/; revision=303239 svn path=/vendor/lld/lld-release_39-r276489/; revision=303240; tag=vendor/lld/lld-release_39-r276489
-rw-r--r--.arcconfig2
-rw-r--r--CMakeLists.txt2
-rw-r--r--COFF/CMakeLists.txt3
-rw-r--r--COFF/Chunks.cpp13
-rw-r--r--COFF/Chunks.h10
-rw-r--r--COFF/Config.h4
-rw-r--r--COFF/DLL.cpp2
-rw-r--r--COFF/Driver.cpp55
-rw-r--r--COFF/Driver.h5
-rw-r--r--COFF/DriverUtils.cpp332
-rw-r--r--COFF/Error.cpp13
-rw-r--r--COFF/Error.h18
-rw-r--r--COFF/ICF.cpp6
-rw-r--r--COFF/InputFiles.cpp119
-rw-r--r--COFF/InputFiles.h9
-rw-r--r--COFF/Librarian.cpp489
-rw-r--r--COFF/ModuleDef.cpp14
-rw-r--r--COFF/Options.td2
-rw-r--r--COFF/PDB.cpp3
-rw-r--r--COFF/README.md266
-rw-r--r--COFF/SymbolTable.cpp33
-rw-r--r--COFF/SymbolTable.h2
-rw-r--r--COFF/Symbols.cpp28
-rw-r--r--COFF/Symbols.h4
-rw-r--r--COFF/Writer.cpp72
-rw-r--r--ELF/CMakeLists.txt28
-rw-r--r--ELF/Config.h63
-rw-r--r--ELF/Driver.cpp463
-rw-r--r--ELF/Driver.h65
-rw-r--r--ELF/DriverUtils.cpp234
-rw-r--r--ELF/EhFrame.cpp167
-rw-r--r--ELF/EhFrame.h22
-rw-r--r--ELF/Error.cpp49
-rw-r--r--ELF/Error.h39
-rw-r--r--ELF/ICF.cpp345
-rw-r--r--ELF/ICF.h19
-rw-r--r--ELF/InputFiles.cpp775
-rw-r--r--ELF/InputFiles.h187
-rw-r--r--ELF/InputSection.cpp779
-rw-r--r--ELF/InputSection.h206
-rw-r--r--ELF/LTO.cpp325
-rw-r--r--ELF/LTO.h54
-rw-r--r--ELF/LinkerScript.cpp566
-rw-r--r--ELF/LinkerScript.h103
-rw-r--r--ELF/MarkLive.cpp167
-rw-r--r--ELF/Options.td283
-rw-r--r--ELF/OutputSections.cpp2176
-rw-r--r--ELF/OutputSections.h596
-rw-r--r--ELF/README.md22
-rw-r--r--ELF/Relocations.cpp704
-rw-r--r--ELF/Relocations.h93
-rw-r--r--ELF/ScriptParser.cpp163
-rw-r--r--ELF/ScriptParser.h49
-rw-r--r--ELF/Strings.cpp98
-rw-r--r--ELF/Strings.h29
-rw-r--r--ELF/SymbolListFile.cpp168
-rw-r--r--ELF/SymbolListFile.h27
-rw-r--r--ELF/SymbolTable.cpp717
-rw-r--r--ELF/SymbolTable.h99
-rw-r--r--ELF/Symbols.cpp369
-rw-r--r--ELF/Symbols.h470
-rw-r--r--ELF/Target.cpp2678
-rw-r--r--ELF/Target.h151
-rw-r--r--ELF/Thunks.cpp268
-rw-r--r--ELF/Thunks.h56
-rw-r--r--ELF/Writer.cpp1564
-rw-r--r--ELF/Writer.h20
-rw-r--r--LICENSE.TXT2
-rw-r--r--docs/AtomLLD.rst61
-rw-r--r--docs/NewLLD.rst350
-rw-r--r--docs/ReleaseNotes.rst35
-rw-r--r--docs/conf.py3
-rw-r--r--docs/design.rst31
-rw-r--r--docs/index.rst72
-rw-r--r--docs/open_projects.rst5
-rw-r--r--include/lld/Core/Alias.h100
-rw-r--r--include/lld/Core/ArchiveLibraryFile.h15
-rw-r--r--include/lld/Core/Atom.h53
-rw-r--r--include/lld/Core/DefinedAtom.h50
-rw-r--r--include/lld/Core/Error.h42
-rw-r--r--include/lld/Core/File.h120
-rw-r--r--include/lld/Core/LLVM.h6
-rw-r--r--include/lld/Core/LinkingContext.h150
-rw-r--r--include/lld/Core/Node.h6
-rw-r--r--include/lld/Core/Parallel.h36
-rw-r--r--include/lld/Core/Pass.h4
-rw-r--r--include/lld/Core/PassManager.h7
-rw-r--r--include/lld/Core/Reader.h9
-rw-r--r--include/lld/Core/Reference.h18
-rw-r--r--include/lld/Core/Resolver.h41
-rw-r--r--include/lld/Core/STDExtras.h29
-rw-r--r--include/lld/Core/SharedLibraryAtom.h4
-rw-r--r--include/lld/Core/SharedLibraryFile.h21
-rw-r--r--include/lld/Core/Simple.h150
-rw-r--r--include/lld/Core/SymbolTable.h11
-rw-r--r--include/lld/Core/UndefinedAtom.h10
-rw-r--r--include/lld/Core/Writer.h11
-rw-r--r--include/lld/Core/range.h738
-rw-r--r--include/lld/Driver/Driver.h138
-rw-r--r--include/lld/ReaderWriter/AtomLayout.h39
-rw-r--r--include/lld/ReaderWriter/CoreLinkingContext.h47
-rw-r--r--include/lld/ReaderWriter/ELFLinkingContext.h422
-rw-r--r--include/lld/ReaderWriter/LinkerScript.h1471
-rw-r--r--include/lld/ReaderWriter/MachOLinkingContext.h133
-rw-r--r--lib/Config/Version.cpp27
-rw-r--r--lib/Core/DefinedAtom.cpp11
-rw-r--r--lib/Core/Error.cpp48
-rw-r--r--lib/Core/File.cpp2
-rw-r--r--lib/Core/LinkingContext.cpp47
-rw-r--r--lib/Core/Reader.cpp1
-rw-r--r--lib/Core/Resolver.cpp330
-rw-r--r--lib/Core/SymbolTable.cpp92
-rw-r--r--lib/Driver/CMakeLists.txt21
-rw-r--r--lib/Driver/CoreDriver.cpp173
-rw-r--r--lib/Driver/CoreOptions.td15
-rw-r--r--lib/Driver/DarwinLdDriver.cpp387
-rw-r--r--lib/Driver/DarwinLdOptions.td35
-rw-r--r--lib/Driver/Driver.cpp142
-rw-r--r--lib/Driver/GnuLdDriver.cpp782
-rw-r--r--lib/Driver/GnuLdOptions.td378
-rw-r--r--lib/Driver/TODO.rst99
-rw-r--r--lib/Driver/UniversalDriver.cpp225
-rw-r--r--lib/Driver/UniversalDriverOptions.td19
-rw-r--r--lib/ReaderWriter/CMakeLists.txt3
-rw-r--r--lib/ReaderWriter/CoreLinkingContext.cpp50
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64DynamicLibraryWriter.h45
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.cpp52
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64ExecutableWriter.h38
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.cpp45
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64LinkingContext.h101
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.cpp556
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64RelocationHandler.h36
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.cpp612
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64RelocationPass.h32
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.cpp39
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64SectionChunks.h37
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.cpp51
-rw-r--r--lib/ReaderWriter/ELF/AArch64/AArch64TargetHandler.h90
-rw-r--r--lib/ReaderWriter/ELF/AArch64/CMakeLists.txt14
-rw-r--r--lib/ReaderWriter/ELF/AArch64/TODO.rst15
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMDynamicLibraryWriter.h49
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMELFFile.h154
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMELFWriters.h120
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMExecutableWriter.h68
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMLinkingContext.cpp64
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMLinkingContext.h80
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.cpp680
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMRelocationHandler.h35
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp985
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMRelocationPass.h31
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMSymbolTable.h59
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMTargetHandler.cpp32
-rw-r--r--lib/ReaderWriter/ELF/ARM/ARMTargetHandler.h174
-rw-r--r--lib/ReaderWriter/ELF/ARM/CMakeLists.txt12
-rw-r--r--lib/ReaderWriter/ELF/ARM/TODO.rst21
-rw-r--r--lib/ReaderWriter/ELF/Atoms.cpp297
-rw-r--r--lib/ReaderWriter/ELF/Atoms.h493
-rw-r--r--lib/ReaderWriter/ELF/CMakeLists.txt29
-rw-r--r--lib/ReaderWriter/ELF/Chunk.h111
-rw-r--r--lib/ReaderWriter/ELF/DynamicFile.cpp146
-rw-r--r--lib/ReaderWriter/ELF/DynamicFile.h59
-rw-r--r--lib/ReaderWriter/ELF/DynamicLibraryWriter.h86
-rw-r--r--lib/ReaderWriter/ELF/ELFFile.cpp829
-rw-r--r--lib/ReaderWriter/ELF/ELFFile.h395
-rw-r--r--lib/ReaderWriter/ELF/ELFLinkingContext.cpp263
-rw-r--r--lib/ReaderWriter/ELF/ELFReader.h47
-rw-r--r--lib/ReaderWriter/ELF/ExecutableWriter.h157
-rw-r--r--lib/ReaderWriter/ELF/FileCommon.cpp66
-rw-r--r--lib/ReaderWriter/ELF/FileCommon.h45
-rw-r--r--lib/ReaderWriter/ELF/HeaderChunks.cpp205
-rw-r--r--lib/ReaderWriter/ELF/HeaderChunks.h154
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/CMakeLists.txt11
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonDynamicLibraryWriter.h67
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonELFFile.h149
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonEncodings.h638
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonExecutableWriter.h73
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.cpp47
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonLinkingContext.h61
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.cpp330
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonRelocationHandler.h33
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.cpp382
-rw-r--r--lib/ReaderWriter/ELF/Hexagon/HexagonTargetHandler.h134
-rw-r--r--lib/ReaderWriter/ELF/Mips/CMakeLists.txt18
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.cpp675
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsAbiInfoHandler.h83
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.cpp76
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsCtorsOrderPass.h25
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsDynamicTable.h124
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsELFFile.cpp348
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsELFFile.h126
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsELFWriters.cpp292
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsELFWriters.h102
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsLinkingContext.cpp164
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsLinkingContext.h56
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.cpp687
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsRelocationHandler.h31
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsRelocationPass.cpp1415
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsRelocationPass.h25
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsSectionChunks.cpp264
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsSectionChunks.h150
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsTargetHandler.cpp166
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsTargetHandler.h73
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsTargetLayout.cpp111
-rw-r--r--lib/ReaderWriter/ELF/Mips/MipsTargetLayout.h71
-rw-r--r--lib/ReaderWriter/ELF/OrderPass.h31
-rw-r--r--lib/ReaderWriter/ELF/OutputELFWriter.cpp514
-rw-r--r--lib/ReaderWriter/ELF/OutputELFWriter.h153
-rw-r--r--lib/ReaderWriter/ELF/Reader.cpp43
-rw-r--r--lib/ReaderWriter/ELF/SectionChunks.cpp996
-rw-r--r--lib/ReaderWriter/ELF/SectionChunks.h616
-rw-r--r--lib/ReaderWriter/ELF/SegmentChunks.cpp519
-rw-r--r--lib/ReaderWriter/ELF/SegmentChunks.h246
-rw-r--r--lib/ReaderWriter/ELF/TODO.txt18
-rw-r--r--lib/ReaderWriter/ELF/TargetHandler.h35
-rw-r--r--lib/ReaderWriter/ELF/TargetLayout.cpp747
-rw-r--r--lib/ReaderWriter/ELF/TargetLayout.h327
-rw-r--r--lib/ReaderWriter/ELF/Writer.cpp23
-rw-r--r--lib/ReaderWriter/ELF/Writer.h35
-rw-r--r--lib/ReaderWriter/ELF/X86/CMakeLists.txt11
-rw-r--r--lib/ReaderWriter/ELF/X86/X86DynamicLibraryWriter.h44
-rw-r--r--lib/ReaderWriter/ELF/X86/X86ExecutableWriter.h39
-rw-r--r--lib/ReaderWriter/ELF/X86/X86LinkingContext.cpp39
-rw-r--r--lib/ReaderWriter/ELF/X86/X86LinkingContext.h44
-rw-r--r--lib/ReaderWriter/ELF/X86/X86RelocationHandler.cpp54
-rw-r--r--lib/ReaderWriter/ELF/X86/X86RelocationHandler.h28
-rw-r--r--lib/ReaderWriter/ELF/X86/X86TargetHandler.cpp36
-rw-r--r--lib/ReaderWriter/ELF/X86/X86TargetHandler.h48
-rw-r--r--lib/ReaderWriter/ELF/X86_64/CMakeLists.txt17
-rw-r--r--lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/CMakeLists.txt11
-rw-r--r--lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.cpp35
-rw-r--r--lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleLinkingContext.h31
-rw-r--r--lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.cpp22
-rw-r--r--lib/ReaderWriter/ELF/X86_64/ExampleSubTarget/ExampleTargetHandler.h31
-rw-r--r--lib/ReaderWriter/ELF/X86_64/TODO.rst46
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64DynamicLibraryWriter.h45
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64ExecutableWriter.h57
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.cpp50
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64LinkingContext.h103
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.cpp147
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64RelocationHandler.h37
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.cpp513
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64RelocationPass.h32
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.cpp37
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64SectionChunks.h36
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.cpp34
-rw-r--r--lib/ReaderWriter/ELF/X86_64/X86_64TargetHandler.h104
-rw-r--r--lib/ReaderWriter/FileArchive.cpp173
-rw-r--r--lib/ReaderWriter/LinkerScript.cpp2895
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler.h29
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler_arm.cpp131
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler_arm64.cpp122
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler_x86.cpp74
-rw-r--r--lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp178
-rw-r--r--lib/ReaderWriter/MachO/Atoms.h32
-rw-r--r--lib/ReaderWriter/MachO/CMakeLists.txt2
-rw-r--r--lib/ReaderWriter/MachO/CompactUnwindPass.cpp33
-rw-r--r--lib/ReaderWriter/MachO/ExecutableAtoms.h108
-rw-r--r--lib/ReaderWriter/MachO/File.h93
-rw-r--r--lib/ReaderWriter/MachO/FlatNamespaceFile.h28
-rw-r--r--lib/ReaderWriter/MachO/GOTPass.cpp12
-rw-r--r--lib/ReaderWriter/MachO/LayoutPass.cpp47
-rw-r--r--lib/ReaderWriter/MachO/LayoutPass.h39
-rw-r--r--lib/ReaderWriter/MachO/MachOLinkingContext.cpp216
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFile.h32
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp44
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h46
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp461
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp268
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp608
-rw-r--r--lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp81
-rw-r--r--lib/ReaderWriter/MachO/MachOPasses.h1
-rw-r--r--lib/ReaderWriter/MachO/ObjCPass.cpp128
-rw-r--r--lib/ReaderWriter/MachO/SectCreateFile.h19
-rw-r--r--lib/ReaderWriter/MachO/ShimPass.cpp13
-rw-r--r--lib/ReaderWriter/MachO/StubsPass.cpp40
-rw-r--r--lib/ReaderWriter/MachO/TLVPass.cpp14
-rw-r--r--lib/ReaderWriter/MachO/WriterMachO.cpp9
-rw-r--r--lib/ReaderWriter/YAML/ReaderWriterYAML.cpp302
-rw-r--r--test/CMakeLists.txt4
-rw-r--r--test/COFF/Inputs/armnt-executable.obj.yaml2
-rw-r--r--test/COFF/Inputs/export.yaml4
-rw-r--r--test/COFF/Inputs/export2.yaml2
-rw-r--r--test/COFF/Inputs/hello32.yaml2
-rw-r--r--test/COFF/Inputs/import.yaml2
-rw-r--r--test/COFF/Inputs/include1a.yaml4
-rw-r--r--test/COFF/Inputs/include1b.yaml4
-rw-r--r--test/COFF/Inputs/include1c.yaml2
-rw-r--r--test/COFF/Inputs/machine-x64.yaml2
-rw-r--r--test/COFF/Inputs/machine-x86.yaml2
-rw-r--r--test/COFF/Inputs/manifestinput.test13
-rw-r--r--test/COFF/Inputs/ret42.yaml2
-rw-r--r--test/COFF/alternatename.test4
-rw-r--r--test/COFF/ar-comdat.test2
-rw-r--r--test/COFF/armnt-blx23t.test2
-rw-r--r--test/COFF/armnt-branch24t.test2
-rw-r--r--test/COFF/armnt-imports.test2
-rw-r--r--test/COFF/armnt-mov32t-exec.test2
-rw-r--r--test/COFF/armnt-movt32t.test2
-rw-r--r--test/COFF/base.test2
-rw-r--r--test/COFF/baserel.test2
-rw-r--r--test/COFF/common.test2
-rw-r--r--test/COFF/conflict.test2
-rw-r--r--test/COFF/debug.test2
-rw-r--r--test/COFF/dllorder.test65
-rw-r--r--test/COFF/entry-inference.test2
-rw-r--r--test/COFF/entry-inference2.test4
-rw-r--r--test/COFF/entry-inference32.test2
-rw-r--r--test/COFF/entry-mangled.test2
-rw-r--r--test/COFF/export32.test4
-rw-r--r--test/COFF/force.test2
-rw-r--r--test/COFF/icf-circular.test2
-rw-r--r--test/COFF/icf-circular2.test2
-rw-r--r--test/COFF/icf-different-align.test2
-rw-r--r--test/COFF/icf-local.test2
-rw-r--r--test/COFF/icf-simple.test2
-rw-r--r--test/COFF/imports-mangle.test2
-rw-r--r--test/COFF/include.test4
-rw-r--r--test/COFF/internal.test2
-rw-r--r--test/COFF/invalid-obj.test2
-rw-r--r--test/COFF/loadcfg.ll2
-rw-r--r--test/COFF/loadcfg.test22
-rw-r--r--test/COFF/loadcfg32.test20
-rw-r--r--test/COFF/locally-imported.test2
-rw-r--r--test/COFF/locally-imported32.test2
-rw-r--r--test/COFF/long-section-name.test2
-rw-r--r--test/COFF/manifestinput.test10
-rw-r--r--test/COFF/merge.test2
-rw-r--r--test/COFF/opt.test2
-rw-r--r--test/COFF/out.test6
-rw-r--r--test/COFF/reloc-arm.test2
-rw-r--r--test/COFF/reloc-x64.test2
-rw-r--r--test/COFF/reloc-x86.test2
-rw-r--r--test/COFF/safeseh.test2
-rw-r--r--test/COFF/section.test62
-rw-r--r--test/COFF/seh.test2
-rw-r--r--test/COFF/sort-debug.test2
-rw-r--r--test/COFF/subsystem-inference.test2
-rw-r--r--test/COFF/symtab.test2
-rw-r--r--test/COFF/tls.test2
-rw-r--r--test/COFF/tls32.test4
-rw-r--r--test/COFF/unwind.test2
-rw-r--r--test/COFF/weak-external.test2
-rw-r--r--test/COFF/weak-external2.test2
-rw-r--r--test/COFF/weak-external3.test2
-rw-r--r--test/Driver/def-lib-search.test8
-rw-r--r--test/Driver/flavor-option.test8
-rw-r--r--test/Driver/lib-search.test24
-rw-r--r--test/Driver/so-whole-archive.test63
-rw-r--r--test/Driver/trivial-driver.test5
-rw-r--r--test/Driver/undef-basic.objtxt22
-rw-r--r--test/ELF/Inputs/aarch64-copy2.s5
-rw-r--r--test/ELF/Inputs/aarch64-tls-gdie.s4
-rw-r--r--test/ELF/Inputs/abs-hidden.s3
-rw-r--r--test/ELF/Inputs/allow-shlib-undefined.s2
-rw-r--r--test/ELF/Inputs/archive.s4
-rw-r--r--test/ELF/Inputs/arm-plt-reloc.s14
-rw-r--r--test/ELF/Inputs/arm-thumb-blx-targets.s36
-rw-r--r--test/ELF/Inputs/arm-thumb-narrow-branch.s18
-rw-r--r--test/ELF/Inputs/conflict.s7
-rw-r--r--test/ELF/Inputs/copy-in-shared.s4
-rw-r--r--test/ELF/Inputs/copy-rel-corrupted.s4
-rw-r--r--test/ELF/Inputs/copy-rel-pie.s9
-rw-r--r--test/ELF/Inputs/ctors_dtors_priority1.s5
-rw-r--r--test/ELF/Inputs/ctors_dtors_priority2.s5
-rw-r--r--test/ELF/Inputs/ctors_dtors_priority3.s5
-rw-r--r--test/ELF/Inputs/duplicated-plt-entry.s3
-rw-r--r--test/ELF/Inputs/dynamic-reloc-weak.s11
-rw-r--r--test/ELF/Inputs/ehframe-relocation.s2
-rw-r--r--test/ELF/Inputs/empty-ver.ver2
-rw-r--r--test/ELF/Inputs/far-arm-abs.s13
-rw-r--r--test/ELF/Inputs/far-arm-thumb-abs.s24
-rw-r--r--test/ELF/Inputs/gc-sections-weak.s8
-rw-r--r--test/ELF/Inputs/gnu-ifunc-gotpcrel.s4
-rw-r--r--test/ELF/Inputs/gotpc-relax-und-dso.s4
-rw-r--r--test/ELF/Inputs/icf2.s5
-rw-r--r--test/ELF/Inputs/invalid-cie-version2.elfbin0 -> 1128 bytes
-rw-r--r--test/ELF/Inputs/libsearch-dyn.s2
-rw-r--r--test/ELF/Inputs/libsearch-st.s2
-rw-r--r--test/ELF/Inputs/mips-align-err.s2
-rw-r--r--test/ELF/Inputs/mips-dynamic.s24
-rw-r--r--test/ELF/Inputs/mips-gp-disp.sobin131832 -> 131828 bytes
-rw-r--r--test/ELF/Inputs/mips-nonalloc.s2
-rw-r--r--test/ELF/Inputs/mips-pic.s19
-rw-r--r--test/ELF/Inputs/mips-tls.s5
-rw-r--r--test/ELF/Inputs/plt-aarch64.s5
-rw-r--r--test/ELF/Inputs/ppc64-addr16-error.s3
-rw-r--r--test/ELF/Inputs/protected-shared.s10
-rw-r--r--test/ELF/Inputs/relocatable-ehframe.s14
-rw-r--r--test/ELF/Inputs/relocatable.s22
-rw-r--r--test/ELF/Inputs/relocatable2.s22
-rw-r--r--test/ELF/Inputs/relocation-copy-alias.s25
-rw-r--r--test/ELF/Inputs/relocation-copy-arm.s22
-rw-r--r--test/ELF/Inputs/resolution-shared.s2
-rw-r--r--test/ELF/Inputs/shared.s4
-rw-r--r--test/ELF/Inputs/start-lib-comdat.s5
-rw-r--r--test/ELF/Inputs/start-lib1.s3
-rw-r--r--test/ELF/Inputs/start-lib2.s2
-rw-r--r--test/ELF/Inputs/symbol-override.s16
-rw-r--r--test/ELF/Inputs/tls-got-entry.s13
-rw-r--r--test/ELF/Inputs/tls-in-archive.s3
-rw-r--r--test/ELF/Inputs/trace-ar1.s2
-rw-r--r--test/ELF/Inputs/trace-ar2.s2
-rw-r--r--test/ELF/Inputs/trace-symbols-foo-strong.s14
-rw-r--r--test/ELF/Inputs/trace-symbols-foo-weak.s12
-rw-r--r--test/ELF/Inputs/undef-with-plt-addr.s7
-rw-r--r--test/ELF/Inputs/undef.s3
-rw-r--r--test/ELF/Inputs/unresolved-symbols.s3
-rw-r--r--test/ELF/Inputs/verdef-defaultver.s22
-rw-r--r--test/ELF/Inputs/verdef.s6
-rwxr-xr-xtest/ELF/Inputs/verneed.so.sh58
-rw-r--r--test/ELF/Inputs/version-script-err.script4
-rw-r--r--test/ELF/Inputs/version-use.script6
-rw-r--r--test/ELF/Inputs/visibility.s1
-rw-r--r--test/ELF/Inputs/warn-common.s2
-rw-r--r--test/ELF/Inputs/warn-common2.s8
-rw-r--r--test/ELF/Inputs/whole-archive.s2
-rw-r--r--test/ELF/Inputs/x86-64-relax-offset.s7
-rw-r--r--test/ELF/Inputs/x86-64-reloc-error.s7
-rw-r--r--test/ELF/Inputs/x86-64-tls-gd-got.s6
-rw-r--r--test/ELF/aarch64-abs64-dyn.s27
-rw-r--r--test/ELF/aarch64-copy.s38
-rw-r--r--test/ELF/aarch64-copy2.s27
-rw-r--r--test/ELF/aarch64-fpic-abs16.s2
-rw-r--r--test/ELF/aarch64-fpic-add_abs_lo12_nc.s2
-rw-r--r--test/ELF/aarch64-fpic-adr_prel_lo21.s2
-rw-r--r--test/ELF/aarch64-fpic-adr_prel_pg_hi21.s2
-rw-r--r--test/ELF/aarch64-fpic-got.s18
-rw-r--r--test/ELF/aarch64-fpic-ldst32_abs_lo12_nc.s2
-rw-r--r--test/ELF/aarch64-fpic-ldst64_abs_lo12_nc.s2
-rw-r--r--test/ELF/aarch64-fpic-ldst8_abs_lo12_nc.s2
-rw-r--r--test/ELF/aarch64-fpic-prel16.s2
-rw-r--r--test/ELF/aarch64-fpic-prel32.s2
-rw-r--r--test/ELF/aarch64-fpic-prel64.s2
-rw-r--r--test/ELF/aarch64-gnu-ifunc-nosym.s6
-rw-r--r--test/ELF/aarch64-gnu-ifunc.s16
-rw-r--r--test/ELF/aarch64-got-relocations.s21
-rw-r--r--test/ELF/aarch64-got.s18
-rw-r--r--test/ELF/aarch64-relative.s26
-rw-r--r--test/ELF/aarch64-relocs.s30
-rw-r--r--test/ELF/aarch64-tls-gdie.s34
-rw-r--r--test/ELF/aarch64-tls-gdle.s26
-rw-r--r--test/ELF/aarch64-tls-ie.s3
-rw-r--r--test/ELF/aarch64-tls-iele.s33
-rw-r--r--test/ELF/aarch64-tls-le.s31
-rw-r--r--test/ELF/aarch64-tls-pie.s28
-rw-r--r--test/ELF/aarch64-tls-static.s37
-rw-r--r--test/ELF/aarch64-tlsdesc.s24
-rw-r--r--test/ELF/abs-hidden.s46
-rw-r--r--test/ELF/allow-shlib-undefined.s2
-rw-r--r--test/ELF/amdgpu-entry.s2
-rw-r--r--test/ELF/amdgpu-globals.s20
-rw-r--r--test/ELF/amdgpu-kernels.s10
-rw-r--r--test/ELF/amdgpu-relocs.s33
-rw-r--r--test/ELF/archive.s4
-rw-r--r--test/ELF/arm-abs32-dyn.s32
-rw-r--r--test/ELF/arm-attributes-remove.s45
-rw-r--r--test/ELF/arm-blx.s113
-rw-r--r--test/ELF/arm-branch-error.s19
-rw-r--r--test/ELF/arm-branch.s59
-rw-r--r--test/ELF/arm-copy.s81
-rw-r--r--test/ELF/arm-data-prel.s63
-rw-r--r--test/ELF/arm-data-relocs.s20
-rw-r--r--test/ELF/arm-fpic-got.s63
-rw-r--r--test/ELF/arm-gnu-ifunc-nosym.s27
-rw-r--r--test/ELF/arm-gnu-ifunc.s131
-rw-r--r--test/ELF/arm-got-relative.s53
-rw-r--r--test/ELF/arm-gotoff.s74
-rw-r--r--test/ELF/arm-mov-relocs.s94
-rw-r--r--test/ELF/arm-plt-reloc.s90
-rw-r--r--test/ELF/arm-thumb-blx.s85
-rw-r--r--test/ELF/arm-thumb-branch-error.s19
-rw-r--r--test/ELF/arm-thumb-branch.s59
-rw-r--r--test/ELF/arm-thumb-interwork-thunk.s375
-rw-r--r--test/ELF/arm-thumb-narrow-branch-check.s72
-rw-r--r--test/ELF/arm-thumb-plt-reloc.s101
-rw-r--r--test/ELF/as-needed-no-reloc.s23
-rw-r--r--test/ELF/as-needed.s5
-rw-r--r--test/ELF/avoid-empty-program-headers.s78
-rw-r--r--test/ELF/basic-aarch64.s2
-rw-r--r--test/ELF/basic-mips.s99
-rw-r--r--test/ELF/basic-ppc.s13
-rw-r--r--test/ELF/basic.s22
-rw-r--r--test/ELF/basic32.s4
-rw-r--r--test/ELF/basic64be.s76
-rw-r--r--test/ELF/bsymbolic-undef.s26
-rw-r--r--test/ELF/bsymbolic.s34
-rw-r--r--test/ELF/build-id.s38
-rw-r--r--test/ELF/combrelocs.s92
-rw-r--r--test/ELF/comdat.s11
-rw-r--r--test/ELF/common.s3
-rw-r--r--test/ELF/compressed-debug-input.s61
-rw-r--r--test/ELF/conflict.s26
-rw-r--r--test/ELF/copy-errors.s15
-rw-r--r--test/ELF/copy-in-shared.s10
-rw-r--r--test/ELF/copy-rel-corrupted.s10
-rw-r--r--test/ELF/copy-rel-pie-error.s12
-rw-r--r--test/ELF/copy-rel-pie.s44
-rw-r--r--test/ELF/ctors_dtors_priority.s41
-rw-r--r--test/ELF/default-output.s2
-rw-r--r--test/ELF/discard-merge-locals.s11
-rw-r--r--test/ELF/discard-merge-unnamed.s11
-rw-r--r--test/ELF/discard-none.s2
-rw-r--r--test/ELF/dont-export-hidden.s39
-rw-r--r--test/ELF/driver.test49
-rw-r--r--test/ELF/duplicate-internal.s2
-rw-r--r--test/ELF/duplicated-plt-entry.s17
-rw-r--r--test/ELF/dynamic-list.s110
-rw-r--r--test/ELF/dynamic-reloc-in-ro.s8
-rw-r--r--test/ELF/dynamic-reloc-weak.s14
-rw-r--r--test/ELF/dynamic-reloc.s2
-rw-r--r--test/ELF/dynamic.s44
-rw-r--r--test/ELF/dynsym-pie.s36
-rw-r--r--test/ELF/edata-etext.s117
-rw-r--r--test/ELF/eh-frame-dyn-rel.s10
-rw-r--r--test/ELF/eh-frame-gc.s20
-rw-r--r--test/ELF/eh-frame-hdr-abs-fde.s33
-rw-r--r--test/ELF/eh-frame-hdr-augmentation.s38
-rw-r--r--test/ELF/eh-frame-hdr-icf.s27
-rw-r--r--test/ELF/eh-frame-hdr-no-out.s6
-rw-r--r--test/ELF/eh-frame-hdr-no-out2.s19
-rw-r--r--test/ELF/eh-frame-hdr.s127
-rw-r--r--test/ELF/eh-frame-marker.s6
-rw-r--r--test/ELF/eh-frame-merge.s2
-rw-r--r--test/ELF/eh-frame-multilpe-cie.s12
-rw-r--r--test/ELF/eh-frame-type.test5
-rw-r--r--test/ELF/ehframe-relocation.s8
-rw-r--r--test/ELF/empty-ver.s25
-rw-r--r--test/ELF/emulation.s118
-rw-r--r--test/ELF/end.s8
-rw-r--r--test/ELF/entry.s4
-rw-r--r--test/ELF/fatal-warnings.s16
-rw-r--r--test/ELF/file-sym.s12
-rw-r--r--test/ELF/gc-merge-local-sym.s34
-rw-r--r--test/ELF/gc-sections-eh.s13
-rw-r--r--test/ELF/gc-sections-local-sym.s57
-rw-r--r--test/ELF/gc-sections-lsda.s21
-rw-r--r--test/ELF/gc-sections-merge-addend.s39
-rw-r--r--test/ELF/gc-sections-merge-implicit-addend.s39
-rw-r--r--test/ELF/gc-sections-merge.s61
-rw-r--r--test/ELF/gc-sections-protected.s18
-rw-r--r--test/ELF/gc-sections-shared.s34
-rw-r--r--test/ELF/gc-sections-weak.s24
-rw-r--r--test/ELF/global_offset_table_shared.s9
-rw-r--r--test/ELF/gnu-ifunc-gotpcrel.s14
-rw-r--r--test/ELF/gnu-ifunc-i386.s16
-rw-r--r--test/ELF/gnu-ifunc-nosym-i386.s6
-rw-r--r--test/ELF/gnu-ifunc-nosym.s6
-rw-r--r--test/ELF/gnu-ifunc-relative.s23
-rw-r--r--test/ELF/gnu-ifunc.s18
-rw-r--r--test/ELF/gnu-unique.s33
-rw-r--r--test/ELF/got-plt-header.s30
-rw-r--r--test/ELF/gotpc-relax-nopic.s81
-rw-r--r--test/ELF/gotpc-relax-und-dso.s72
-rw-r--r--test/ELF/gotpc-relax.s98
-rw-r--r--test/ELF/gotpcrelx.s30
-rw-r--r--test/ELF/i386-got-and-copy.s25
-rw-r--r--test/ELF/i386-gotpc.s20
-rw-r--r--test/ELF/i386-merge.s50
-rw-r--r--test/ELF/i386-relative.s14
-rw-r--r--test/ELF/i386-relax-reloc.s12
-rw-r--r--test/ELF/i386-tls-ie-shared.s110
-rw-r--r--test/ELF/icf1.s23
-rw-r--r--test/ELF/icf2.s17
-rw-r--r--test/ELF/icf3.s19
-rw-r--r--test/ELF/icf4.s19
-rw-r--r--test/ELF/icf5.s19
-rw-r--r--test/ELF/icf6.s23
-rw-r--r--test/ELF/icf7.s29
-rw-r--r--test/ELF/image-base.s60
-rw-r--r--test/ELF/incompatible.s1
-rw-r--r--test/ELF/init-fini.s2
-rw-r--r--test/ELF/init_fini_priority.s37
-rw-r--r--test/ELF/invalid-cie-length.s2
-rw-r--r--test/ELF/invalid-cie-length3.s2
-rw-r--r--test/ELF/invalid-cie-length4.s2
-rw-r--r--test/ELF/invalid-cie-length5.s2
-rw-r--r--test/ELF/invalid-cie-reference.s2
-rw-r--r--test/ELF/invalid-dynamic-list.test37
-rw-r--r--test/ELF/invalid-elf.test13
-rw-r--r--test/ELF/invalid-linkerscript.test54
-rw-r--r--test/ELF/invalid-relocations.test5
-rw-r--r--test/ELF/libsearch.s12
-rw-r--r--test/ELF/linkerscript-align.s41
-rw-r--r--test/ELF/linkerscript-diagnostic.s66
-rw-r--r--test/ELF/linkerscript-locationcounter.s340
-rw-r--r--test/ELF/linkerscript-orphans.s31
-rw-r--r--test/ELF/linkerscript-phdr-check.s15
-rw-r--r--test/ELF/linkerscript-repsection-va.s24
-rw-r--r--test/ELF/linkerscript-sections-keep.s80
-rw-r--r--test/ELF/linkerscript-sections-padding.s44
-rw-r--r--test/ELF/linkerscript-sections.s10
-rw-r--r--test/ELF/linkerscript-symbol-conflict.s11
-rw-r--r--test/ELF/linkerscript-symbols.s11
-rw-r--r--test/ELF/linkerscript-va.s24
-rw-r--r--test/ELF/linkerscript.s38
-rw-r--r--test/ELF/linkerscript2.s8
-rw-r--r--test/ELF/lit.local.cfg2
-rw-r--r--test/ELF/llvm33-rela-outside-group.s11
-rw-r--r--test/ELF/local-dynamic.s11
-rw-r--r--test/ELF/local-got-pie.s36
-rw-r--r--test/ELF/local-undefined-symbol.s13
-rw-r--r--test/ELF/lto/Inputs/archive-2.ll6
-rw-r--r--test/ELF/lto/Inputs/archive-3.ll5
-rw-r--r--test/ELF/lto/Inputs/archive.ll6
-rw-r--r--test/ELF/lto/Inputs/available-externally.ll6
-rw-r--r--test/ELF/lto/Inputs/comdat.s5
-rw-r--r--test/ELF/lto/Inputs/common.s1
-rw-r--r--test/ELF/lto/Inputs/drop-debug-info.bcbin0 -> 1152 bytes
-rw-r--r--test/ELF/lto/Inputs/drop-linkage.ll12
-rw-r--r--test/ELF/lto/Inputs/dynsym.s3
-rw-r--r--test/ELF/lto/Inputs/internalize-exportdyn.ll6
-rw-r--r--test/ELF/lto/Inputs/internalize-undef.ll6
-rw-r--r--test/ELF/lto/Inputs/irmover-error.ll6
-rw-r--r--test/ELF/lto/Inputs/linkonce-odr.ll6
-rw-r--r--test/ELF/lto/Inputs/linkonce.ll6
-rw-r--r--test/ELF/lto/Inputs/resolution.s4
-rw-r--r--test/ELF/lto/Inputs/save-temps.ll6
-rw-r--r--test/ELF/lto/Inputs/shared.s7
-rw-r--r--test/ELF/lto/Inputs/start-lib1.ll8
-rw-r--r--test/ELF/lto/Inputs/start-lib2.ll6
-rw-r--r--test/ELF/lto/Inputs/tls-mixed.s4
-rw-r--r--test/ELF/lto/Inputs/type-merge.ll8
-rw-r--r--test/ELF/lto/Inputs/type-merge2.ll8
-rw-r--r--test/ELF/lto/Inputs/undef-mixed.s3
-rw-r--r--test/ELF/lto/Inputs/unnamed-addr-lib.s6
-rw-r--r--test/ELF/lto/Inputs/visibility.s8
-rw-r--r--test/ELF/lto/archive-2.ll28
-rw-r--r--test/ELF/lto/archive-3.ll19
-rw-r--r--test/ELF/lto/archive.ll37
-rw-r--r--test/ELF/lto/asmundef.ll25
-rw-r--r--test/ELF/lto/available-externally.ll22
-rw-r--r--test/ELF/lto/combined-lto-object-name.ll14
-rw-r--r--test/ELF/lto/comdat.ll21
-rw-r--r--test/ELF/lto/comdat2.ll40
-rw-r--r--test/ELF/lto/common.ll31
-rw-r--r--test/ELF/lto/common2.ll24
-rw-r--r--test/ELF/lto/ctors.ll18
-rw-r--r--test/ELF/lto/discard-value-names.ll23
-rw-r--r--test/ELF/lto/drop-debug-info.ll9
-rw-r--r--test/ELF/lto/drop-linkage.ll14
-rw-r--r--test/ELF/lto/duplicated.ll10
-rw-r--r--test/ELF/lto/dynamic-list.ll25
-rw-r--r--test/ELF/lto/dynsym.ll25
-rw-r--r--test/ELF/lto/inline-asm.ll11
-rw-r--r--test/ELF/lto/internalize-basic.ll21
-rw-r--r--test/ELF/lto/internalize-exportdyn.ll47
-rw-r--r--test/ELF/lto/internalize-llvmused.ll20
-rw-r--r--test/ELF/lto/internalize-undef.ll16
-rw-r--r--test/ELF/lto/internalize-version-script.ll22
-rw-r--r--test/ELF/lto/invalid-bitcode.ll12
-rw-r--r--test/ELF/lto/irmover-error.ll12
-rw-r--r--test/ELF/lto/linkage.ll20
-rw-r--r--test/ELF/lto/linkonce-odr.ll17
-rw-r--r--test/ELF/lto/linkonce.ll17
-rw-r--r--test/ELF/lto/lto-start.ll23
-rw-r--r--test/ELF/lto/ltopasses-basic.ll18
-rw-r--r--test/ELF/lto/ltopasses-custom.ll30
-rw-r--r--test/ELF/lto/metadata.ll13
-rw-r--r--test/ELF/lto/mix-platforms.ll10
-rw-r--r--test/ELF/lto/module-asm.ll19
-rw-r--r--test/ELF/lto/opt-level.ll29
-rw-r--r--test/ELF/lto/parallel-internalize.ll57
-rw-r--r--test/ELF/lto/parallel.ll24
-rw-r--r--test/ELF/lto/pic.ll20
-rw-r--r--test/ELF/lto/relax-relocs.ll15
-rw-r--r--test/ELF/lto/resolution.ll27
-rw-r--r--test/ELF/lto/save-temps.ll20
-rw-r--r--test/ELF/lto/shlib-undefined.ll27
-rw-r--r--test/ELF/lto/start-lib.ll27
-rw-r--r--test/ELF/lto/tls-mixed.ll10
-rw-r--r--test/ELF/lto/tls-preserve.ll25
-rw-r--r--test/ELF/lto/type-merge.ll26
-rw-r--r--test/ELF/lto/type-merge2.ll27
-rw-r--r--test/ELF/lto/undef-mixed.ll22
-rw-r--r--test/ELF/lto/undef-weak.ll29
-rw-r--r--test/ELF/lto/undef.ll20
-rw-r--r--test/ELF/lto/undefined-puts.ll28
-rw-r--r--test/ELF/lto/unnamed-addr-comdat.ll11
-rw-r--r--test/ELF/lto/unnamed-addr-lib.ll21
-rw-r--r--test/ELF/lto/unnamed-addr.ll14
-rw-r--r--test/ELF/lto/verify-invalid.ll17
-rw-r--r--test/ELF/lto/version-script.ll50
-rw-r--r--test/ELF/lto/visibility.ll35
-rw-r--r--test/ELF/lto/weak.ll16
-rw-r--r--test/ELF/merge-shared-str.s28
-rw-r--r--test/ELF/merge-shared.s2
-rw-r--r--test/ELF/merge-string-align.s25
-rw-r--r--test/ELF/merge-string-error.s4
-rw-r--r--test/ELF/merge-string-no-null.s2
-rw-r--r--test/ELF/merge-string.s26
-rw-r--r--test/ELF/merge.s6
-rw-r--r--test/ELF/mips-26.s95
-rw-r--r--test/ELF/mips-32.s78
-rw-r--r--test/ELF/mips-64-disp.s89
-rw-r--r--test/ELF/mips-64-got.s87
-rw-r--r--test/ELF/mips-64-gprel-so.s23
-rw-r--r--test/ELF/mips-64-rels.s46
-rw-r--r--test/ELF/mips-64.s63
-rw-r--r--test/ELF/mips-align-err.s12
-rw-r--r--test/ELF/mips-dynamic.s19
-rw-r--r--test/ELF/mips-gnu-hash.s2
-rw-r--r--test/ELF/mips-got-and-copy.s57
-rw-r--r--test/ELF/mips-got-extsym.s59
-rw-r--r--test/ELF/mips-got-redundant.s58
-rw-r--r--test/ELF/mips-got-relocs.s5
-rw-r--r--test/ELF/mips-got-weak.s172
-rw-r--r--test/ELF/mips-got16.s120
-rw-r--r--test/ELF/mips-gp-disp.s9
-rw-r--r--test/ELF/mips-gp-local.s20
-rw-r--r--test/ELF/mips-gprel32-relocs-gp0.test31
-rw-r--r--test/ELF/mips-gprel32-relocs.s2
-rw-r--r--test/ELF/mips-hilo-gp-disp.s21
-rw-r--r--test/ELF/mips-hilo-hi-only.s2
-rw-r--r--test/ELF/mips-hilo.s10
-rw-r--r--test/ELF/mips-jalr.test7
-rw-r--r--test/ELF/mips-lo16-not-relative.s23
-rw-r--r--test/ELF/mips-nonalloc.s21
-rw-r--r--test/ELF/mips-npic-call-pic.s144
-rw-r--r--test/ELF/mips-options-r.test19
-rw-r--r--test/ELF/mips-options.s28
-rw-r--r--test/ELF/mips-pc-relocs.s15
-rw-r--r--test/ELF/mips-plt-copy.s85
-rw-r--r--test/ELF/mips-relocs.s42
-rw-r--r--test/ELF/mips-sto-plt.s66
-rw-r--r--test/ELF/mips-tls-64.s86
-rw-r--r--test/ELF/mips-tls-hilo.s52
-rw-r--r--test/ELF/mips-tls.s77
-rw-r--r--test/ELF/no-augmentation.s19
-rw-r--r--test/ELF/no-inhibit-exec.s4
-rw-r--r--test/ELF/no-plt-shared.s17
-rw-r--r--test/ELF/no-undefined.s2
-rw-r--r--test/ELF/noplt-pie.s21
-rw-r--r--test/ELF/note.s18
-rw-r--r--test/ELF/phdr-align.s82
-rw-r--r--test/ELF/pie-weak.s16
-rw-r--r--test/ELF/pie.s102
-rw-r--r--test/ELF/plt-aarch64.s2
-rw-r--r--test/ELF/plt-i686.s20
-rw-r--r--test/ELF/plt.s2
-rw-r--r--test/ELF/ppc64-addr16-error.s5
-rw-r--r--test/ELF/ppc64-relocs.s4
-rw-r--r--test/ELF/ppc64-toc-restore.s4
-rw-r--r--test/ELF/pre_init_fini_array.s24
-rw-r--r--test/ELF/progname.s21
-rw-r--r--test/ELF/protected-shared.s52
-rw-r--r--test/ELF/rel-offset.s15
-rw-r--r--test/ELF/relative-dynamic-reloc-pie.s26
-rw-r--r--test/ELF/relative-dynamic-reloc-ppc64.s7
-rw-r--r--test/ELF/relative-dynamic-reloc.s7
-rw-r--r--test/ELF/relocatable-bss.s40
-rw-r--r--test/ELF/relocatable-ehframe.s51
-rw-r--r--test/ELF/relocatable-reloc.s14
-rw-r--r--test/ELF/relocatable-symbols.s183
-rw-r--r--test/ELF/relocatable.s121
-rw-r--r--test/ELF/relocation-copy-alias.s67
-rw-r--r--test/ELF/relocation-copy-flags.s73
-rw-r--r--test/ELF/relocation-copy-i686.s2
-rw-r--r--test/ELF/relocation-copy.s2
-rw-r--r--test/ELF/relocation-i686.s24
-rw-r--r--test/ELF/relocation-in-merge.s2
-rw-r--r--test/ELF/relocation-non-alloc.s60
-rw-r--r--test/ELF/relocation-past-merge-end.s3
-rw-r--r--test/ELF/relocation-relative-absolute.s12
-rw-r--r--test/ELF/relocation-relative-synthetic.s11
-rw-r--r--test/ELF/relocation-relative-weak.s14
-rw-r--r--test/ELF/relocation-shared.s35
-rw-r--r--test/ELF/relocation-size-shared.s76
-rw-r--r--test/ELF/relocation-size.s138
-rw-r--r--test/ELF/relocation.s21
-rw-r--r--test/ELF/relro-tls.s23
-rw-r--r--test/ELF/relro.s2
-rw-r--r--test/ELF/reproduce-error.s15
-rw-r--r--test/ELF/reproduce-linkerscript.s17
-rw-r--r--test/ELF/reproduce-thin-archive.s15
-rw-r--r--test/ELF/reproduce-windows.s12
-rw-r--r--test/ELF/reproduce.s67
-rw-r--r--test/ELF/resolution-shared.s15
-rw-r--r--test/ELF/resolution.s2
-rw-r--r--test/ELF/section-align-0.test3
-rw-r--r--test/ELF/section-name.s6
-rw-r--r--test/ELF/section-symbol.s13
-rw-r--r--test/ELF/shared-be.s7
-rw-r--r--test/ELF/shared.s19
-rw-r--r--test/ELF/soname.s2
-rw-r--r--test/ELF/splitstacks.s11
-rw-r--r--test/ELF/start-lib-comdat.s23
-rw-r--r--test/ELF/start-lib.s25
-rw-r--r--test/ELF/startstop-gccollect.s32
-rw-r--r--test/ELF/startstop-shared.s20
-rw-r--r--test/ELF/startstop.s16
-rw-r--r--test/ELF/string-gc.s73
-rw-r--r--test/ELF/string-table.s5
-rw-r--r--test/ELF/strip-all.s6
-rw-r--r--test/ELF/strip-debug.s25
-rw-r--r--test/ELF/symbol-override.s46
-rw-r--r--test/ELF/symbols.s14
-rw-r--r--test/ELF/sysroot.s4
-rw-r--r--test/ELF/tail-merge-string-align.s35
-rw-r--r--test/ELF/tls-archive.s10
-rw-r--r--test/ELF/tls-dynamic-i686.s24
-rw-r--r--test/ELF/tls-dynamic.s10
-rw-r--r--test/ELF/tls-got-entry.s25
-rw-r--r--test/ELF/tls-got.s2
-rw-r--r--test/ELF/tls-i686.s54
-rw-r--r--test/ELF/tls-in-archive.s11
-rw-r--r--test/ELF/tls-initial-exec-local.s36
-rw-r--r--test/ELF/tls-offset.s56
-rw-r--r--test/ELF/tls-opt-gdie.s27
-rw-r--r--test/ELF/tls-opt-iele-i686-nopic.s59
-rw-r--r--test/ELF/tls-opt-no-plt.s34
-rw-r--r--test/ELF/tls-opt.s74
-rw-r--r--test/ELF/tls-two-relocs.s30
-rw-r--r--test/ELF/trace-ar.s21
-rw-r--r--test/ELF/trace-symbols.s78
-rw-r--r--test/ELF/trace.s9
-rw-r--r--test/ELF/undef-shared.s14
-rw-r--r--test/ELF/undef-version-script.s40
-rw-r--r--test/ELF/undef-with-plt-addr-i686.s23
-rw-r--r--test/ELF/undef-with-plt-addr.s45
-rw-r--r--test/ELF/undef.s15
-rw-r--r--test/ELF/undefined-opt.s13
-rw-r--r--test/ELF/unresolved-symbols.s63
-rw-r--r--test/ELF/user_def_init_array_start.s10
-rw-r--r--test/ELF/valid-cie-length-dw64.s13
-rw-r--r--test/ELF/verdef-defaultver.s205
-rw-r--r--test/ELF/verdef-dependency.s44
-rw-r--r--test/ELF/verdef.s117
-rw-r--r--test/ELF/verneed-as-needed-weak.s14
-rw-r--r--test/ELF/verneed-local.s8
-rw-r--r--test/ELF/verneed.s173
-rw-r--r--test/ELF/version-script-err.s10
-rw-r--r--test/ELF/version-script-extern.s97
-rw-r--r--test/ELF/version-script-noundef.s22
-rw-r--r--test/ELF/version-script.s274
-rw-r--r--test/ELF/version-undef-sym.s42
-rw-r--r--test/ELF/version-use.s9
-rw-r--r--test/ELF/version-wildcard.test114
-rw-r--r--test/ELF/visibility.s31
-rw-r--r--test/ELF/warn-common.s25
-rw-r--r--test/ELF/weak-undef-hidden.s29
-rw-r--r--test/ELF/weak-undef-shared.s19
-rw-r--r--test/ELF/weak-undef.s21
-rw-r--r--test/ELF/whole-archive.s8
-rw-r--r--test/ELF/wildcards.s80
-rw-r--r--test/ELF/writable-merge.s4
-rw-r--r--test/ELF/x86-64-dyn-rel-error.s12
-rw-r--r--test/ELF/x86-64-dyn-rel-error2.s12
-rw-r--r--test/ELF/x86-64-rela.s11
-rw-r--r--test/ELF/x86-64-relax-offset.s13
-rw-r--r--test/ELF/x86-64-reloc-32-error.s8
-rw-r--r--test/ELF/x86-64-reloc-32-fpic.s7
-rw-r--r--test/ELF/x86-64-reloc-32S-error.s7
-rw-r--r--test/ELF/x86-64-reloc-error.s10
-rw-r--r--test/ELF/x86-64-reloc-pc32-fpic.s7
-rw-r--r--test/ELF/x86-64-reloc-range.s13
-rw-r--r--test/ELF/x86-64-tls-gd-got.s19
-rw-r--r--test/ELF/x86-64-tls-gd-local.s52
-rw-r--r--test/ELF/x86-64-tls-pie.s26
-rw-r--r--test/ELF/zdefs.s7
-rw-r--r--test/LinkerScript/expr-precedence.test34
-rw-r--r--test/LinkerScript/extern-bad-symbol.test22
-rw-r--r--test/LinkerScript/extern-empty.test19
-rw-r--r--test/LinkerScript/extern-valid.test29
-rw-r--r--test/LinkerScript/incomplete-ternary.test25
-rw-r--r--test/LinkerScript/libname-err-1.test11
-rw-r--r--test/LinkerScript/libname-err-2.test11
-rw-r--r--test/LinkerScript/linker-script-outputformat.test12
-rw-r--r--test/LinkerScript/linker-script.test46
-rw-r--r--test/LinkerScript/memory-empty.test17
-rw-r--r--test/LinkerScript/memory-missing-attrs.test32
-rw-r--r--test/LinkerScript/memory-missing-length.test29
-rw-r--r--test/LinkerScript/memory-missing-name.test31
-rw-r--r--test/LinkerScript/memory-missing-origin.test30
-rw-r--r--test/LinkerScript/memory-valid.test56
-rw-r--r--test/LinkerScript/missing-entry-symbol.test21
-rw-r--r--test/LinkerScript/missing-input-file-name.test25
-rw-r--r--test/LinkerScript/missing-input-sections.test27
-rw-r--r--test/LinkerScript/missing-operand.test24
-rw-r--r--test/LinkerScript/missing-output-section-name.test25
-rw-r--r--test/LinkerScript/missing-symbol.test24
-rw-r--r--test/LinkerScript/phdrs-sections.test29
-rw-r--r--test/LinkerScript/sections.test624
-rw-r--r--test/Unit/lit.site.cfg.in4
-rw-r--r--test/core/Inputs/archive-basic.objtxt21
-rw-r--r--test/core/Inputs/archive-chain.objtxt24
-rw-r--r--test/core/Inputs/archive-chain2.objtxt21
-rw-r--r--test/core/Inputs/archive-tentdef-search.objtxt11
-rw-r--r--test/core/Inputs/associates.objtxt8
-rw-r--r--test/core/Inputs/auto-hide-coalesce.objtxt20
-rw-r--r--test/core/Inputs/code-model-attributes.objtxt4
-rw-r--r--test/core/Inputs/code-model-attributes2.objtxt4
-rw-r--r--test/core/Inputs/code-model-attributes3.objtxt4
-rw-r--r--test/core/Inputs/code-model-attributes4.objtxt4
-rw-r--r--test/core/Inputs/code-model-attributes5.objtxt4
-rw-r--r--test/core/Inputs/constants-coalesce.objtxt9
-rw-r--r--test/core/Inputs/constants-coalesce2.objtxt10
-rw-r--r--test/core/Inputs/cstring-coalesce.objtxt6
-rw-r--r--test/core/Inputs/cstring-coalesce2.objtxt6
-rw-r--r--test/core/Inputs/custom-section-coalesce.objtxt15
-rw-r--r--test/core/Inputs/custom-section-coalesce2.objtxt13
-rw-r--r--test/core/Inputs/dead-strip-attributes.objtxt4
-rw-r--r--test/core/Inputs/dead-strip-attributes2.objtxt4
-rw-r--r--test/core/Inputs/dead-strip-basic.objtxt9
-rw-r--r--test/core/Inputs/dead-strip-basic2.objtxt8
-rw-r--r--test/core/Inputs/dead-strip-globals.objtxt9
-rw-r--r--test/core/Inputs/dead-strip-globals2.objtxt8
-rw-r--r--test/core/Inputs/error-duplicate-absolutes.objtxt5
-rw-r--r--test/core/Inputs/gnulinkonce-rearrange-resolve.objtxt26
-rw-r--r--test/core/Inputs/gnulinkonce-remaining-undef.objtxt34
-rw-r--r--test/core/Inputs/gnulinkonce-remaining-undef2.objtxt4
-rw-r--r--test/core/Inputs/gnulinkonce-resolve.objtxt25
-rw-r--r--test/core/Inputs/gnulinkonce-simple.objtxt4
-rw-r--r--test/core/Inputs/inline-coalesce.objtxt6
-rw-r--r--test/core/Inputs/inline-coalesce2.objtxt6
-rw-r--r--test/core/Inputs/multiple-def-error.objtxt5
-rw-r--r--test/core/Inputs/sectiongroup-deadstrip.objtxt3
-rw-r--r--test/core/Inputs/sectiongroup-gnulinkonce-error.objtxt26
-rw-r--r--test/core/Inputs/sectiongroup-rearrange-resolve.objtxt25
-rw-r--r--test/core/Inputs/sectiongroup-remaining-undef.objtxt34
-rw-r--r--test/core/Inputs/sectiongroup-remaining-undef2.objtxt4
-rw-r--r--test/core/Inputs/sectiongroup-resolve.objtxt26
-rw-r--r--test/core/Inputs/sectiongroup-simple.objtxt4
-rw-r--r--test/core/Inputs/shared-library-coalesce.objtxt28
-rw-r--r--test/core/Inputs/tent-merge.objtxt6
-rw-r--r--test/core/Inputs/undef-coalesce-error.objtxt8
-rw-r--r--test/core/Inputs/undef-coalesce-error2.objtxt8
-rw-r--r--test/core/Inputs/undef-coalesce.objtxt8
-rw-r--r--test/core/Inputs/undef-coalesce2.objtxt8
-rw-r--r--test/core/Inputs/undef-fallback.objtxt7
-rw-r--r--test/core/Inputs/undef-weak-coalesce.objtxt20
-rw-r--r--test/core/Inputs/weak-coalesce.objtxt5
-rw-r--r--test/core/Inputs/weak-coalesce2.objtxt6
-rw-r--r--test/core/absolute-basic.objtxt23
-rw-r--r--test/core/absolute-local.objtxt25
-rw-r--r--test/core/archive-basic.objtxt23
-rw-r--r--test/core/archive-chain.objtxt23
-rw-r--r--test/core/archive-tentdef-search.objtxt30
-rw-r--r--test/core/associates.objtxt21
-rw-r--r--test/core/auto-hide-coalesce.objtxt39
-rw-r--r--test/core/code-model-attributes.objtxt33
-rw-r--r--test/core/constants-coalesce.objtxt42
-rw-r--r--test/core/cstring-coalesce.objtxt29
-rw-r--r--test/core/custom-section-coalesce.objtxt50
-rw-r--r--test/core/custom-section.objtxt34
-rw-r--r--test/core/dead-strip-attributes.objtxt22
-rw-r--r--test/core/dead-strip-basic.objtxt45
-rw-r--r--test/core/dead-strip-globals.objtxt43
-rw-r--r--test/core/dead-strip-reverse.objtxt25
-rw-r--r--test/core/error-atom-attribute.objtxt19
-rw-r--r--test/core/error-atom-content-byte-value.objtxt18
-rw-r--r--test/core/error-atom-content-bytes.objtxt19
-rw-r--r--test/core/error-atom-type.objtxt19
-rw-r--r--test/core/error-atom-undefined-wrong-attribue.objtxt17
-rw-r--r--test/core/error-duplicate-absolutes.objtxt19
-rw-r--r--test/core/error-file-attribute.objtxt17
-rw-r--r--test/core/error-fixup-attribute.objtxt21
-rw-r--r--test/core/error-fixup-target.objtxt26
-rw-r--r--test/core/fixups-addend.objtxt50
-rw-r--r--test/core/fixups-dup-named.objtxt31
-rw-r--r--test/core/fixups-named.objtxt36
-rw-r--r--test/core/fixups-unnamed.objtxt40
-rw-r--r--test/core/gnulinkonce-rearrange-resolve.objtxt53
-rw-r--r--test/core/gnulinkonce-remaining-undef.objtxt43
-rw-r--r--test/core/gnulinkonce-resolve.objtxt63
-rw-r--r--test/core/gnulinkonce-simple.objtxt76
-rw-r--r--test/core/inline-coalesce.objtxt19
-rw-r--r--test/core/multiple-def-error.objtxt14
-rw-r--r--test/core/permissions.objtxt57
-rw-r--r--test/core/sectiongroup-deadstrip.objtxt84
-rw-r--r--test/core/sectiongroup-gnulinkonce-error.objtxt38
-rw-r--r--test/core/sectiongroup-rearrange-resolve.objtxt53
-rw-r--r--test/core/sectiongroup-remaining-undef.objtxt42
-rw-r--r--test/core/sectiongroup-resolve.objtxt64
-rw-r--r--test/core/sectiongroup-simple.objtxt76
-rw-r--r--test/core/shared-library-basic.objtxt40
-rw-r--r--test/core/shared-library-coalesce.objtxt55
-rw-r--r--test/core/tent-merge.objtxt19
-rw-r--r--test/core/undef-coalesce-error.objtxt31
-rw-r--r--test/core/undef-coalesce.objtxt26
-rw-r--r--test/core/undef-fallback.objtxt29
-rw-r--r--test/core/undef-weak-coalesce.objtxt52
-rw-r--r--test/core/weak-coalesce.objtxt16
-rw-r--r--test/darwin/cmdline-objc_gc.objtxt15
-rw-r--r--test/darwin/cmdline-objc_gc_compaction.objtxt15
-rw-r--r--test/darwin/cmdline-objc_gc_only.objtxt15
-rw-r--r--test/lit.cfg13
-rw-r--r--test/lit.site.cfg.in5
-rw-r--r--test/mach-o/Inputs/no-version-min-load-command-object.yaml22
-rw-r--r--test/mach-o/Inputs/swift-version-1.yaml18
-rw-r--r--test/mach-o/arm-interworking-movw.yaml6
-rw-r--r--test/mach-o/arm64-relocs-errors-delta64-offset.yaml2
-rw-r--r--test/mach-o/data-in-code-load-command.yaml35
-rw-r--r--test/mach-o/dead-strip-globals.yaml27
-rw-r--r--test/mach-o/dependency_info.yaml13
-rw-r--r--test/mach-o/do-not-emit-unwind-fde-arm64.yaml8
-rw-r--r--test/mach-o/dso_handle.yaml2
-rw-r--r--test/mach-o/eh-frame-relocs-arm64.yaml318
-rw-r--r--test/mach-o/error-simulator-vs-macosx.yaml30
-rw-r--r--test/mach-o/function-starts-load-command.yaml32
-rw-r--r--test/mach-o/hello-world-x86_64.yaml5
-rw-r--r--test/mach-o/interposing-section.yaml2
-rw-r--r--test/mach-o/lazy-bind-x86_64.yaml11
-rw-r--r--test/mach-o/mach_header-cpusubtype.yaml34
-rw-r--r--test/mach-o/mh_bundle_header.yaml9
-rw-r--r--test/mach-o/mh_dylib_header.yaml2
-rw-r--r--test/mach-o/objc-category-list-atom.yaml70
-rw-r--r--test/mach-o/objc-image-info-host-vs-simulator.yaml23
-rw-r--r--test/mach-o/objc-image-info-invalid-size.yaml20
-rw-r--r--test/mach-o/objc-image-info-invalid-version.yaml20
-rw-r--r--test/mach-o/objc-image-info-mismatched-swift-version.yaml20
-rw-r--r--test/mach-o/objc-image-info-pass-output.yaml30
-rw-r--r--test/mach-o/objc-image-info-simulator-vs-host.yaml23
-rw-r--r--test/mach-o/objc-image-info-unsupported-gc.yaml20
-rw-r--r--test/mach-o/objc_export_list.yaml2
-rw-r--r--test/mach-o/parse-cfstring32.yaml2
-rw-r--r--test/mach-o/parse-compact-unwind64.yaml2
-rw-r--r--test/mach-o/parse-data-relocs-x86_64.yaml126
-rw-r--r--test/mach-o/parse-data.yaml4
-rw-r--r--test/mach-o/parse-eh-frame.yaml2
-rw-r--r--test/mach-o/sdk-version-error.yaml22
-rw-r--r--test/mach-o/sectattrs.yaml30
-rw-r--r--test/mach-o/seg-protection-arm64.yaml78
-rw-r--r--test/mach-o/seg-protection-x86_64.yaml78
-rw-r--r--test/mach-o/source-version.yaml28
-rw-r--r--test/mach-o/subsections-via-symbols-default.yaml28
-rw-r--r--test/mach-o/unwind-info-simple-arm64.yaml2
-rw-r--r--test/mach-o/unwind-info-simple-x86_64.yaml4
-rw-r--r--test/mach-o/version-min-load-command-object.yaml35
-rw-r--r--test/mach-o/version-min-load-command.yaml43
-rw-r--r--test/old-elf/AArch64/Inputs/fn.c4
-rw-r--r--test/old-elf/AArch64/Inputs/fn.obin899 -> 0 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/general-dyn-tls-0.yaml64
-rw-r--r--test/old-elf/AArch64/Inputs/initfini-option.c12
-rw-r--r--test/old-elf/AArch64/Inputs/initfini-option.obin1552 -> 0 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/initfini.c13
-rw-r--r--test/old-elf/AArch64/Inputs/initfini.obin2056 -> 0 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/initial-exec-tls-1.yaml77
-rw-r--r--test/old-elf/AArch64/Inputs/main.c4
-rw-r--r--test/old-elf/AArch64/Inputs/main.obin1064 -> 0 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/no-interp-section.c1
-rw-r--r--test/old-elf/AArch64/Inputs/no-interp-section.obin903 -> 0 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/zerosizedsection.obin816 -> 0 bytes
-rw-r--r--test/old-elf/AArch64/Inputs/zerosizedsection.s3
-rw-r--r--test/old-elf/AArch64/defsym.test22
-rw-r--r--test/old-elf/AArch64/dontignorezerosize-sections.test9
-rw-r--r--test/old-elf/AArch64/dynamicvars.test113
-rw-r--r--test/old-elf/AArch64/dynlib-nointerp-section.test5
-rw-r--r--test/old-elf/AArch64/general-dyn-tls-0.test103
-rw-r--r--test/old-elf/AArch64/initfini.test23
-rw-r--r--test/old-elf/AArch64/initial-exec-tls-0.test146
-rw-r--r--test/old-elf/AArch64/local-tls.test184
-rw-r--r--test/old-elf/AArch64/rel-abs16-overflow.test44
-rw-r--r--test/old-elf/AArch64/rel-abs16.test53
-rw-r--r--test/old-elf/AArch64/rel-abs32-overflow.test53
-rw-r--r--test/old-elf/AArch64/rel-abs32.test59
-rw-r--r--test/old-elf/AArch64/rel-abs64.test59
-rw-r--r--test/old-elf/AArch64/rel-adr_prel_lo21-overflow.test45
-rw-r--r--test/old-elf/AArch64/rel-adr_prel_lo21.test51
-rw-r--r--test/old-elf/AArch64/rel-adr_prel_pg_hi21-overflow.test45
-rw-r--r--test/old-elf/AArch64/rel-adr_prel_pg_hi21.test52
-rw-r--r--test/old-elf/AArch64/rel-bad.test44
-rw-r--r--test/old-elf/AArch64/rel-prel16-overflow.test53
-rw-r--r--test/old-elf/AArch64/rel-prel16.test59
-rw-r--r--test/old-elf/AArch64/rel-prel32-overflow.test53
-rw-r--r--test/old-elf/AArch64/rel-prel32.test59
-rw-r--r--test/old-elf/AArch64/rel-prel64.test59
-rw-r--r--test/old-elf/ARM/Inputs/fn.c1
-rwxr-xr-xtest/old-elf/ARM/Inputs/libfn.sobin4972 -> 0 bytes
-rwxr-xr-xtest/old-elf/ARM/Inputs/libobj.sobin5067 -> 0 bytes
-rw-r--r--test/old-elf/ARM/Inputs/obj.c4
-rw-r--r--test/old-elf/ARM/arm-symbols.test51
-rw-r--r--test/old-elf/ARM/defsym.test50
-rw-r--r--test/old-elf/ARM/dynamic-symbols.test83
-rw-r--r--test/old-elf/ARM/entry-point.test113
-rw-r--r--test/old-elf/ARM/exidx.test254
-rw-r--r--test/old-elf/ARM/header-flags.test57
-rw-r--r--test/old-elf/ARM/mapping-code-model.test160
-rw-r--r--test/old-elf/ARM/mapping-symbols.test122
-rw-r--r--test/old-elf/ARM/missing-symbol.test38
-rw-r--r--test/old-elf/ARM/plt-dynamic.test200
-rw-r--r--test/old-elf/ARM/plt-ifunc-interwork.test396
-rw-r--r--test/old-elf/ARM/plt-ifunc-mapping.test109
-rw-r--r--test/old-elf/ARM/rel-abs32.test58
-rw-r--r--test/old-elf/ARM/rel-arm-call.test112
-rw-r--r--test/old-elf/ARM/rel-arm-jump24-veneer-b.test122
-rw-r--r--test/old-elf/ARM/rel-arm-jump24-veneer-bl.test120
-rw-r--r--test/old-elf/ARM/rel-arm-jump24.test108
-rw-r--r--test/old-elf/ARM/rel-arm-mov.test64
-rw-r--r--test/old-elf/ARM/rel-arm-prel31.test90
-rw-r--r--test/old-elf/ARM/rel-arm-target1.test114
-rw-r--r--test/old-elf/ARM/rel-arm-thm-interwork.test121
-rw-r--r--test/old-elf/ARM/rel-base-prel.test61
-rw-r--r--test/old-elf/ARM/rel-copy.test60
-rw-r--r--test/old-elf/ARM/rel-glob-dat.test57
-rw-r--r--test/old-elf/ARM/rel-got-brel.test63
-rw-r--r--test/old-elf/ARM/rel-group-relocs.test71
-rw-r--r--test/old-elf/ARM/rel-ifunc.test101
-rw-r--r--test/old-elf/ARM/rel-jump-slot.test50
-rw-r--r--test/old-elf/ARM/rel-rel32.test56
-rw-r--r--test/old-elf/ARM/rel-thm-call.test114
-rw-r--r--test/old-elf/ARM/rel-thm-jump11.test209
-rw-r--r--test/old-elf/ARM/rel-thm-jump24-veneer.test120
-rw-r--r--test/old-elf/ARM/rel-thm-jump24.test110
-rw-r--r--test/old-elf/ARM/rel-thm-mov.test70
-rw-r--r--test/old-elf/ARM/rel-tls-ie32.test125
-rw-r--r--test/old-elf/ARM/rel-tls-le32.test73
-rw-r--r--test/old-elf/ARM/rel-v4bx.test72
-rw-r--r--test/old-elf/ARM/thm-symbols.test51
-rw-r--r--test/old-elf/ARM/two-got-for-symbol.test62
-rw-r--r--test/old-elf/ARM/undef-lazy-symbol.test133
-rw-r--r--test/old-elf/ARM/veneer-mapping.test92
-rw-r--r--test/old-elf/ARM/weak-branch.test221
-rw-r--r--test/old-elf/Hexagon/Inputs/dynobj-data.c3
-rw-r--r--test/old-elf/Hexagon/Inputs/dynobj-data.obin916 -> 0 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/dynobj.c26
-rw-r--r--test/old-elf/Hexagon/Inputs/dynobj.obin1288 -> 0 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/got-plt-order.c6
-rw-r--r--test/old-elf/Hexagon/Inputs/got-plt-order.obin964 -> 0 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/libMaxAlignment.abin1010 -> 0 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/sda-base.obin1469 -> 0 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/sdata1.c3
-rw-r--r--test/old-elf/Hexagon/Inputs/sdata1.obin684 -> 0 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/sdata2.c6
-rw-r--r--test/old-elf/Hexagon/Inputs/sdata2.obin829 -> 0 bytes
-rw-r--r--test/old-elf/Hexagon/Inputs/use-shared.hexagonbin872 -> 0 bytes
-rw-r--r--test/old-elf/Hexagon/dynlib-data.test9
-rw-r--r--test/old-elf/Hexagon/dynlib-gotoff.test128
-rw-r--r--test/old-elf/Hexagon/dynlib-hash.test9
-rw-r--r--test/old-elf/Hexagon/dynlib-rela.test9
-rw-r--r--test/old-elf/Hexagon/dynlib-syms.test7
-rw-r--r--test/old-elf/Hexagon/dynlib.test36
-rw-r--r--test/old-elf/Hexagon/hexagon-got-plt-order.test5
-rw-r--r--test/old-elf/Hexagon/hexagon-plt-setup.test12
-rw-r--r--test/old-elf/Hexagon/maxalignment.test8
-rw-r--r--test/old-elf/Hexagon/rela-order.test9
-rw-r--r--test/old-elf/Hexagon/sda-base.test4
-rw-r--r--test/old-elf/Hexagon/zerofillquick-sdata.test18
-rw-r--r--test/old-elf/Inputs/abs-test.i386bin504 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/allowduplicates.objtxt12
-rw-r--r--test/old-elf/Inputs/bar.o.x86-64bin1240 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/branch-test.hexagonbin700 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/branch-test.ppcbin852 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/consecutive-weak-defs.o.yaml65
-rw-r--r--test/old-elf/Inputs/constants-merge.x86-64bin1232 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/constdata.x86-64bin1688 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/foo.o.x86-64bin1240 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/globalconst.c2
-rw-r--r--test/old-elf/Inputs/globalconst.o.x86-64bin1072 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/gotpcrel.S11
-rw-r--r--test/old-elf/Inputs/gotpcrel.x86-64bin904 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/group-cmd-search-1.ls1
-rw-r--r--test/old-elf/Inputs/group-cmd-search-2.ls1
-rw-r--r--test/old-elf/Inputs/group-cmd-search-3.ls1
-rw-r--r--test/old-elf/Inputs/ifunc.S21
-rw-r--r--test/old-elf/Inputs/ifunc.cpp3
-rw-r--r--test/old-elf/Inputs/ifunc.cpp.x86-64bin1224 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/ifunc.x86-64bin912 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/libfnarchive.abin2656 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/libifunc.x86-64.sobin2512 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/libundef.sobin11128 -> 0 bytes
-rwxr-xr-xtest/old-elf/Inputs/libweaksym.sobin2160 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/main-with-global-def.o.yaml55
-rw-r--r--test/old-elf/Inputs/mainobj.x86_64bin1360 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/no-unique-section-names.x86-64bin2128 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/object-test.elf-hexagonbin1532 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/object-test.elf-i386bin1784 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/phdr.i386bin17536 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/quickdata-sort-test.o.elf-hexagonbin1385 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/quickdata-sortcommon-test.o.elf-hexagonbin1469 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/quickdata-test.elf-hexagonbin891 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/reloc-test.elf-i386bin1076 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/reloc-xb.x86bin568 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/reloc-xt.x86bin548 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/relocs-dynamic.x86-64bin864 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/relocs.x86-64bin1536 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/responsefile1
-rw-r--r--test/old-elf/Inputs/rodata-test.hexagonbin669 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/rodata-test.i386bin537 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/rodata.c4
-rw-r--r--test/old-elf/Inputs/rodata.obin1568 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/section-test.i386bin717 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/shared.c16
-rw-r--r--test/old-elf/Inputs/shared.so-x86-64bin7536 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/shndx.o-x86_64bin624 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/stripped-empty.x86_64bin416 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/target-test.hexagonbin676 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/target-test.ppcbin552 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/tls-tbss-size.yaml59
-rw-r--r--test/old-elf/Inputs/tls.S50
-rw-r--r--test/old-elf/Inputs/tls.c11
-rw-r--r--test/old-elf/Inputs/tls.x86-64bin1424 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/tlsAddr.x86-64bin1752 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/tlsaddr.c8
-rw-r--r--test/old-elf/Inputs/undef-from-main-so.c1
-rw-r--r--test/old-elf/Inputs/undef-from-main.c5
-rw-r--r--test/old-elf/Inputs/undef-pc32.obin1248 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/undef.obin1264 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/undef2-so.o.yaml49
-rw-r--r--test/old-elf/Inputs/use-shared-32s.c8
-rw-r--r--test/old-elf/Inputs/use-shared-32s.x86-64bin1336 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/use-shared.c7
-rw-r--r--test/old-elf/Inputs/use-shared.x86-64bin1376 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/weaksym.obin840 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/writersyms.obin868 -> 0 bytes
-rw-r--r--test/old-elf/Inputs/x86-64-relocs.S12
-rw-r--r--test/old-elf/Mips/abi-flags-01.test35
-rw-r--r--test/old-elf/Mips/abi-flags-02.test92
-rw-r--r--test/old-elf/Mips/abi-flags-03.test149
-rw-r--r--test/old-elf/Mips/abi-flags-04.test125
-rw-r--r--test/old-elf/Mips/abi-flags-05.test186
-rw-r--r--test/old-elf/Mips/abi-flags-06.test79
-rw-r--r--test/old-elf/Mips/abi-flags-07.test60
-rw-r--r--test/old-elf/Mips/abi-flags-08.test71
-rw-r--r--test/old-elf/Mips/abi-flags-09.test67
-rw-r--r--test/old-elf/Mips/abi-flags-10.test60
-rw-r--r--test/old-elf/Mips/abi-flags-11.test59
-rw-r--r--test/old-elf/Mips/base-address-64.test80
-rw-r--r--test/old-elf/Mips/base-address.test95
-rw-r--r--test/old-elf/Mips/ctors-order.test164
-rw-r--r--test/old-elf/Mips/driver-hash-style.test15
-rw-r--r--test/old-elf/Mips/dt-textrel-64.test74
-rw-r--r--test/old-elf/Mips/dt-textrel.test74
-rw-r--r--test/old-elf/Mips/dynamic-linking.test22
-rw-r--r--test/old-elf/Mips/dynamic-sym.test41
-rw-r--r--test/old-elf/Mips/dynlib-dynamic.test110
-rw-r--r--test/old-elf/Mips/dynlib-dynsym-micro.test208
-rw-r--r--test/old-elf/Mips/dynlib-dynsym.test202
-rw-r--r--test/old-elf/Mips/dynlib-fileheader-64.test72
-rw-r--r--test/old-elf/Mips/dynlib-fileheader-micro-64.test75
-rw-r--r--test/old-elf/Mips/dynlib-fileheader-micro.test79
-rw-r--r--test/old-elf/Mips/dynlib-fileheader.test76
-rw-r--r--test/old-elf/Mips/dynsym-table-1.test127
-rw-r--r--test/old-elf/Mips/dynsym-table-2.test105
-rw-r--r--test/old-elf/Mips/e-flags-merge-1-64.test30
-rw-r--r--test/old-elf/Mips/e-flags-merge-1.test56
-rw-r--r--test/old-elf/Mips/e-flags-merge-10.test43
-rw-r--r--test/old-elf/Mips/e-flags-merge-11.test43
-rw-r--r--test/old-elf/Mips/e-flags-merge-12.test44
-rw-r--r--test/old-elf/Mips/e-flags-merge-2-64.test33
-rw-r--r--test/old-elf/Mips/e-flags-merge-2.test35
-rw-r--r--test/old-elf/Mips/e-flags-merge-3-64.test130
-rw-r--r--test/old-elf/Mips/e-flags-merge-3.test134
-rw-r--r--test/old-elf/Mips/e-flags-merge-4-64.test64
-rw-r--r--test/old-elf/Mips/e-flags-merge-4.test65
-rw-r--r--test/old-elf/Mips/e-flags-merge-5-64.test42
-rw-r--r--test/old-elf/Mips/e-flags-merge-5.test42
-rw-r--r--test/old-elf/Mips/e-flags-merge-6-64.test79
-rw-r--r--test/old-elf/Mips/e-flags-merge-6.test80
-rw-r--r--test/old-elf/Mips/e-flags-merge-7-64.test42
-rw-r--r--test/old-elf/Mips/e-flags-merge-7.test42
-rw-r--r--test/old-elf/Mips/e-flags-merge-8.test65
-rw-r--r--test/old-elf/Mips/e-flags-merge-9.test43
-rw-r--r--test/old-elf/Mips/entry-name.test26
-rw-r--r--test/old-elf/Mips/exe-dynamic.test110
-rw-r--r--test/old-elf/Mips/exe-dynsym-micro.test94
-rw-r--r--test/old-elf/Mips/exe-dynsym.test91
-rw-r--r--test/old-elf/Mips/exe-fileheader-02.test62
-rw-r--r--test/old-elf/Mips/exe-fileheader-03.test72
-rw-r--r--test/old-elf/Mips/exe-fileheader-64.test66
-rw-r--r--test/old-elf/Mips/exe-fileheader-be-64.test60
-rw-r--r--test/old-elf/Mips/exe-fileheader-be.test60
-rw-r--r--test/old-elf/Mips/exe-fileheader-micro-64.test68
-rw-r--r--test/old-elf/Mips/exe-fileheader-micro.test69
-rw-r--r--test/old-elf/Mips/exe-fileheader-n32.test65
-rw-r--r--test/old-elf/Mips/exe-fileheader.test105
-rw-r--r--test/old-elf/Mips/exe-got-micro.test115
-rw-r--r--test/old-elf/Mips/exe-got.test116
-rw-r--r--test/old-elf/Mips/got-page-32-micro.test251
-rw-r--r--test/old-elf/Mips/got-page-32.test244
-rw-r--r--test/old-elf/Mips/got-page-64-micro.test210
-rw-r--r--test/old-elf/Mips/got-page-64.test203
-rw-r--r--test/old-elf/Mips/got16-2.test73
-rw-r--r--test/old-elf/Mips/got16-micro.test165
-rw-r--r--test/old-elf/Mips/got16.test196
-rw-r--r--test/old-elf/Mips/gotsym.test43
-rw-r--r--test/old-elf/Mips/gp-sym-1-micro.test88
-rw-r--r--test/old-elf/Mips/gp-sym-1.test86
-rw-r--r--test/old-elf/Mips/gp-sym-2.test103
-rw-r--r--test/old-elf/Mips/hilo16-1.test40
-rw-r--r--test/old-elf/Mips/hilo16-2.test70
-rw-r--r--test/old-elf/Mips/hilo16-3-overflow.test44
-rw-r--r--test/old-elf/Mips/hilo16-3.test74
-rw-r--r--test/old-elf/Mips/hilo16-4.test93
-rw-r--r--test/old-elf/Mips/hilo16-5.test103
-rw-r--r--test/old-elf/Mips/hilo16-8-micro.test81
-rw-r--r--test/old-elf/Mips/hilo16-9-micro.test142
-rw-r--r--test/old-elf/Mips/initfini-micro.test45
-rw-r--r--test/old-elf/Mips/interpreter-64.test26
-rw-r--r--test/old-elf/Mips/interpreter-n32.test27
-rw-r--r--test/old-elf/Mips/interpreter.test26
-rw-r--r--test/old-elf/Mips/invalid-reginfo.test28
-rw-r--r--test/old-elf/Mips/jalx-align-err.test46
-rw-r--r--test/old-elf/Mips/jalx-jalr.test47
-rw-r--r--test/old-elf/Mips/jalx.test71
-rw-r--r--test/old-elf/Mips/jump-fix-err.test45
-rw-r--r--test/old-elf/Mips/la25-stub-be.test113
-rw-r--r--test/old-elf/Mips/la25-stub-micro-be.test121
-rw-r--r--test/old-elf/Mips/la25-stub-micro.test136
-rw-r--r--test/old-elf/Mips/la25-stub-npic-01.test153
-rw-r--r--test/old-elf/Mips/la25-stub-npic-02.test123
-rw-r--r--test/old-elf/Mips/la25-stub-npic-shared.test152
-rw-r--r--test/old-elf/Mips/la25-stub-pic.test144
-rw-r--r--test/old-elf/Mips/la25-stub.test133
-rw-r--r--test/old-elf/Mips/mips-options-01.test34
-rw-r--r--test/old-elf/Mips/mips-options-02.test104
-rw-r--r--test/old-elf/Mips/mips-options-03.test41
-rw-r--r--test/old-elf/Mips/mips-options-04.test77
-rw-r--r--test/old-elf/Mips/mips-options-05.test119
-rw-r--r--test/old-elf/Mips/mips-options-gp0.test77
-rw-r--r--test/old-elf/Mips/n32-rela-chain.test68
-rw-r--r--test/old-elf/Mips/n64-rel-chain.test204
-rw-r--r--test/old-elf/Mips/n64-rel-shift.test48
-rw-r--r--test/old-elf/Mips/opt-emulation.test43
-rw-r--r--test/old-elf/Mips/pc23-range.test54
-rw-r--r--test/old-elf/Mips/plt-entry-mixed-1.test114
-rw-r--r--test/old-elf/Mips/plt-entry-mixed-2.test93
-rw-r--r--test/old-elf/Mips/plt-entry-mixed-3.test98
-rw-r--r--test/old-elf/Mips/plt-entry-mixed-4.test85
-rw-r--r--test/old-elf/Mips/plt-entry-r6-be.test109
-rw-r--r--test/old-elf/Mips/plt-entry-r6.test109
-rw-r--r--test/old-elf/Mips/plt-header-be.test104
-rw-r--r--test/old-elf/Mips/plt-header-micro-be.test105
-rw-r--r--test/old-elf/Mips/plt-header-micro.test108
-rw-r--r--test/old-elf/Mips/plt-header-mixed.test105
-rw-r--r--test/old-elf/Mips/plt-header.test99
-rw-r--r--test/old-elf/Mips/r26-1-micro.test131
-rw-r--r--test/old-elf/Mips/r26-1.test132
-rw-r--r--test/old-elf/Mips/r26-2-micro.test31
-rw-r--r--test/old-elf/Mips/r26-2.test31
-rw-r--r--test/old-elf/Mips/reginfo-01.test30
-rw-r--r--test/old-elf/Mips/reginfo-02.test107
-rw-r--r--test/old-elf/Mips/reginfo-03.test45
-rw-r--r--test/old-elf/Mips/reginfo-04.test81
-rw-r--r--test/old-elf/Mips/reginfo-05.test123
-rw-r--r--test/old-elf/Mips/rel-16-overflow.test45
-rw-r--r--test/old-elf/Mips/rel-16.test51
-rw-r--r--test/old-elf/Mips/rel-32-be.test60
-rw-r--r--test/old-elf/Mips/rel-32.test59
-rw-r--r--test/old-elf/Mips/rel-64.test61
-rw-r--r--test/old-elf/Mips/rel-call-hilo-01.test109
-rw-r--r--test/old-elf/Mips/rel-call-hilo-micro.test154
-rw-r--r--test/old-elf/Mips/rel-copy-micro.test159
-rw-r--r--test/old-elf/Mips/rel-copy-pc.test113
-rw-r--r--test/old-elf/Mips/rel-copy.test177
-rw-r--r--test/old-elf/Mips/rel-dynamic-01-micro.test201
-rw-r--r--test/old-elf/Mips/rel-dynamic-01.test261
-rw-r--r--test/old-elf/Mips/rel-dynamic-02.test101
-rw-r--r--test/old-elf/Mips/rel-dynamic-03-micro.test133
-rw-r--r--test/old-elf/Mips/rel-dynamic-03.test129
-rw-r--r--test/old-elf/Mips/rel-dynamic-04-micro.test226
-rw-r--r--test/old-elf/Mips/rel-dynamic-04.test221
-rw-r--r--test/old-elf/Mips/rel-dynamic-05-micro.test192
-rw-r--r--test/old-elf/Mips/rel-dynamic-05.test188
-rw-r--r--test/old-elf/Mips/rel-dynamic-06-64.test114
-rw-r--r--test/old-elf/Mips/rel-dynamic-06.test115
-rw-r--r--test/old-elf/Mips/rel-dynamic-07-64.test348
-rw-r--r--test/old-elf/Mips/rel-dynamic-07.test363
-rw-r--r--test/old-elf/Mips/rel-dynamic-08-64.test275
-rw-r--r--test/old-elf/Mips/rel-dynamic-08-micro.test278
-rw-r--r--test/old-elf/Mips/rel-dynamic-08.test275
-rw-r--r--test/old-elf/Mips/rel-dynamic-09-micro.test109
-rw-r--r--test/old-elf/Mips/rel-dynamic-09.test107
-rw-r--r--test/old-elf/Mips/rel-dynamic-10-micro.test166
-rw-r--r--test/old-elf/Mips/rel-dynamic-10.test160
-rw-r--r--test/old-elf/Mips/rel-dynamic-11.test110
-rw-r--r--test/old-elf/Mips/rel-dynamic-12.test237
-rw-r--r--test/old-elf/Mips/rel-dynamic-13.test94
-rw-r--r--test/old-elf/Mips/rel-dynamic-14.test94
-rw-r--r--test/old-elf/Mips/rel-dynamic-15.test81
-rw-r--r--test/old-elf/Mips/rel-eh-01.test186
-rw-r--r--test/old-elf/Mips/rel-eh-02.test130
-rw-r--r--test/old-elf/Mips/rel-eh-03.test128
-rw-r--r--test/old-elf/Mips/rel-got-hilo-01.test109
-rw-r--r--test/old-elf/Mips/rel-got-hilo-micro.test154
-rw-r--r--test/old-elf/Mips/rel-gprel16-micro-overflow.test57
-rw-r--r--test/old-elf/Mips/rel-gprel16-micro.test78
-rw-r--r--test/old-elf/Mips/rel-gprel16-overflow.test48
-rw-r--r--test/old-elf/Mips/rel-gprel16.test104
-rw-r--r--test/old-elf/Mips/rel-gprel32-64.test84
-rw-r--r--test/old-elf/Mips/rel-gprel32.test84
-rw-r--r--test/old-elf/Mips/rel-gprel7-micro-overflow.test48
-rw-r--r--test/old-elf/Mips/rel-gprel7-micro.test65
-rw-r--r--test/old-elf/Mips/rel-hi0-lo16-micro.test58
-rw-r--r--test/old-elf/Mips/rel-high-01.test25
-rw-r--r--test/old-elf/Mips/rel-high-02.test25
-rw-r--r--test/old-elf/Mips/rel-jalr-01.test101
-rw-r--r--test/old-elf/Mips/rel-jalr-02.test68
-rw-r--r--test/old-elf/Mips/rel-lit-micro.test59
-rw-r--r--test/old-elf/Mips/rel-lit.test57
-rw-r--r--test/old-elf/Mips/rel-pc-hilo.test70
-rw-r--r--test/old-elf/Mips/rel-pc16-align.test43
-rw-r--r--test/old-elf/Mips/rel-pc16-overflow.test45
-rw-r--r--test/old-elf/Mips/rel-pc16.test53
-rw-r--r--test/old-elf/Mips/rel-pc18-s3-align.test44
-rw-r--r--test/old-elf/Mips/rel-pc18-s3-micro.test56
-rw-r--r--test/old-elf/Mips/rel-pc18-s3.test54
-rw-r--r--test/old-elf/Mips/rel-pc19-s2-align.test44
-rw-r--r--test/old-elf/Mips/rel-pc19-s2-micro.test56
-rw-r--r--test/old-elf/Mips/rel-pc19-s2.test54
-rw-r--r--test/old-elf/Mips/rel-pc21-s2-align.test44
-rw-r--r--test/old-elf/Mips/rel-pc21-s2-micro.test56
-rw-r--r--test/old-elf/Mips/rel-pc21-s2-overflow.test45
-rw-r--r--test/old-elf/Mips/rel-pc21-s2.test54
-rw-r--r--test/old-elf/Mips/rel-pc26-s2-align.test44
-rw-r--r--test/old-elf/Mips/rel-pc26-s2-micro.test56
-rw-r--r--test/old-elf/Mips/rel-pc26-s2.test54
-rw-r--r--test/old-elf/Mips/rel-pc32.test59
-rw-r--r--test/old-elf/Mips/rel-pc7-10-16-23.test86
-rw-r--r--test/old-elf/Mips/rel-sub-micro.test62
-rw-r--r--test/old-elf/Mips/rel-sub.test61
-rw-r--r--test/old-elf/Mips/rld_map.test42
-rw-r--r--test/old-elf/Mips/sign-rela.test54
-rw-r--r--test/old-elf/Mips/st-other.test90
-rw-r--r--test/old-elf/Mips/static-01.test119
-rw-r--r--test/old-elf/Mips/tls-1-micro.test65
-rw-r--r--test/old-elf/Mips/tls-1.test63
-rw-r--r--test/old-elf/Mips/tls-2-64-static.test71
-rw-r--r--test/old-elf/Mips/tls-2-64.test69
-rw-r--r--test/old-elf/Mips/tls-2-micro.test70
-rw-r--r--test/old-elf/Mips/tls-2-static.test125
-rw-r--r--test/old-elf/Mips/tls-2.test69
-rw-r--r--test/old-elf/Mips/tls-3-64-static.test70
-rw-r--r--test/old-elf/Mips/tls-3-micro.test183
-rw-r--r--test/old-elf/Mips/tls-3-static.test67
-rw-r--r--test/old-elf/Mips/tls-3.test180
-rw-r--r--test/old-elf/Mips/tls-4-64-static.test71
-rw-r--r--test/old-elf/Mips/tls-4-micro.test126
-rw-r--r--test/old-elf/Mips/tls-4-static.test68
-rw-r--r--test/old-elf/Mips/tls-4.test123
-rw-r--r--test/old-elf/Mips/tls-5-64.test71
-rw-r--r--test/old-elf/Mips/tls-5-micro.test70
-rw-r--r--test/old-elf/Mips/tls-5.test69
-rw-r--r--test/old-elf/Mips/validate-rel-01.test82
-rw-r--r--test/old-elf/Mips/validate-rel-03.test56
-rw-r--r--test/old-elf/X86_64/ExampleTarget/triple.test32
-rw-r--r--test/old-elf/X86_64/Inputs/constint.c1
-rw-r--r--test/old-elf/X86_64/Inputs/constint.obin1062 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/debug0.c5
-rw-r--r--test/old-elf/X86_64/Inputs/debug0.x86-64bin2704 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/debug1.c3
-rw-r--r--test/old-elf/X86_64/Inputs/debug1.x86-64bin2584 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/externtls.c6
-rw-r--r--test/old-elf/X86_64/Inputs/externtls.x86-64bin1424 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/fn.c4
-rw-r--r--test/old-elf/X86_64/Inputs/fn.obin1072 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/generaltls-so.o.yaml67
-rw-r--r--test/old-elf/X86_64/Inputs/group/1.c8
-rw-r--r--test/old-elf/X86_64/Inputs/group/1.obin1456 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn.c4
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn.obin1360 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn1.c3
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn1.obin1352 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn2.c3
-rw-r--r--test/old-elf/X86_64/Inputs/group/fn2.obin1224 -> 0 bytes
-rwxr-xr-xtest/old-elf/X86_64/Inputs/group/group.sh38
-rw-r--r--test/old-elf/X86_64/Inputs/group/libfn.abin2792 -> 0 bytes
-rwxr-xr-xtest/old-elf/X86_64/Inputs/group/libfn.sobin2516 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/group/libfn1.abin1492 -> 0 bytes
-rwxr-xr-xtest/old-elf/X86_64/Inputs/group/libfn2.sobin9624 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/initfini-option.c13
-rw-r--r--test/old-elf/X86_64/Inputs/initfini-option.obin1824 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/initfini.c14
-rw-r--r--test/old-elf/X86_64/Inputs/initfini.obin2256 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/largebss.c3
-rw-r--r--test/old-elf/X86_64/Inputs/largebss.obin1131 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/1.c8
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/1.obin1448 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/2.c7
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/2.obin1320 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/3.c3
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/3.obin1216 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/layoutpass/lib2.abin1464 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/libfn.abin1364 -> 0 bytes
-rwxr-xr-xtest/old-elf/X86_64/Inputs/libfn.sobin2008 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/main.c4
-rw-r--r--test/old-elf/X86_64/Inputs/main.obin1360 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/multi-ovrd.c10
-rw-r--r--test/old-elf/X86_64/Inputs/multi-ovrd.obin1648 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/multi-weak.c20
-rw-r--r--test/old-elf/X86_64/Inputs/multi-weak.obin1856 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/multiweaksyms.obin928 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/nmagic.c8
-rw-r--r--test/old-elf/X86_64/Inputs/nmagic.obin1528 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/no-interp-section.c1
-rw-r--r--test/old-elf/X86_64/Inputs/no-interp-section.obin975 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/note.obin785 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/note.s11
-rw-r--r--test/old-elf/X86_64/Inputs/note_ro_rw.obin905 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/note_ro_rw.s21
-rw-r--r--test/old-elf/X86_64/Inputs/ovrd.c6
-rw-r--r--test/old-elf/X86_64/Inputs/ovrd.obin1488 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/rodata.c3
-rw-r--r--test/old-elf/X86_64/Inputs/rodata.obin1584 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/rodata.s24
-rw-r--r--test/old-elf/X86_64/Inputs/rwint.c1
-rw-r--r--test/old-elf/X86_64/Inputs/rwint.obin963 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/sectionmap.c4
-rw-r--r--test/old-elf/X86_64/Inputs/sectionmap.obin1478 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/undefcpp.c1
-rw-r--r--test/old-elf/X86_64/Inputs/undefcpp.obin1344 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/weak-zero-sized.obin688 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/weak.c14
-rw-r--r--test/old-elf/X86_64/Inputs/weak.obin1712 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/weak.s21
-rw-r--r--test/old-elf/X86_64/Inputs/zerosizedsection.obin760 -> 0 bytes
-rw-r--r--test/old-elf/X86_64/Inputs/zerosizedsection.s3
-rw-r--r--test/old-elf/X86_64/alignoffset.test118
-rw-r--r--test/old-elf/X86_64/debug.test57
-rw-r--r--test/old-elf/X86_64/defsym.test22
-rw-r--r--test/old-elf/X86_64/demangle.test12
-rw-r--r--test/old-elf/X86_64/dontignorezerosize-sections.test9
-rw-r--r--test/old-elf/X86_64/dynamicvars.test123
-rw-r--r--test/old-elf/X86_64/dynlib-nointerp-section.test4
-rw-r--r--test/old-elf/X86_64/dynlib-search.test6
-rw-r--r--test/old-elf/X86_64/dynsym-weak.test118
-rw-r--r--test/old-elf/X86_64/extern-tls.test16
-rw-r--r--test/old-elf/X86_64/general-dynamic-tls.test128
-rw-r--r--test/old-elf/X86_64/imagebase.test94
-rw-r--r--test/old-elf/X86_64/initfini-order.test10
-rw-r--r--test/old-elf/X86_64/initfini.test23
-rw-r--r--test/old-elf/X86_64/largebss.test20
-rw-r--r--test/old-elf/X86_64/layoutpass-order.test14
-rw-r--r--test/old-elf/X86_64/maxpagesize.test113
-rw-r--r--test/old-elf/X86_64/mergesimilarstrings.test47
-rw-r--r--test/old-elf/X86_64/multi-weak-layout.test52
-rw-r--r--test/old-elf/X86_64/multi-weak-override.test16
-rw-r--r--test/old-elf/X86_64/multi-weak-syms-order.test13
-rw-r--r--test/old-elf/X86_64/nmagic.test91
-rw-r--r--test/old-elf/X86_64/noalignsegments.test95
-rw-r--r--test/old-elf/X86_64/note-sections-ro_plus_rw.test42
-rw-r--r--test/old-elf/X86_64/note-sections.test23
-rw-r--r--test/old-elf/X86_64/omagic.test237
-rw-r--r--test/old-elf/X86_64/outputsegments.test188
-rw-r--r--test/old-elf/X86_64/reloc_r_x86_64_16.test59
-rw-r--r--test/old-elf/X86_64/reloc_r_x86_64_pc16.test60
-rw-r--r--test/old-elf/X86_64/reloc_r_x86_64_pc64.test60
-rw-r--r--test/old-elf/X86_64/rodata.test9
-rw-r--r--test/old-elf/X86_64/sectionchoice.test7
-rw-r--r--test/old-elf/X86_64/sectionmap.test22
-rw-r--r--test/old-elf/X86_64/startGroupEndGroup.test48
-rw-r--r--test/old-elf/X86_64/startGroupEndGroupWithDynlib.test10
-rw-r--r--test/old-elf/X86_64/staticlib-search.test6
-rw-r--r--test/old-elf/X86_64/undef.test18
-rw-r--r--test/old-elf/X86_64/underscore-end.test81
-rw-r--r--test/old-elf/X86_64/weak-override.test45
-rw-r--r--test/old-elf/X86_64/weak-zero-sized.test26
-rw-r--r--test/old-elf/X86_64/weaksym.test77
-rw-r--r--test/old-elf/X86_64/yamlinput.test166
-rw-r--r--test/old-elf/abs-dup.objtxt19
-rw-r--r--test/old-elf/abs.test19
-rw-r--r--test/old-elf/allowduplicates.objtxt41
-rw-r--r--test/old-elf/archive-elf-forceload.test43
-rw-r--r--test/old-elf/archive-elf.test38
-rw-r--r--test/old-elf/as-needed.test15
-rw-r--r--test/old-elf/branch.test34
-rw-r--r--test/old-elf/check.test39
-rw-r--r--test/old-elf/checkrodata.test9
-rw-r--r--test/old-elf/common.test10
-rw-r--r--test/old-elf/consecutive-weak-sym-defs.test81
-rw-r--r--test/old-elf/defsym.objtxt31
-rw-r--r--test/old-elf/discard-all.test88
-rw-r--r--test/old-elf/discard-locals.test65
-rw-r--r--test/old-elf/dynamic-segorder.test17
-rw-r--r--test/old-elf/dynamic-undef.test38
-rw-r--r--test/old-elf/dynamic.test80
-rw-r--r--test/old-elf/eh_frame_hdr.test30
-rw-r--r--test/old-elf/entry.objtxt58
-rw-r--r--test/old-elf/export-dynamic.test98
-rw-r--r--test/old-elf/filenotfound.test3
-rw-r--r--test/old-elf/gnulinkonce/gnulinkonce-report-discarded-reference.test145
-rw-r--r--test/old-elf/gnulinkonce/gnulinkonce-report-undef.test127
-rw-r--r--test/old-elf/gnulinkonce/gnulinkonce.test149
-rw-r--r--test/old-elf/gotpcrel.test21
-rw-r--r--test/old-elf/gottpoff.test119
-rw-r--r--test/old-elf/group-cmd-search.test134
-rw-r--r--test/old-elf/hexagon-quickdata-sort.test12
-rw-r--r--test/old-elf/hexagon-quickdata-sortcommon.test16
-rw-r--r--test/old-elf/ifunc.test69
-rw-r--r--test/old-elf/ignore-unknownoption.test5
-rw-r--r--test/old-elf/init_array-order.test67
-rw-r--r--test/old-elf/init_array.test127
-rw-r--r--test/old-elf/initfini-options.test-1.test33
-rw-r--r--test/old-elf/initfini-options.test-2.test47
-rw-r--r--test/old-elf/initfini-options.test-3.test53
-rw-r--r--test/old-elf/librarynotfound.test5
-rw-r--r--test/old-elf/linker-as-ld.test16
-rw-r--r--test/old-elf/linkerscript/Inputs/externs.ls3
-rw-r--r--test/old-elf/linkerscript/Inputs/invalid.ls1
-rw-r--r--test/old-elf/linkerscript/Inputs/prog1.o.yaml87
-rw-r--r--test/old-elf/linkerscript/Inputs/prog2.o.yaml88
-rw-r--r--test/old-elf/linkerscript/Inputs/prog3.o.yaml51
-rw-r--r--test/old-elf/linkerscript/Inputs/simple-pic.o.yaml32
-rw-r--r--test/old-elf/linkerscript/Inputs/simple.o.yaml51
-rw-r--r--test/old-elf/linkerscript/Inputs/valid.ls6
-rw-r--r--test/old-elf/linkerscript/externs.objtxt21
-rw-r--r--test/old-elf/linkerscript/filename-with-wildcards.test49
-rw-r--r--test/old-elf/linkerscript/invalid-script-cli-1.test10
-rw-r--r--test/old-elf/linkerscript/invalid-script-cli-2.test6
-rw-r--r--test/old-elf/linkerscript/invalid.test5
-rw-r--r--test/old-elf/linkerscript/phdrs-all-none.test26
-rw-r--r--test/old-elf/linkerscript/phdrs-custom-none.test36
-rw-r--r--test/old-elf/linkerscript/phdrs-default.test82
-rw-r--r--test/old-elf/linkerscript/phdrs-different.test45
-rw-r--r--test/old-elf/linkerscript/phdrs-extra-program.test27
-rw-r--r--test/old-elf/linkerscript/phdrs-flags.test46
-rw-r--r--test/old-elf/linkerscript/phdrs-has-program.test33
-rw-r--r--test/old-elf/linkerscript/phdrs-invalid.test63
-rw-r--r--test/old-elf/linkerscript/phdrs-misplaced-program.test26
-rw-r--r--test/old-elf/linkerscript/phdrs-no-program.test25
-rw-r--r--test/old-elf/linkerscript/phdrs-one-none.test36
-rw-r--r--test/old-elf/linkerscript/phdrs-program-flags.test33
-rw-r--r--test/old-elf/linkerscript/phdrs-program-good-phdrs.test34
-rw-r--r--test/old-elf/linkerscript/phdrs-program-no-phdrs.test26
-rw-r--r--test/old-elf/linkerscript/phdrs-program-wrong-phdrs.test26
-rw-r--r--test/old-elf/linkerscript/phdrs-same-flags.test35
-rw-r--r--test/old-elf/linkerscript/phdrs-same.test36
-rw-r--r--test/old-elf/linkerscript/phdrs/sections-empty-phdrs.script11
-rw-r--r--test/old-elf/linkerscript/phdrs/sections-no-phdrs.script7
-rw-r--r--test/old-elf/linkerscript/phdrs/sections-none-phdrs.script11
-rw-r--r--test/old-elf/linkerscript/phdrs/undef-empty-phdrs.script11
-rw-r--r--test/old-elf/linkerscript/phdrs/undef-id-phdrs.script12
-rw-r--r--test/old-elf/linkerscript/phdrs/undef-no-phdrs.script7
-rw-r--r--test/old-elf/linkerscript/sections-order.test113
-rw-r--r--test/old-elf/linkerscript/sections-with-wildcards.test88
-rw-r--r--test/old-elf/linkerscript/symbol-definition-so.test32
-rw-r--r--test/old-elf/linkerscript/symbol-definition.test54
-rw-r--r--test/old-elf/linkerscript/valid-script-cli.objtxt23
-rw-r--r--test/old-elf/loginputfiles.test28
-rw-r--r--test/old-elf/mergeatoms.test6
-rw-r--r--test/old-elf/mergeconstants.test20
-rw-r--r--test/old-elf/mergeglobalatoms.test11
-rw-r--r--test/old-elf/no-unique-section-names.test19
-rw-r--r--test/old-elf/note.test50
-rw-r--r--test/old-elf/options/dynamic-linker.test17
-rw-r--r--test/old-elf/options/target-specific-args.test5
-rw-r--r--test/old-elf/phdr.test99
-rw-r--r--test/old-elf/quickdata.test15
-rw-r--r--test/old-elf/reloc.test38
-rw-r--r--test/old-elf/responsefile.test6
-rw-r--r--test/old-elf/rodata.test5
-rw-r--r--test/old-elf/rosegment.test26
-rw-r--r--test/old-elf/sectionGroups/sectiongroup-new-members.test151
-rw-r--r--test/old-elf/sectionGroups/sectiongroup-simple.test144
-rw-r--r--test/old-elf/sectionGroups/sectiongroup-undef-member-other.test156
-rw-r--r--test/old-elf/sectionGroups/sectiongroup-undef-member.test142
-rw-r--r--test/old-elf/sectionGroups/sectiongroup-with-globalsymbols.test250
-rw-r--r--test/old-elf/sectionGroups/sectiongroup-with-undef-external-reference.test236
-rw-r--r--test/old-elf/sectionGroups/sectiongroup-with-undef-signature.test219
-rw-r--r--test/old-elf/sections.test142
-rw-r--r--test/old-elf/sh_addralign.test37
-rw-r--r--test/old-elf/shndx.test18
-rw-r--r--test/old-elf/soname.test6
-rw-r--r--test/old-elf/start-stop-sym.test108
-rw-r--r--test/old-elf/strip-all.test108
-rw-r--r--test/old-elf/stripped-empty.test4
-rw-r--r--test/old-elf/symbols.test33
-rw-r--r--test/old-elf/tls-tbss-size.test176
-rw-r--r--test/old-elf/tls.test43
-rw-r--r--test/old-elf/tlsAddr.test7
-rw-r--r--test/old-elf/undef-from-dso-to-main.test52
-rw-r--r--test/old-elf/undef-from-main-dso.test43
-rw-r--r--test/old-elf/weaksym.test7
-rw-r--r--test/old-elf/wrap.test276
-rw-r--r--test/old-elf/x86-64-dynamic-relocs.test26
-rw-r--r--test/old-elf/x86-64-dynamic.test79
-rw-r--r--test/old-elf/x86.test38
-rw-r--r--test/old-elf/x86_64-kinds.test23
-rw-r--r--test/old-elf/zoption_dtflags.test89
-rw-r--r--tools/CMakeLists.txt2
-rw-r--r--tools/linker-script-test/CMakeLists.txt8
-rw-r--r--tools/linker-script-test/linker-script-test.cpp57
-rw-r--r--tools/lld/CMakeLists.txt1
-rw-r--r--tools/lld/TODO.txt2
-rw-r--r--tools/lld/lld.cpp108
-rw-r--r--unittests/CoreTests/CMakeLists.txt5
-rw-r--r--unittests/CoreTests/RangeTest.cpp240
-rw-r--r--unittests/DriverTests/CMakeLists.txt4
-rw-r--r--unittests/DriverTests/DarwinLdDriverTest.cpp153
-rw-r--r--unittests/DriverTests/DriverTest.h61
-rw-r--r--unittests/DriverTests/GnuLdDriverTest.cpp299
-rw-r--r--unittests/DriverTests/UniversalDriverTest.cpp33
-rw-r--r--unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp25
-rw-r--r--unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp18
-rw-r--r--unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp18
-rw-r--r--unittests/MachOTests/MachONormalizedFileYAMLTests.cpp23
1685 files changed, 30937 insertions, 78902 deletions
diff --git a/.arcconfig b/.arcconfig
index 787b339a9f20..ebf4a4a6f8b7 100644
--- a/.arcconfig
+++ b/.arcconfig
@@ -1,4 +1,4 @@
{
"project_id" : "lld",
- "conduit_uri" : "http://reviews.llvm.org/"
+ "conduit_uri" : "https://reviews.llvm.org/"
}
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7458de08fc16..46ca748f8fac 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -94,7 +94,7 @@ endmacro(add_lld_library)
add_subdirectory(lib)
-add_subdirectory(tools)
+add_subdirectory(tools/lld)
if (LLVM_INCLUDE_TESTS)
add_subdirectory(test)
diff --git a/COFF/CMakeLists.txt b/COFF/CMakeLists.txt
index 3f31ba9ba1fb..3319f392efe1 100644
--- a/COFF/CMakeLists.txt
+++ b/COFF/CMakeLists.txt
@@ -10,6 +10,7 @@ add_lld_library(lldCOFF
Error.cpp
ICF.cpp
InputFiles.cpp
+ Librarian.cpp
MarkLive.cpp
ModuleDef.cpp
PDB.cpp
@@ -28,6 +29,8 @@ add_lld_library(lldCOFF
Target
Option
Support
+
+ LINK_LIBS ${PTHREAD_LIB}
)
add_dependencies(lldCOFF COFFOptionsTableGen)
diff --git a/COFF/Chunks.cpp b/COFF/Chunks.cpp
index f9f768d69866..1c1b18176aa2 100644
--- a/COFF/Chunks.cpp
+++ b/COFF/Chunks.cpp
@@ -34,10 +34,7 @@ SectionChunk::SectionChunk(ObjectFile *F, const coff_section *H)
// Initialize SectionName.
File->getCOFFObj()->getSectionName(Header, SectionName);
- // Bit [20:24] contains section alignment. Both 0 and 1 mean alignment 1.
- unsigned Shift = (Header->Characteristics >> 20) & 0xF;
- if (Shift > 0)
- Align = uint32_t(1) << (Shift - 1);
+ Align = Header->getAlignment();
// Only COMDAT sections are subject of dead-stripping.
Live = !isCOMDAT();
@@ -64,7 +61,7 @@ void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, Defined *Sym,
case IMAGE_REL_AMD64_SECTION: add16(Off, Sym->getSectionIndex()); break;
case IMAGE_REL_AMD64_SECREL: add32(Off, Sym->getSecrel()); break;
default:
- error("Unsupported relocation type");
+ fatal("unsupported relocation type");
}
}
@@ -79,7 +76,7 @@ void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, Defined *Sym,
case IMAGE_REL_I386_SECTION: add16(Off, Sym->getSectionIndex()); break;
case IMAGE_REL_I386_SECREL: add32(Off, Sym->getSecrel()); break;
default:
- error("Unsupported relocation type");
+ fatal("unsupported relocation type");
}
}
@@ -123,7 +120,7 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, Defined *Sym,
case IMAGE_REL_ARM_BRANCH24T: applyBranch24T(Off, S - P - 4); break;
case IMAGE_REL_ARM_BLX23T: applyBranch24T(Off, S - P - 4); break;
default:
- error("Unsupported relocation type");
+ fatal("unsupported relocation type");
}
}
@@ -310,7 +307,7 @@ void SEHTableChunk::writeTo(uint8_t *Buf) const {
BaserelChunk::BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End) {
// Block header consists of 4 byte page RVA and 4 byte block size.
// Each entry is 2 byte. Last entry may be padding.
- Data.resize(align((End - Begin) * 2 + 8, 4));
+ Data.resize(alignTo((End - Begin) * 2 + 8, 4));
uint8_t *P = Data.data();
write32le(P, Page);
write32le(P + 4, Data.size());
diff --git a/COFF/Chunks.h b/COFF/Chunks.h
index 274135516eb9..cd0e2e69ef5d 100644
--- a/COFF/Chunks.h
+++ b/COFF/Chunks.h
@@ -18,6 +18,7 @@
#include "llvm/ADT/iterator_range.h"
#include "llvm/Object/COFF.h"
#include <atomic>
+#include <utility>
#include <vector>
namespace lld {
@@ -138,6 +139,7 @@ public:
SectionChunk(ObjectFile *File, const coff_section *Header);
static bool classof(const Chunk *C) { return C->kind() == SectionKind; }
size_t getSize() const override { return Header->SizeOfRawData; }
+ ArrayRef<uint8_t> getContents() const;
void writeTo(uint8_t *Buf) const override;
bool hasData() const override;
uint32_t getPermissions() const override;
@@ -186,8 +188,6 @@ public:
uint32_t Checksum = 0;
private:
- ArrayRef<uint8_t> getContents() const;
-
// A file this chunk was created from.
ObjectFile *File;
@@ -295,7 +295,7 @@ private:
// functions. x86-only.
class SEHTableChunk : public Chunk {
public:
- explicit SEHTableChunk(std::set<Defined *> S) : Syms(S) {}
+ explicit SEHTableChunk(std::set<Defined *> S) : Syms(std::move(S)) {}
size_t getSize() const override { return Syms.size() * 4; }
void writeTo(uint8_t *Buf) const override;
@@ -326,10 +326,6 @@ public:
uint8_t Type;
};
-inline uint64_t align(uint64_t Value, uint64_t Align) {
- return llvm::RoundUpToAlignment(Value, Align);
-}
-
} // namespace coff
} // namespace lld
diff --git a/COFF/Config.h b/COFF/Config.h
index 9cfccadba5fa..a5472e937fa1 100644
--- a/COFF/Config.h
+++ b/COFF/Config.h
@@ -106,11 +106,15 @@ struct Configuration {
// Used for /merge:from=to (e.g. /merge:.rdata=.text)
std::map<StringRef, StringRef> Merge;
+ // Used for /section=.name,{DEKPRSW} to set section attributes.
+ std::map<StringRef, uint32_t> Section;
+
// Options for manifest files.
ManifestKind Manifest = SideBySide;
int ManifestID = 1;
StringRef ManifestDependency;
bool ManifestUAC = true;
+ std::vector<std::string> ManifestInput;
StringRef ManifestLevel = "'asInvoker'";
StringRef ManifestUIAccess = "'false'";
StringRef ManifestFile;
diff --git a/COFF/DLL.cpp b/COFF/DLL.cpp
index 8f3383d75c7b..9ac370c11d59 100644
--- a/COFF/DLL.cpp
+++ b/COFF/DLL.cpp
@@ -45,7 +45,7 @@ public:
size_t getSize() const override {
// Starts with 2 byte Hint field, followed by a null-terminated string,
// ends with 0 or 1 byte padding.
- return align(Name.size() + 3, 2);
+ return alignTo(Name.size() + 3, 2);
}
void writeTo(uint8_t *Buf) const override {
diff --git a/COFF/Driver.cpp b/COFF/Driver.cpp
index 4cacf0ff552a..bb6a60e4fc4c 100644
--- a/COFF/Driver.cpp
+++ b/COFF/Driver.cpp
@@ -14,6 +14,7 @@
#include "SymbolTable.h"
#include "Symbols.h"
#include "Writer.h"
+#include "lld/Driver/Driver.h"
#include "llvm/ADT/Optional.h"
#include "llvm/LibDriver/LibDriver.h"
#include "llvm/Option/Arg.h"
@@ -40,27 +41,28 @@ namespace coff {
Configuration *Config;
LinkerDriver *Driver;
-void link(llvm::ArrayRef<const char *> Args) {
+bool link(llvm::ArrayRef<const char *> Args) {
Configuration C;
LinkerDriver D;
Config = &C;
Driver = &D;
- return Driver->link(Args);
+ Driver->link(Args);
+ return true;
}
-// Drop directory components and replace extension with ".exe".
+// Drop directory components and replace extension with ".exe" or ".dll".
static std::string getOutputPath(StringRef Path) {
auto P = Path.find_last_of("\\/");
StringRef S = (P == StringRef::npos) ? Path : Path.substr(P + 1);
- return (S.substr(0, S.rfind('.')) + ".exe").str();
+ const char* E = Config->DLL ? ".dll" : ".exe";
+ return (S.substr(0, S.rfind('.')) + E).str();
}
// Opens a file. Path has to be resolved already.
// Newly created memory buffers are owned by this driver.
MemoryBufferRef LinkerDriver::openFile(StringRef Path) {
- auto MBOrErr = MemoryBuffer::getFile(Path);
- error(MBOrErr, Twine("Could not open ") + Path);
- std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
+ std::unique_ptr<MemoryBuffer> MB =
+ check(MemoryBuffer::getFile(Path), "could not open " + Path);
MemoryBufferRef MBRef = MB->getMemBufferRef();
OwningMBs.push_back(std::move(MB)); // take ownership
return MBRef;
@@ -116,12 +118,16 @@ void LinkerDriver::parseDirectives(StringRef S) {
case OPT_nodefaultlib:
Config->NoDefaultLibs.insert(doFindLib(Arg->getValue()));
break;
+ case OPT_section:
+ parseSection(Arg->getValue());
+ break;
case OPT_editandcontinue:
+ case OPT_fastfail:
case OPT_guardsym:
case OPT_throwingnew:
break;
default:
- error(Twine(Arg->getSpelling()) + " is not allowed in .drectve");
+ fatal(Arg->getSpelling() + " is not allowed in .drectve");
}
}
}
@@ -246,7 +252,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// We call our own implementation of lib.exe that understands bitcode files.
if (ArgsArr.size() > 1 && StringRef(ArgsArr[1]).equals_lower("/lib")) {
if (llvm::libDriverMain(ArgsArr.slice(1)) != 0)
- error("lib failed");
+ fatal("lib failed");
return;
}
@@ -268,7 +274,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
}
if (Args.filtered_begin(OPT_INPUT) == Args.filtered_end())
- error("no input files.");
+ fatal("no input files");
// Construct search path list.
SearchPaths.push_back("");
@@ -295,7 +301,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// Handle /noentry
if (Args.hasArg(OPT_noentry)) {
if (!Args.hasArg(OPT_dll))
- error("/noentry must be specified with /dll");
+ fatal("/noentry must be specified with /dll");
Config->NoEntry = true;
}
@@ -308,7 +314,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// Handle /fixed
if (Args.hasArg(OPT_fixed)) {
if (Args.hasArg(OPT_dynamicbase))
- error("/fixed must not be specified with /dynamicbase");
+ fatal("/fixed must not be specified with /dynamicbase");
Config->Relocatable = false;
Config->DynamicBase = false;
}
@@ -382,17 +388,17 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
StringRef OptLevel = StringRef(S).substr(7);
if (OptLevel.getAsInteger(10, Config->LTOOptLevel) ||
Config->LTOOptLevel > 3)
- error("/opt:lldlto: invalid optimization level: " + OptLevel);
+ fatal("/opt:lldlto: invalid optimization level: " + OptLevel);
continue;
}
if (StringRef(S).startswith("lldltojobs=")) {
StringRef Jobs = StringRef(S).substr(11);
if (Jobs.getAsInteger(10, Config->LTOJobs) || Config->LTOJobs == 0)
- error("/opt:lldltojobs: invalid job count: " + Jobs);
+ fatal("/opt:lldltojobs: invalid job count: " + Jobs);
continue;
}
if (S != "ref" && S != "lbr" && S != "nolbr")
- error(Twine("/opt: unknown option: ") + S);
+ fatal("/opt: unknown option: " + S);
}
}
@@ -404,6 +410,10 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
for (auto *Arg : Args.filtered(OPT_merge))
parseMerge(Arg->getValue());
+ // Handle /section
+ for (auto *Arg : Args.filtered(OPT_section))
+ parseSection(Arg->getValue());
+
// Handle /manifest
if (auto *Arg = Args.getLastArg(OPT_manifest_colon))
parseManifest(Arg->getValue());
@@ -420,6 +430,10 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
if (auto *Arg = Args.getLastArg(OPT_manifestfile))
Config->ManifestFile = Arg->getValue();
+ // Handle /manifestinput
+ for (auto *Arg : Args.filtered(OPT_manifestinput))
+ Config->ManifestInput.push_back(Arg->getValue());
+
// Handle miscellaneous boolean flags.
if (Args.hasArg(OPT_allowbind_no))
Config->AllowBind = false;
@@ -485,7 +499,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
continue;
}
if (Config->Machine != MT)
- error(Twine(File->getShortName()) + ": machine type " + machineToStr(MT) +
+ fatal(File->getShortName() + ": machine type " + machineToStr(MT) +
" conflicts with " + machineToStr(Config->Machine));
}
if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) {
@@ -520,7 +534,7 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
// infer that from user-defined entry name.
StringRef S = findDefaultEntry();
if (S.empty())
- error("entry point must be defined");
+ fatal("entry point must be defined");
Config->Entry = addUndefined(S);
if (Config->Verbose)
llvm::outs() << "Entry name inferred: " << S << "\n";
@@ -627,14 +641,14 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) {
Config->Subsystem = inferSubsystem();
if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN)
- error("subsystem must be defined");
+ fatal("subsystem must be defined");
}
// Handle /safeseh.
if (Args.hasArg(OPT_safeseh))
for (ObjectFile *File : Symtab.ObjectFiles)
if (!File->SEHCompat)
- error("/safeseh: " + File->getName() + " is not compatible with SEH");
+ fatal("/safeseh: " + File->getName() + " is not compatible with SEH");
// Windows specific -- when we are creating a .dll file, we also
// need to create a .lib file.
@@ -668,7 +682,8 @@ void LinkerDriver::link(llvm::ArrayRef<const char *> ArgsArr) {
if (auto *Arg = Args.getLastArg(OPT_lldmap)) {
std::error_code EC;
llvm::raw_fd_ostream Out(Arg->getValue(), EC, OpenFlags::F_Text);
- error(EC, "Could not create the symbol map");
+ if (EC)
+ fatal(EC, "could not create the symbol map");
Symtab.printMap(Out);
}
// Call exit to avoid calling destructors.
diff --git a/COFF/Driver.h b/COFF/Driver.h
index e50da20cbb04..23969ee802fb 100644
--- a/COFF/Driver.h
+++ b/COFF/Driver.h
@@ -34,9 +34,6 @@ using llvm::COFF::WindowsSubsystem;
using llvm::Optional;
class InputFile;
-// Entry point of the COFF linker.
-void link(llvm::ArrayRef<const char *> Args);
-
// Implemented in MarkLive.cpp.
void markLive(const std::vector<Chunk *> &Chunks);
@@ -136,6 +133,7 @@ void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major,
void parseAlternateName(StringRef);
void parseMerge(StringRef);
+void parseSection(StringRef);
// Parses a string in the form of "EMBED[,=<integer>]|NO".
void parseManifest(StringRef Arg);
@@ -163,7 +161,6 @@ void checkFailIfMismatch(StringRef Arg);
std::unique_ptr<MemoryBuffer>
convertResToCOFF(const std::vector<MemoryBufferRef> &MBs);
-void touchFile(StringRef Path);
void createPDB(StringRef Path);
// Create enum with OPT_xxx values for each option in Options.td
diff --git a/COFF/DriverUtils.cpp b/COFF/DriverUtils.cpp
index 014fee7fefd7..5d7dc2bc65af 100644
--- a/COFF/DriverUtils.cpp
+++ b/COFF/DriverUtils.cpp
@@ -19,15 +19,12 @@
#include "Symbols.h"
#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringSwitch.h"
-#include "llvm/Object/Archive.h"
-#include "llvm/Object/ArchiveWriter.h"
#include "llvm/Object/COFF.h"
#include "llvm/Option/Arg.h"
#include "llvm/Option/ArgList.h"
#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileUtilities.h"
-#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/Program.h"
#include "llvm/Support/raw_ostream.h"
@@ -53,7 +50,8 @@ public:
void run() {
ErrorOr<std::string> ExeOrErr = llvm::sys::findProgramByName(Prog);
- error(ExeOrErr, Twine("unable to find ") + Prog + " in PATH: ");
+ if (auto EC = ExeOrErr.getError())
+ fatal(EC, "unable to find " + Prog + " in PATH: ");
const char *Exe = Saver.save(*ExeOrErr);
Args.insert(Args.begin(), Exe);
Args.push_back(nullptr);
@@ -61,7 +59,7 @@ public:
for (const char *S : Args)
if (S)
llvm::errs() << S << " ";
- error("failed");
+ fatal("ExecuteAndWait failed");
}
}
@@ -85,7 +83,7 @@ MachineTypes getMachineType(StringRef S) {
.Default(IMAGE_FILE_MACHINE_UNKNOWN);
if (MT != IMAGE_FILE_MACHINE_UNKNOWN)
return MT;
- error(Twine("unknown /machine argument: ") + S);
+ fatal("unknown /machine argument: " + S);
}
StringRef machineToStr(MachineTypes MT) {
@@ -106,9 +104,9 @@ void parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size) {
StringRef S1, S2;
std::tie(S1, S2) = Arg.split(',');
if (S1.getAsInteger(0, *Addr))
- error(Twine("invalid number: ") + S1);
+ fatal("invalid number: " + S1);
if (Size && !S2.empty() && S2.getAsInteger(0, *Size))
- error(Twine("invalid number: ") + S2);
+ fatal("invalid number: " + S2);
}
// Parses a string in the form of "<integer>[.<integer>]".
@@ -117,10 +115,10 @@ void parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor) {
StringRef S1, S2;
std::tie(S1, S2) = Arg.split('.');
if (S1.getAsInteger(0, *Major))
- error(Twine("invalid number: ") + S1);
+ fatal("invalid number: " + S1);
*Minor = 0;
if (!S2.empty() && S2.getAsInteger(0, *Minor))
- error(Twine("invalid number: ") + S2);
+ fatal("invalid number: " + S2);
}
// Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".
@@ -140,7 +138,7 @@ void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major,
.Case("windows", IMAGE_SUBSYSTEM_WINDOWS_GUI)
.Default(IMAGE_SUBSYSTEM_UNKNOWN);
if (*Sys == IMAGE_SUBSYSTEM_UNKNOWN)
- error(Twine("unknown subsystem: ") + SysStr);
+ fatal("unknown subsystem: " + SysStr);
if (!Ver.empty())
parseVersion(Ver, Major, Minor);
}
@@ -151,10 +149,10 @@ void parseAlternateName(StringRef S) {
StringRef From, To;
std::tie(From, To) = S.split('=');
if (From.empty() || To.empty())
- error(Twine("/alternatename: invalid argument: ") + S);
+ fatal("/alternatename: invalid argument: " + S);
auto It = Config->AlternateNames.find(From);
if (It != Config->AlternateNames.end() && It->second != To)
- error(Twine("/alternatename: conflicts: ") + S);
+ fatal("/alternatename: conflicts: " + S);
Config->AlternateNames.insert(It, std::make_pair(From, To));
}
@@ -164,7 +162,7 @@ void parseMerge(StringRef S) {
StringRef From, To;
std::tie(From, To) = S.split('=');
if (From.empty() || To.empty())
- error(Twine("/merge: invalid argument: ") + S);
+ fatal("/merge: invalid argument: " + S);
auto Pair = Config->Merge.insert(std::make_pair(From, To));
bool Inserted = Pair.second;
if (!Inserted) {
@@ -175,6 +173,47 @@ void parseMerge(StringRef S) {
}
}
+static uint32_t parseSectionAttributes(StringRef S) {
+ uint32_t Ret = 0;
+ for (char C : S.lower()) {
+ switch (C) {
+ case 'd':
+ Ret |= IMAGE_SCN_MEM_DISCARDABLE;
+ break;
+ case 'e':
+ Ret |= IMAGE_SCN_MEM_EXECUTE;
+ break;
+ case 'k':
+ Ret |= IMAGE_SCN_MEM_NOT_CACHED;
+ break;
+ case 'p':
+ Ret |= IMAGE_SCN_MEM_NOT_PAGED;
+ break;
+ case 'r':
+ Ret |= IMAGE_SCN_MEM_READ;
+ break;
+ case 's':
+ Ret |= IMAGE_SCN_MEM_SHARED;
+ break;
+ case 'w':
+ Ret |= IMAGE_SCN_MEM_WRITE;
+ break;
+ default:
+ fatal("/section: invalid argument: " + S);
+ }
+ }
+ return Ret;
+}
+
+// Parses /section option argument.
+void parseSection(StringRef S) {
+ StringRef Name, Attrs;
+ std::tie(Name, Attrs) = S.split(',');
+ if (Name.empty() || Attrs.empty())
+ fatal("/section: invalid argument: " + S);
+ Config->Section[Name] = parseSectionAttributes(Attrs);
+}
+
// Parses a string in the form of "EMBED[,=<integer>]|NO".
// Results are directly written to Config.
void parseManifest(StringRef Arg) {
@@ -183,16 +222,16 @@ void parseManifest(StringRef Arg) {
return;
}
if (!Arg.startswith_lower("embed"))
- error(Twine("Invalid option ") + Arg);
+ fatal("invalid option " + Arg);
Config->Manifest = Configuration::Embed;
Arg = Arg.substr(strlen("embed"));
if (Arg.empty())
return;
if (!Arg.startswith_lower(",id="))
- error(Twine("Invalid option ") + Arg);
+ fatal("invalid option " + Arg);
Arg = Arg.substr(strlen(",id="));
if (Arg.getAsInteger(0, Config->ManifestID))
- error(Twine("Invalid option ") + Arg);
+ fatal("invalid option " + Arg);
}
// Parses a string in the form of "level=<string>|uiAccess=<string>|NO".
@@ -216,7 +255,7 @@ void parseManifestUAC(StringRef Arg) {
std::tie(Config->ManifestUIAccess, Arg) = Arg.split(" ");
continue;
}
- error(Twine("Invalid option ") + Arg);
+ fatal("invalid option " + Arg);
}
}
@@ -240,10 +279,19 @@ static void quoteAndPrint(raw_ostream &Out, StringRef S) {
}
}
-// Create a manifest file contents.
-static std::string createManifestXml() {
- std::string S;
- llvm::raw_string_ostream OS(S);
+// Create the default manifest file as a temporary file.
+static std::string createDefaultXml() {
+ // Create a temporary file.
+ SmallString<128> Path;
+ if (auto EC = sys::fs::createTemporaryFile("tmp", "manifest", Path))
+ fatal(EC, "cannot create a temporary file");
+
+ // Open the temporary file for writing.
+ std::error_code EC;
+ llvm::raw_fd_ostream OS(Path, EC, sys::fs::F_Text);
+ if (EC)
+ fatal(EC, "failed to open " + Path);
+
// Emit the XML. Note that we do *not* verify that the XML attributes are
// syntactically correct. This is intentional for link.exe compatibility.
OS << "<?xml version=\"1.0\" standalone=\"yes\"?>\n"
@@ -267,21 +315,57 @@ static std::string createManifestXml() {
}
}
OS << "</assembly>\n";
- OS.flush();
- return S;
+ OS.close();
+ return StringRef(Path);
+}
+
+static std::string readFile(StringRef Path) {
+ std::unique_ptr<MemoryBuffer> MB =
+ check(MemoryBuffer::getFile(Path), "could not open " + Path);
+ std::unique_ptr<MemoryBuffer> Buf(std::move(MB));
+ return Buf->getBuffer();
+}
+
+static std::string createManifestXml() {
+ // Create the default manifest file.
+ std::string Path1 = createDefaultXml();
+ if (Config->ManifestInput.empty())
+ return readFile(Path1);
+
+ // If manifest files are supplied by the user using /MANIFESTINPUT
+ // option, we need to merge them with the default manifest.
+ SmallString<128> Path2;
+ if (auto EC = sys::fs::createTemporaryFile("tmp", "manifest", Path2))
+ fatal(EC, "cannot create a temporary file");
+ FileRemover Remover1(Path1);
+ FileRemover Remover2(Path2);
+
+ Executor E("mt.exe");
+ E.add("/manifest");
+ E.add(Path1);
+ for (StringRef Filename : Config->ManifestInput) {
+ E.add("/manifest");
+ E.add(Filename);
+ }
+ E.add("/nologo");
+ E.add("/out:" + StringRef(Path2));
+ E.run();
+ return readFile(Path2);
}
// Create a resource file containing a manifest XML.
std::unique_ptr<MemoryBuffer> createManifestRes() {
// Create a temporary file for the resource script file.
SmallString<128> RCPath;
- std::error_code EC = sys::fs::createTemporaryFile("tmp", "rc", RCPath);
- error(EC, "cannot create a temporary file");
+ if (auto EC = sys::fs::createTemporaryFile("tmp", "rc", RCPath))
+ fatal(EC, "cannot create a temporary file");
FileRemover RCRemover(RCPath);
// Open the temporary file for writing.
+ std::error_code EC;
llvm::raw_fd_ostream Out(RCPath, EC, sys::fs::F_Text);
- error(EC, Twine("failed to open ") + RCPath);
+ if (EC)
+ fatal(EC, "failed to open " + RCPath);
// Write resource script to the RC file.
Out << "#define LANG_ENGLISH 9\n"
@@ -296,8 +380,8 @@ std::unique_ptr<MemoryBuffer> createManifestRes() {
// Create output resource file.
SmallString<128> ResPath;
- EC = sys::fs::createTemporaryFile("tmp", "res", ResPath);
- error(EC, "cannot create a temporary file");
+ if (auto EC = sys::fs::createTemporaryFile("tmp", "res", ResPath))
+ fatal(EC, "cannot create a temporary file");
Executor E("rc.exe");
E.add("/fo");
@@ -305,18 +389,17 @@ std::unique_ptr<MemoryBuffer> createManifestRes() {
E.add("/nologo");
E.add(RCPath.str());
E.run();
- ErrorOr<std::unique_ptr<MemoryBuffer>> Ret = MemoryBuffer::getFile(ResPath);
- error(Ret, Twine("Could not open ") + ResPath);
- return std::move(*Ret);
+ return check(MemoryBuffer::getFile(ResPath), "could not open " + ResPath);
}
void createSideBySideManifest() {
std::string Path = Config->ManifestFile;
if (Path == "")
- Path = (Twine(Config->OutputFile) + ".manifest").str();
+ Path = Config->OutputFile + ".manifest";
std::error_code EC;
llvm::raw_fd_ostream Out(Path, EC, llvm::sys::fs::F_Text);
- error(EC, "failed to create manifest");
+ if (EC)
+ fatal(EC, "failed to create manifest");
Out << createManifestXml();
}
@@ -380,7 +463,7 @@ Export parseExport(StringRef Arg) {
return E;
err:
- error(Twine("invalid /export: ") + Arg);
+ fatal("invalid /export: " + Arg);
}
static StringRef undecorate(StringRef Sym) {
@@ -398,7 +481,7 @@ void fixupExports() {
if (E.Ordinal == 0)
continue;
if (!Ords.insert(E.Ordinal).second)
- error("duplicate export ordinal: " + E.Name);
+ fatal("duplicate export ordinal: " + E.Name);
}
for (Export &E : Config->Exports) {
@@ -459,11 +542,11 @@ void checkFailIfMismatch(StringRef Arg) {
StringRef K, V;
std::tie(K, V) = Arg.split('=');
if (K.empty() || V.empty())
- error(Twine("/failifmismatch: invalid argument: ") + Arg);
+ fatal("/failifmismatch: invalid argument: " + Arg);
StringRef Existing = Config->MustMatch[K];
if (!Existing.empty() && V != Existing)
- error(Twine("/failifmismatch: mismatch detected: ") + Existing + " and " +
- V + " for key " + K);
+ fatal("/failifmismatch: mismatch detected: " + Existing + " and " + V +
+ " for key " + K);
Config->MustMatch[K] = V;
}
@@ -473,8 +556,8 @@ std::unique_ptr<MemoryBuffer>
convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) {
// Create an output file path.
SmallString<128> Path;
- if (llvm::sys::fs::createTemporaryFile("resource", "obj", Path))
- error("Could not create temporary file");
+ if (auto EC = llvm::sys::fs::createTemporaryFile("resource", "obj", Path))
+ fatal(EC, "could not create temporary file");
// Execute cvtres.exe.
Executor E("cvtres.exe");
@@ -485,170 +568,7 @@ convertResToCOFF(const std::vector<MemoryBufferRef> &MBs) {
for (MemoryBufferRef MB : MBs)
E.add(MB.getBufferIdentifier());
E.run();
- ErrorOr<std::unique_ptr<MemoryBuffer>> Ret = MemoryBuffer::getFile(Path);
- error(Ret, Twine("Could not open ") + Path);
- return std::move(*Ret);
-}
-
-static std::string writeToTempFile(StringRef Contents) {
- SmallString<128> Path;
- int FD;
- if (llvm::sys::fs::createTemporaryFile("tmp", "def", FD, Path)) {
- llvm::errs() << "failed to create a temporary file\n";
- return "";
- }
- llvm::raw_fd_ostream OS(FD, /*shouldClose*/ true);
- OS << Contents;
- return Path.str();
-}
-
-void touchFile(StringRef Path) {
- int FD;
- std::error_code EC = sys::fs::openFileForWrite(Path, FD, sys::fs::F_Append);
- error(EC, "failed to create a file");
- sys::Process::SafelyCloseFileDescriptor(FD);
-}
-
-static std::string getImplibPath() {
- if (!Config->Implib.empty())
- return Config->Implib;
- SmallString<128> Out = StringRef(Config->OutputFile);
- sys::path::replace_extension(Out, ".lib");
- return Out.str();
-}
-
-static std::unique_ptr<MemoryBuffer> createEmptyImportLibrary() {
- std::string S = (Twine("LIBRARY \"") +
- llvm::sys::path::filename(Config->OutputFile) + "\"\n")
- .str();
- std::string Path1 = writeToTempFile(S);
- std::string Path2 = getImplibPath();
- llvm::FileRemover Remover1(Path1);
- llvm::FileRemover Remover2(Path2);
-
- Executor E("lib.exe");
- E.add("/nologo");
- E.add("/machine:" + machineToStr(Config->Machine));
- E.add(Twine("/def:") + Path1);
- E.add(Twine("/out:") + Path2);
- E.run();
-
- ErrorOr<std::unique_ptr<MemoryBuffer>> BufOrErr =
- MemoryBuffer::getFile(Path2, -1, false);
- error(BufOrErr, Twine("Failed to open ") + Path2);
- return MemoryBuffer::getMemBufferCopy((*BufOrErr)->getBuffer());
-}
-
-static std::vector<NewArchiveIterator>
-readMembers(const object::Archive &Archive) {
- std::vector<NewArchiveIterator> V;
- for (const auto &ChildOrErr : Archive.children()) {
- error(ChildOrErr, "Archive::Child::getName failed");
- const object::Archive::Child C(*ChildOrErr);
- ErrorOr<StringRef> NameOrErr = C.getName();
- error(NameOrErr, "Archive::Child::getName failed");
- V.emplace_back(C, *NameOrErr);
- }
- return V;
-}
-
-// This class creates short import files which is described in
-// PE/COFF spec 7. Import Library Format.
-class ShortImportCreator {
-public:
- ShortImportCreator(object::Archive *A, StringRef S) : Parent(A), DLLName(S) {}
-
- NewArchiveIterator create(StringRef Sym, uint16_t Ordinal,
- ImportNameType NameType, bool isData) {
- size_t ImpSize = DLLName.size() + Sym.size() + 2; // +2 for NULs
- size_t Size = sizeof(object::ArchiveMemberHeader) +
- sizeof(coff_import_header) + ImpSize;
- char *Buf = Alloc.Allocate<char>(Size);
- memset(Buf, 0, Size);
- char *P = Buf;
-
- // Write archive member header
- auto *Hdr = reinterpret_cast<object::ArchiveMemberHeader *>(P);
- P += sizeof(*Hdr);
- sprintf(Hdr->Name, "%-12s", "dummy");
- sprintf(Hdr->LastModified, "%-12d", 0);
- sprintf(Hdr->UID, "%-6d", 0);
- sprintf(Hdr->GID, "%-6d", 0);
- sprintf(Hdr->AccessMode, "%-8d", 0644);
- sprintf(Hdr->Size, "%-10d", int(sizeof(coff_import_header) + ImpSize));
-
- // Write short import library.
- auto *Imp = reinterpret_cast<coff_import_header *>(P);
- P += sizeof(*Imp);
- Imp->Sig2 = 0xFFFF;
- Imp->Machine = Config->Machine;
- Imp->SizeOfData = ImpSize;
- if (Ordinal > 0)
- Imp->OrdinalHint = Ordinal;
- Imp->TypeInfo = (isData ? IMPORT_DATA : IMPORT_CODE);
- Imp->TypeInfo |= NameType << 2;
-
- // Write symbol name and DLL name.
- memcpy(P, Sym.data(), Sym.size());
- P += Sym.size() + 1;
- memcpy(P, DLLName.data(), DLLName.size());
-
- std::error_code EC;
- object::Archive::Child C(Parent, Buf, &EC);
- assert(!EC && "We created an invalid buffer");
- return NewArchiveIterator(C, DLLName);
- }
-
-private:
- BumpPtrAllocator Alloc;
- object::Archive *Parent;
- StringRef DLLName;
-};
-
-static ImportNameType getNameType(StringRef Sym, StringRef ExtName) {
- if (Sym != ExtName)
- return IMPORT_NAME_UNDECORATE;
- if (Config->Machine == I386 && Sym.startswith("_"))
- return IMPORT_NAME_NOPREFIX;
- return IMPORT_NAME;
-}
-
-static std::string replace(StringRef S, StringRef From, StringRef To) {
- size_t Pos = S.find(From);
- assert(Pos != StringRef::npos);
- return (Twine(S.substr(0, Pos)) + To + S.substr(Pos + From.size())).str();
-}
-
-// Creates an import library for a DLL. In this function, we first
-// create an empty import library using lib.exe and then adds short
-// import files to that file.
-void writeImportLibrary() {
- std::unique_ptr<MemoryBuffer> Buf = createEmptyImportLibrary();
- std::error_code EC;
- object::Archive Archive(Buf->getMemBufferRef(), EC);
- error(EC, "Error reading an empty import file");
- std::vector<NewArchiveIterator> Members = readMembers(Archive);
-
- std::string DLLName = llvm::sys::path::filename(Config->OutputFile);
- ShortImportCreator ShortImport(&Archive, DLLName);
- for (Export &E : Config->Exports) {
- if (E.Private)
- continue;
- if (E.ExtName.empty()) {
- Members.push_back(ShortImport.create(
- E.SymbolName, E.Ordinal, getNameType(E.SymbolName, E.Name), E.Data));
- } else {
- Members.push_back(ShortImport.create(
- replace(E.SymbolName, E.Name, E.ExtName), E.Ordinal,
- getNameType(E.SymbolName, E.Name), E.Data));
- }
- }
-
- std::string Path = getImplibPath();
- std::pair<StringRef, std::error_code> Result =
- writeArchive(Path, Members, /*WriteSymtab*/ true, object::Archive::K_GNU,
- /*Deterministic*/ true, /*Thin*/ false);
- error(Result.second, Twine("Failed to write ") + Path);
+ return check(MemoryBuffer::getFile(Path), "could not open " + Path);
}
// Create OptTable
@@ -695,7 +615,7 @@ llvm::opt::InputArgList ArgParser::parse(ArrayRef<const char *> ArgsArr) {
}
if (MissingCount)
- error(Twine("missing arg value for \"") + Args.getArgString(MissingIndex) +
+ fatal("missing arg value for \"" + Twine(Args.getArgString(MissingIndex)) +
"\", expected " + Twine(MissingCount) +
(MissingCount == 1 ? " argument." : " arguments."));
for (auto *Arg : Args.filtered(OPT_UNKNOWN))
diff --git a/COFF/Error.cpp b/COFF/Error.cpp
index 255d9bbad9d8..602a8544ce2b 100644
--- a/COFF/Error.cpp
+++ b/COFF/Error.cpp
@@ -10,20 +10,23 @@
#include "Error.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
namespace lld {
namespace coff {
-void error(const Twine &Msg) {
+void fatal(const Twine &Msg) {
llvm::errs() << Msg << "\n";
exit(1);
}
-void error(std::error_code EC, const Twine &Prefix) {
- if (!EC)
- return;
- error(Prefix + ": " + EC.message());
+void fatal(std::error_code EC, const Twine &Msg) {
+ fatal(Msg + ": " + EC.message());
+}
+
+void fatal(llvm::Error &Err, const Twine &Msg) {
+ fatal(errorToErrorCode(std::move(Err)), Msg);
}
} // namespace coff
diff --git a/COFF/Error.h b/COFF/Error.h
index cb0a185f0917..c9f64c662580 100644
--- a/COFF/Error.h
+++ b/COFF/Error.h
@@ -11,15 +11,25 @@
#define LLD_COFF_ERROR_H
#include "lld/Core/LLVM.h"
+#include "llvm/Support/Error.h"
namespace lld {
namespace coff {
-LLVM_ATTRIBUTE_NORETURN void error(const Twine &Msg);
-void error(std::error_code EC, const Twine &Prefix);
+LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);
+LLVM_ATTRIBUTE_NORETURN void fatal(std::error_code EC, const Twine &Prefix);
+LLVM_ATTRIBUTE_NORETURN void fatal(llvm::Error &Err, const Twine &Prefix);
-template <typename T> void error(const ErrorOr<T> &V, const Twine &Prefix) {
- error(V.getError(), Prefix);
+template <class T> T check(ErrorOr<T> &&V, const Twine &Prefix) {
+ if (auto EC = V.getError())
+ fatal(EC, Prefix);
+ return std::move(*V);
+}
+
+template <class T> T check(Expected<T> E, const Twine &Prefix) {
+ if (llvm::Error Err = E.takeError())
+ fatal(Err, Prefix);
+ return std::move(*E);
}
} // namespace coff
diff --git a/COFF/ICF.cpp b/COFF/ICF.cpp
index f99b41624a84..a2c5a90334d0 100644
--- a/COFF/ICF.cpp
+++ b/COFF/ICF.cpp
@@ -70,7 +70,7 @@ private:
static bool equalsConstant(const SectionChunk *A, const SectionChunk *B);
static bool equalsVariable(const SectionChunk *A, const SectionChunk *B);
bool forEachGroup(std::vector<SectionChunk *> &Chunks, Comparator Eq);
- bool partition(ChunkIterator Begin, ChunkIterator End, Comparator Eq);
+ bool segregate(ChunkIterator Begin, ChunkIterator End, Comparator Eq);
std::atomic<uint64_t> NextID = { 1 };
};
@@ -148,7 +148,7 @@ bool ICF::equalsVariable(const SectionChunk *A, const SectionChunk *B) {
return std::equal(A->Relocs.begin(), A->Relocs.end(), B->Relocs.begin(), Eq);
}
-bool ICF::partition(ChunkIterator Begin, ChunkIterator End, Comparator Eq) {
+bool ICF::segregate(ChunkIterator Begin, ChunkIterator End, Comparator Eq) {
bool R = false;
for (auto It = Begin;;) {
SectionChunk *Head = *It;
@@ -171,7 +171,7 @@ bool ICF::forEachGroup(std::vector<SectionChunk *> &Chunks, Comparator Eq) {
auto Bound = std::find_if(It + 1, End, [&](SectionChunk *SC) {
return SC->GroupID != Head->GroupID;
});
- if (partition(It, Bound, Eq))
+ if (segregate(It, Bound, Eq))
R = true;
It = Bound;
}
diff --git a/COFF/InputFiles.cpp b/COFF/InputFiles.cpp
index 23af1e89c34d..ff26826371fa 100644
--- a/COFF/InputFiles.cpp
+++ b/COFF/InputFiles.cpp
@@ -8,30 +8,41 @@
//===----------------------------------------------------------------------===//
#include "Chunks.h"
+#include "Config.h"
#include "Error.h"
#include "InputFiles.h"
#include "Symbols.h"
-#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
#include "llvm/IR/LLVMContext.h"
-#include "llvm/LTO/LTOModule.h"
+#include "llvm/LTO/legacy/LTOModule.h"
+#include "llvm/Object/Binary.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/COFF.h"
-#include "llvm/Support/Debug.h"
+#include "llvm/Support/Casting.h"
#include "llvm/Support/Endian.h"
-#include "llvm/Support/raw_ostream.h"
+#include "llvm/Support/Error.h"
+#include "llvm/Support/ErrorOr.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Target/TargetOptions.h"
+#include "llvm-c/lto.h"
+#include <cstring>
+#include <system_error>
+#include <utility>
using namespace llvm::COFF;
using namespace llvm::object;
using namespace llvm::support::endian;
+
using llvm::Triple;
using llvm::support::ulittle32_t;
-using llvm::sys::fs::file_magic;
-using llvm::sys::fs::identify_magic;
namespace lld {
namespace coff {
int InputFile::NextIndex = 0;
+llvm::LLVMContext BitcodeFile::Context;
// Returns the last element of a path, which is supposed to be a filename.
static StringRef getBasename(StringRef Path) {
@@ -52,9 +63,7 @@ std::string InputFile::getShortName() {
void ArchiveFile::parse() {
// Parse a MemoryBufferRef as an archive file.
- auto ArchiveOrErr = Archive::create(MB);
- error(ArchiveOrErr, "Failed to parse static library");
- File = std::move(*ArchiveOrErr);
+ File = check(Archive::create(MB), "failed to parse static library");
// Allocate a buffer for Lazy objects.
size_t NumSyms = File->getNumberOfSymbols();
@@ -67,40 +76,38 @@ void ArchiveFile::parse() {
// Seen is a map from member files to boolean values. Initially
// all members are mapped to false, which indicates all these files
// are not read yet.
- for (auto &ChildOrErr : File->children()) {
- error(ChildOrErr, "Failed to parse static library");
- const Archive::Child &Child = *ChildOrErr;
+ Error Err;
+ for (auto &Child : File->children(Err))
Seen[Child.getChildOffset()].clear();
- }
+ if (Err)
+ fatal(Err, "failed to parse static library");
}
// Returns a buffer pointing to a member file containing a given symbol.
// This function is thread-safe.
MemoryBufferRef ArchiveFile::getMember(const Archive::Symbol *Sym) {
- auto COrErr = Sym->getMember();
- error(COrErr, Twine("Could not get the member for symbol ") + Sym->getName());
- const Archive::Child &C = *COrErr;
+ const Archive::Child &C =
+ check(Sym->getMember(),
+ "could not get the member for symbol " + Sym->getName());
// Return an empty buffer if we have already returned the same buffer.
if (Seen[C.getChildOffset()].test_and_set())
return MemoryBufferRef();
- ErrorOr<MemoryBufferRef> Ret = C.getMemoryBufferRef();
- error(Ret, Twine("Could not get the buffer for the member defining symbol ") +
- Sym->getName());
- return *Ret;
+ return check(C.getMemoryBufferRef(),
+ "could not get the buffer for the member defining symbol " +
+ Sym->getName());
}
void ObjectFile::parse() {
// Parse a memory buffer as a COFF file.
- auto BinOrErr = createBinary(MB);
- error(BinOrErr, "Failed to parse object file");
- std::unique_ptr<Binary> Bin = std::move(*BinOrErr);
+ std::unique_ptr<Binary> Bin =
+ check(createBinary(MB), "failed to parse object file");
if (auto *Obj = dyn_cast<COFFObjectFile>(Bin.get())) {
Bin.release();
COFFObj.reset(Obj);
} else {
- error(Twine(getName()) + " is not a COFF file.");
+ fatal(getName() + " is not a COFF file");
}
// Read section and symbol tables.
@@ -116,10 +123,10 @@ void ObjectFile::initializeChunks() {
for (uint32_t I = 1; I < NumSections + 1; ++I) {
const coff_section *Sec;
StringRef Name;
- std::error_code EC = COFFObj->getSection(I, Sec);
- error(EC, Twine("getSection failed: #") + Twine(I));
- EC = COFFObj->getSectionName(Sec, Name);
- error(EC, Twine("getSectionName failed: #") + Twine(I));
+ if (auto EC = COFFObj->getSection(I, Sec))
+ fatal(EC, "getSection failed: #" + Twine(I));
+ if (auto EC = COFFObj->getSectionName(Sec, Name))
+ fatal(EC, "getSectionName failed: #" + Twine(I));
if (Name == ".sxdata") {
SXData = Sec;
continue;
@@ -149,14 +156,12 @@ void ObjectFile::initializeSymbols() {
uint32_t NumSymbols = COFFObj->getNumberOfSymbols();
SymbolBodies.reserve(NumSymbols);
SparseSymbolBodies.resize(NumSymbols);
- llvm::SmallVector<Undefined *, 8> WeakAliases;
+ llvm::SmallVector<std::pair<Undefined *, uint32_t>, 8> WeakAliases;
int32_t LastSectionNumber = 0;
for (uint32_t I = 0; I < NumSymbols; ++I) {
// Get a COFFSymbolRef object.
- auto SymOrErr = COFFObj->getSymbol(I);
- error(SymOrErr, Twine("broken object file: ") + getName());
-
- COFFSymbolRef Sym = *SymOrErr;
+ COFFSymbolRef Sym =
+ check(COFFObj->getSymbol(I), "broken object file: " + getName());
const void *AuxP = nullptr;
if (Sym.getNumberOfAuxSymbols())
@@ -167,8 +172,10 @@ void ObjectFile::initializeSymbols() {
if (Sym.isUndefined()) {
Body = createUndefined(Sym);
} else if (Sym.isWeakExternal()) {
- Body = createWeakExternal(Sym, AuxP);
- WeakAliases.push_back((Undefined *)Body);
+ Body = createUndefined(Sym);
+ uint32_t TagIndex =
+ static_cast<const coff_aux_weak_external *>(AuxP)->TagIndex;
+ WeakAliases.emplace_back((Undefined *)Body, TagIndex);
} else {
Body = createDefined(Sym, AuxP, IsFirst);
}
@@ -179,8 +186,8 @@ void ObjectFile::initializeSymbols() {
I += Sym.getNumberOfAuxSymbols();
LastSectionNumber = Sym.getSectionNumber();
}
- for (Undefined *U : WeakAliases)
- U->WeakAlias = SparseSymbolBodies[(uintptr_t)U->WeakAlias];
+ for (auto WeakAlias : WeakAliases)
+ WeakAlias.first->WeakAlias = SparseSymbolBodies[WeakAlias.second];
}
Undefined *ObjectFile::createUndefined(COFFSymbolRef Sym) {
@@ -189,15 +196,6 @@ Undefined *ObjectFile::createUndefined(COFFSymbolRef Sym) {
return new (Alloc) Undefined(Name);
}
-Undefined *ObjectFile::createWeakExternal(COFFSymbolRef Sym, const void *AuxP) {
- StringRef Name;
- COFFObj->getSymbolName(Sym, Name);
- auto *U = new (Alloc) Undefined(Name);
- auto *Aux = (const coff_aux_weak_external *)AuxP;
- U->WeakAlias = (Undefined *)(uintptr_t)Aux->TagIndex;
- return U;
-}
-
Defined *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP,
bool IsFirst) {
StringRef Name;
@@ -219,11 +217,21 @@ Defined *ObjectFile::createDefined(COFFSymbolRef Sym, const void *AuxP,
}
return new (Alloc) DefinedAbsolute(Name, Sym);
}
- if (Sym.getSectionNumber() == llvm::COFF::IMAGE_SYM_DEBUG)
+ int32_t SectionNumber = Sym.getSectionNumber();
+ if (SectionNumber == llvm::COFF::IMAGE_SYM_DEBUG)
return nullptr;
+ // Reserved sections numbers don't have contents.
+ if (llvm::COFF::isReservedSectionNumber(SectionNumber))
+ fatal("broken object file: " + getName());
+
+ // This symbol references a section which is not present in the section
+ // header.
+ if ((uint32_t)SectionNumber >= SparseChunks.size())
+ fatal("broken object file: " + getName());
+
// Nothing else to do without a section chunk.
- auto *SC = cast_or_null<SectionChunk>(SparseChunks[Sym.getSectionNumber()]);
+ auto *SC = cast_or_null<SectionChunk>(SparseChunks[SectionNumber]);
if (!SC)
return nullptr;
@@ -250,7 +258,7 @@ void ObjectFile::initializeSEH() {
ArrayRef<uint8_t> A;
COFFObj->getSectionContents(SXData, A);
if (A.size() % 4 != 0)
- error(".sxdata must be an array of symbol table indices");
+ fatal(".sxdata must be an array of symbol table indices");
auto *I = reinterpret_cast<const ulittle32_t *>(A.data());
auto *E = reinterpret_cast<const ulittle32_t *>(A.data() + A.size());
for (; I != E; ++I)
@@ -276,11 +284,11 @@ void ImportFile::parse() {
// Check if the total size is valid.
if ((size_t)(End - Buf) != (sizeof(*Hdr) + Hdr->SizeOfData))
- error("broken import library");
+ fatal("broken import library");
// Read names and create an __imp_ symbol.
StringRef Name = StringAlloc.save(StringRef(Buf + sizeof(*Hdr)));
- StringRef ImpName = StringAlloc.save(Twine("__imp_") + Name);
+ StringRef ImpName = StringAlloc.save("__imp_" + Name);
const char *NameStart = Buf + sizeof(coff_import_header) + Name.size() + 1;
DLLName = StringRef(NameStart);
StringRef ExtName;
@@ -315,11 +323,10 @@ void BitcodeFile::parse() {
// Usually parse() is thread-safe, but bitcode file is an exception.
std::lock_guard<std::mutex> Lock(Mu);
- ErrorOr<std::unique_ptr<LTOModule>> ModOrErr =
- LTOModule::createFromBuffer(llvm::getGlobalContext(), MB.getBufferStart(),
- MB.getBufferSize(), llvm::TargetOptions());
- error(ModOrErr, "Could not create lto module");
- M = std::move(*ModOrErr);
+ Context.enableDebugTypeODRUniquing();
+ ErrorOr<std::unique_ptr<LTOModule>> ModOrErr = LTOModule::createFromBuffer(
+ Context, MB.getBufferStart(), MB.getBufferSize(), llvm::TargetOptions());
+ M = check(std::move(ModOrErr), "could not create LTO module");
llvm::StringSaver Saver(Alloc);
for (unsigned I = 0, E = M->getSymbolCount(); I != E; ++I) {
diff --git a/COFF/InputFiles.h b/COFF/InputFiles.h
index 6a263fbaddf6..0ec01b5075f9 100644
--- a/COFF/InputFiles.h
+++ b/COFF/InputFiles.h
@@ -12,7 +12,8 @@
#include "lld/Core/LLVM.h"
#include "llvm/ADT/ArrayRef.h"
-#include "llvm/LTO/LTOModule.h"
+#include "llvm/IR/LLVMContext.h"
+#include "llvm/LTO/legacy/LTOModule.h"
#include "llvm/Object/Archive.h"
#include "llvm/Object/COFF.h"
#include "llvm/Support/StringSaver.h"
@@ -103,7 +104,7 @@ public:
// All symbols returned by ArchiveFiles are of Lazy type.
std::vector<SymbolBody *> &getSymbols() override {
- llvm_unreachable("internal error");
+ llvm_unreachable("internal fatal");
}
private:
@@ -147,7 +148,6 @@ private:
Defined *createDefined(COFFSymbolRef Sym, const void *Aux, bool IsFirst);
Undefined *createUndefined(COFFSymbolRef Sym);
- Undefined *createWeakExternal(COFFSymbolRef Sym, const void *Aux);
std::unique_ptr<COFFObjectFile> COFFObj;
llvm::BumpPtrAllocator Alloc;
@@ -204,9 +204,10 @@ public:
static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; }
std::vector<SymbolBody *> &getSymbols() override { return SymbolBodies; }
MachineTypes getMachineType() override;
-
std::unique_ptr<LTOModule> takeModule() { return std::move(M); }
+ static llvm::LLVMContext Context;
+
private:
void parse() override;
diff --git a/COFF/Librarian.cpp b/COFF/Librarian.cpp
new file mode 100644
index 000000000000..25fb4a87b3eb
--- /dev/null
+++ b/COFF/Librarian.cpp
@@ -0,0 +1,489 @@
+//===- Librarian.cpp ------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file contains functions for the Librarian. The librarian creates and
+// manages libraries of the Common Object File Format (COFF) object files. It
+// primarily is used for creating static libraries and import libraries.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Config.h"
+#include "Driver.h"
+#include "Error.h"
+#include "Symbols.h"
+#include "llvm/Object/Archive.h"
+#include "llvm/Object/ArchiveWriter.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/Path.h"
+
+#include <vector>
+
+using namespace lld::coff;
+using namespace llvm::COFF;
+using namespace llvm::object;
+using namespace llvm;
+
+static bool is32bit() {
+ switch (Config->Machine) {
+ default:
+ llvm_unreachable("unsupported machine");
+ case IMAGE_FILE_MACHINE_AMD64:
+ return false;
+ case IMAGE_FILE_MACHINE_ARMNT:
+ case IMAGE_FILE_MACHINE_I386:
+ return true;
+ }
+}
+
+static uint16_t getImgRelRelocation() {
+ switch (Config->Machine) {
+ default:
+ llvm_unreachable("unsupported machine");
+ case IMAGE_FILE_MACHINE_AMD64:
+ return IMAGE_REL_AMD64_ADDR32NB;
+ case IMAGE_FILE_MACHINE_ARMNT:
+ return IMAGE_REL_ARM_ADDR32NB;
+ case IMAGE_FILE_MACHINE_I386:
+ return IMAGE_REL_I386_DIR32NB;
+ }
+}
+
+template <class T> void append(std::vector<uint8_t> &B, const T &Data) {
+ size_t S = B.size();
+ B.resize(S + sizeof(T));
+ memcpy(&B[S], &Data, sizeof(T));
+}
+
+static void writeStringTable(std::vector<uint8_t> &B,
+ ArrayRef<const std::string> Strings) {
+ // The COFF string table consists of a 4-byte value which is the size of the
+ // table, including the length field itself. This value is followed by the
+ // string content itself, which is an array of null-terminated C-style
+ // strings. The termination is important as they are referenced to by offset
+ // by the symbol entity in the file format.
+
+ std::vector<uint8_t>::size_type Pos = B.size();
+ std::vector<uint8_t>::size_type Offset = B.size();
+
+ // Skip over the length field, we will fill it in later as we will have
+ // computed the length while emitting the string content itself.
+ Pos += sizeof(uint32_t);
+
+ for (const auto &S : Strings) {
+ B.resize(Pos + S.length() + 1);
+ strcpy(reinterpret_cast<char *>(&B[Pos]), S.c_str());
+ Pos += S.length() + 1;
+ }
+
+ // Backfill the length of the table now that it has been computed.
+ support::ulittle32_t Length(B.size() - Offset);
+ memcpy(&B[Offset], &Length, sizeof(Length));
+}
+
+static std::string getImplibPath() {
+ if (!Config->Implib.empty())
+ return Config->Implib;
+ SmallString<128> Out = StringRef(Config->OutputFile);
+ sys::path::replace_extension(Out, ".lib");
+ return Out.str();
+}
+
+static ImportNameType getNameType(StringRef Sym, StringRef ExtName) {
+ if (Sym != ExtName)
+ return IMPORT_NAME_UNDECORATE;
+ if (Config->Machine == I386 && Sym.startswith("_"))
+ return IMPORT_NAME_NOPREFIX;
+ return IMPORT_NAME;
+}
+
+static std::string replace(StringRef S, StringRef From, StringRef To) {
+ size_t Pos = S.find(From);
+ assert(Pos != StringRef::npos);
+ return (Twine(S.substr(0, Pos)) + To + S.substr(Pos + From.size())).str();
+}
+
+static const std::string NullImportDescriptorSymbolName =
+ "__NULL_IMPORT_DESCRIPTOR";
+
+namespace {
+// This class constructs various small object files necessary to support linking
+// symbols imported from a DLL. The contents are pretty strictly defined and
+// nearly entirely static. The details of the structures files are defined in
+// WINNT.h and the PE/COFF specification.
+class ObjectFactory {
+ using u16 = support::ulittle16_t;
+ using u32 = support::ulittle32_t;
+
+ BumpPtrAllocator Alloc;
+ StringRef DLLName;
+ StringRef Library;
+ std::string ImportDescriptorSymbolName;
+ std::string NullThunkSymbolName;
+
+public:
+ ObjectFactory(StringRef S)
+ : DLLName(S), Library(S.drop_back(4)),
+ ImportDescriptorSymbolName(("__IMPORT_DESCRIPTOR_" + Library).str()),
+ NullThunkSymbolName(("\x7f" + Library + "_NULL_THUNK_DATA").str()) {}
+
+ // Creates an Import Descriptor. This is a small object file which contains a
+ // reference to the terminators and contains the library name (entry) for the
+ // import name table. It will force the linker to construct the necessary
+ // structure to import symbols from the DLL.
+ NewArchiveMember createImportDescriptor(std::vector<uint8_t> &Buffer);
+
+ // Creates a NULL import descriptor. This is a small object file whcih
+ // contains a NULL import descriptor. It is used to terminate the imports
+ // from a specific DLL.
+ NewArchiveMember createNullImportDescriptor(std::vector<uint8_t> &Buffer);
+
+ // Create a NULL Thunk Entry. This is a small object file which contains a
+ // NULL Import Address Table entry and a NULL Import Lookup Table Entry. It
+ // is used to terminate the IAT and ILT.
+ NewArchiveMember createNullThunk(std::vector<uint8_t> &Buffer);
+
+ // Create a short import file which is described in PE/COFF spec 7. Import
+ // Library Format.
+ NewArchiveMember createShortImport(StringRef Sym, uint16_t Ordinal,
+ ImportNameType NameType, bool isData);
+};
+}
+
+NewArchiveMember
+ObjectFactory::createImportDescriptor(std::vector<uint8_t> &Buffer) {
+ static const uint32_t NumberOfSections = 2;
+ static const uint32_t NumberOfSymbols = 7;
+ static const uint32_t NumberOfRelocations = 3;
+
+ // COFF Header
+ coff_file_header Header{
+ u16(Config->Machine), u16(NumberOfSections), u32(0),
+ u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
+ // .idata$2
+ sizeof(coff_import_directory_table_entry) +
+ NumberOfRelocations * sizeof(coff_relocation) +
+ // .idata$4
+ (DLLName.size() + 1)),
+ u32(NumberOfSymbols), u16(0),
+ u16(is32bit() ? IMAGE_FILE_32BIT_MACHINE : 0),
+ };
+ append(Buffer, Header);
+
+ // Section Header Table
+ static const coff_section SectionTable[NumberOfSections] = {
+ {{'.', 'i', 'd', 'a', 't', 'a', '$', '2'},
+ u32(0),
+ u32(0),
+ u32(sizeof(coff_import_directory_table_entry)),
+ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),
+ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
+ sizeof(coff_import_directory_table_entry)),
+ u32(0),
+ u16(NumberOfRelocations),
+ u16(0),
+ u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
+ {{'.', 'i', 'd', 'a', 't', 'a', '$', '6'},
+ u32(0),
+ u32(0),
+ u32(DLLName.size() + 1),
+ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
+ sizeof(coff_import_directory_table_entry) +
+ NumberOfRelocations * sizeof(coff_relocation)),
+ u32(0),
+ u32(0),
+ u16(0),
+ u16(0),
+ u32(IMAGE_SCN_ALIGN_2BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
+ };
+ append(Buffer, SectionTable);
+
+ // .idata$2
+ static const coff_import_directory_table_entry ImportDescriptor{
+ u32(0), u32(0), u32(0), u32(0), u32(0),
+ };
+ append(Buffer, ImportDescriptor);
+
+ static const coff_relocation RelocationTable[NumberOfRelocations] = {
+ {u32(offsetof(coff_import_directory_table_entry, NameRVA)), u32(2),
+ u16(getImgRelRelocation())},
+ {u32(offsetof(coff_import_directory_table_entry, ImportLookupTableRVA)),
+ u32(3), u16(getImgRelRelocation())},
+ {u32(offsetof(coff_import_directory_table_entry, ImportAddressTableRVA)),
+ u32(4), u16(getImgRelRelocation())},
+ };
+ append(Buffer, RelocationTable);
+
+ // .idata$6
+ auto S = Buffer.size();
+ Buffer.resize(S + DLLName.size() + 1);
+ memcpy(&Buffer[S], DLLName.data(), DLLName.size());
+ Buffer[S + DLLName.size()] = '\0';
+
+ // Symbol Table
+ coff_symbol16 SymbolTable[NumberOfSymbols] = {
+ {{{0, 0, 0, 0, 0, 0, 0, 0}},
+ u32(0),
+ u16(1),
+ u16(0),
+ IMAGE_SYM_CLASS_EXTERNAL,
+ 0},
+ {{{'.', 'i', 'd', 'a', 't', 'a', '$', '2'}},
+ u32(0),
+ u16(1),
+ u16(0),
+ IMAGE_SYM_CLASS_SECTION,
+ 0},
+ {{{'.', 'i', 'd', 'a', 't', 'a', '$', '6'}},
+ u32(0),
+ u16(2),
+ u16(0),
+ IMAGE_SYM_CLASS_STATIC,
+ 0},
+ {{{'.', 'i', 'd', 'a', 't', 'a', '$', '4'}},
+ u32(0),
+ u16(0),
+ u16(0),
+ IMAGE_SYM_CLASS_SECTION,
+ 0},
+ {{{'.', 'i', 'd', 'a', 't', 'a', '$', '5'}},
+ u32(0),
+ u16(0),
+ u16(0),
+ IMAGE_SYM_CLASS_SECTION,
+ 0},
+ {{{0, 0, 0, 0, 0, 0, 0, 0}},
+ u32(0),
+ u16(0),
+ u16(0),
+ IMAGE_SYM_CLASS_EXTERNAL,
+ 0},
+ {{{0, 0, 0, 0, 0, 0, 0, 0}},
+ u32(0),
+ u16(0),
+ u16(0),
+ IMAGE_SYM_CLASS_EXTERNAL,
+ 0},
+ };
+ reinterpret_cast<StringTableOffset &>(SymbolTable[0].Name).Offset =
+ sizeof(uint32_t);
+ reinterpret_cast<StringTableOffset &>(SymbolTable[5].Name).Offset =
+ sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1;
+ reinterpret_cast<StringTableOffset &>(SymbolTable[6].Name).Offset =
+ sizeof(uint32_t) + ImportDescriptorSymbolName.length() + 1 +
+ NullImportDescriptorSymbolName.length() + 1;
+ append(Buffer, SymbolTable);
+
+ // String Table
+ writeStringTable(Buffer,
+ {ImportDescriptorSymbolName, NullImportDescriptorSymbolName,
+ NullThunkSymbolName});
+
+ StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
+ return {MemoryBufferRef(F, DLLName)};
+}
+
+NewArchiveMember
+ObjectFactory::createNullImportDescriptor(std::vector<uint8_t> &Buffer) {
+ static const uint32_t NumberOfSections = 1;
+ static const uint32_t NumberOfSymbols = 1;
+
+ // COFF Header
+ coff_file_header Header{
+ u16(Config->Machine), u16(NumberOfSections), u32(0),
+ u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
+ // .idata$3
+ sizeof(coff_import_directory_table_entry)),
+ u32(NumberOfSymbols), u16(0),
+ u16(is32bit() ? IMAGE_FILE_32BIT_MACHINE : 0),
+ };
+ append(Buffer, Header);
+
+ // Section Header Table
+ static const coff_section SectionTable[NumberOfSections] = {
+ {{'.', 'i', 'd', 'a', 't', 'a', '$', '3'},
+ u32(0),
+ u32(0),
+ u32(sizeof(coff_import_directory_table_entry)),
+ u32(sizeof(coff_file_header) +
+ (NumberOfSections * sizeof(coff_section))),
+ u32(0),
+ u32(0),
+ u16(0),
+ u16(0),
+ u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
+ };
+ append(Buffer, SectionTable);
+
+ // .idata$3
+ static const coff_import_directory_table_entry ImportDescriptor{
+ u32(0), u32(0), u32(0), u32(0), u32(0),
+ };
+ append(Buffer, ImportDescriptor);
+
+ // Symbol Table
+ coff_symbol16 SymbolTable[NumberOfSymbols] = {
+ {{{0, 0, 0, 0, 0, 0, 0, 0}},
+ u32(0),
+ u16(1),
+ u16(0),
+ IMAGE_SYM_CLASS_EXTERNAL,
+ 0},
+ };
+ reinterpret_cast<StringTableOffset &>(SymbolTable[0].Name).Offset =
+ sizeof(uint32_t);
+ append(Buffer, SymbolTable);
+
+ // String Table
+ writeStringTable(Buffer, {NullImportDescriptorSymbolName});
+
+ StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
+ return {MemoryBufferRef(F, DLLName)};
+}
+
+NewArchiveMember ObjectFactory::createNullThunk(std::vector<uint8_t> &Buffer) {
+ static const uint32_t NumberOfSections = 2;
+ static const uint32_t NumberOfSymbols = 1;
+
+ // COFF Header
+ coff_file_header Header{
+ u16(Config->Machine), u16(NumberOfSections), u32(0),
+ u32(sizeof(Header) + (NumberOfSections * sizeof(coff_section)) +
+ // .idata$5
+ sizeof(export_address_table_entry) +
+ // .idata$4
+ sizeof(export_address_table_entry)),
+ u32(NumberOfSymbols), u16(0),
+ u16(is32bit() ? IMAGE_FILE_32BIT_MACHINE : 0),
+ };
+ append(Buffer, Header);
+
+ // Section Header Table
+ static const coff_section SectionTable[NumberOfSections] = {
+ {{'.', 'i', 'd', 'a', 't', 'a', '$', '5'},
+ u32(0),
+ u32(0),
+ u32(sizeof(export_address_table_entry)),
+ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section)),
+ u32(0),
+ u32(0),
+ u16(0),
+ u16(0),
+ u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
+ {{'.', 'i', 'd', 'a', 't', 'a', '$', '4'},
+ u32(0),
+ u32(0),
+ u32(sizeof(export_address_table_entry)),
+ u32(sizeof(coff_file_header) + NumberOfSections * sizeof(coff_section) +
+ sizeof(export_address_table_entry)),
+ u32(0),
+ u32(0),
+ u16(0),
+ u16(0),
+ u32(IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_CNT_INITIALIZED_DATA |
+ IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE)},
+ };
+ append(Buffer, SectionTable);
+
+ // .idata$5
+ static const export_address_table_entry ILT{u32(0)};
+ append(Buffer, ILT);
+
+ // .idata$4
+ static const export_address_table_entry IAT{u32(0)};
+ append(Buffer, IAT);
+
+ // Symbol Table
+ coff_symbol16 SymbolTable[NumberOfSymbols] = {
+ {{{0, 0, 0, 0, 0, 0, 0, 0}},
+ u32(0),
+ u16(1),
+ u16(0),
+ IMAGE_SYM_CLASS_EXTERNAL,
+ 0},
+ };
+ reinterpret_cast<StringTableOffset &>(SymbolTable[0].Name).Offset =
+ sizeof(uint32_t);
+ append(Buffer, SymbolTable);
+
+ // String Table
+ writeStringTable(Buffer, {NullThunkSymbolName});
+
+ StringRef F{reinterpret_cast<const char *>(Buffer.data()), Buffer.size()};
+ return {MemoryBufferRef{F, DLLName}};
+}
+
+NewArchiveMember ObjectFactory::createShortImport(StringRef Sym,
+ uint16_t Ordinal,
+ ImportNameType NameType,
+ bool isData) {
+ size_t ImpSize = DLLName.size() + Sym.size() + 2; // +2 for NULs
+ size_t Size = sizeof(coff_import_header) + ImpSize;
+ char *Buf = Alloc.Allocate<char>(Size);
+ memset(Buf, 0, Size);
+ char *P = Buf;
+
+ // Write short import library.
+ auto *Imp = reinterpret_cast<coff_import_header *>(P);
+ P += sizeof(*Imp);
+ Imp->Sig2 = 0xFFFF;
+ Imp->Machine = Config->Machine;
+ Imp->SizeOfData = ImpSize;
+ if (Ordinal > 0)
+ Imp->OrdinalHint = Ordinal;
+ Imp->TypeInfo = (isData ? IMPORT_DATA : IMPORT_CODE);
+ Imp->TypeInfo |= NameType << 2;
+
+ // Write symbol name and DLL name.
+ memcpy(P, Sym.data(), Sym.size());
+ P += Sym.size() + 1;
+ memcpy(P, DLLName.data(), DLLName.size());
+
+ return {MemoryBufferRef(StringRef(Buf, Size), DLLName)};
+}
+
+// Creates an import library for a DLL. In this function, we first
+// create an empty import library using lib.exe and then adds short
+// import files to that file.
+void lld::coff::writeImportLibrary() {
+ std::vector<NewArchiveMember> Members;
+
+ std::string Path = getImplibPath();
+ std::string DLLName = llvm::sys::path::filename(Config->OutputFile);
+ ObjectFactory OF(DLLName);
+
+ std::vector<uint8_t> ImportDescriptor;
+ Members.push_back(OF.createImportDescriptor(ImportDescriptor));
+
+ std::vector<uint8_t> NullImportDescriptor;
+ Members.push_back(OF.createNullImportDescriptor(NullImportDescriptor));
+
+ std::vector<uint8_t> NullThunk;
+ Members.push_back(OF.createNullThunk(NullThunk));
+
+ for (Export &E : Config->Exports) {
+ if (E.Private)
+ continue;
+
+ ImportNameType Type = getNameType(E.SymbolName, E.Name);
+ std::string Name = E.ExtName.empty()
+ ? std::string(E.SymbolName)
+ : replace(E.SymbolName, E.Name, E.ExtName);
+ Members.push_back(OF.createShortImport(Name, E.Ordinal, Type, E.Data));
+ }
+
+ std::pair<StringRef, std::error_code> Result =
+ writeArchive(Path, Members, /*WriteSymtab*/ true, object::Archive::K_GNU,
+ /*Deterministic*/ true, /*Thin*/ false);
+ if (auto EC = Result.second)
+ fatal(EC, "failed to write " + Path);
+}
diff --git a/COFF/ModuleDef.cpp b/COFF/ModuleDef.cpp
index d117e961f89a..5e393f45d184 100644
--- a/COFF/ModuleDef.cpp
+++ b/COFF/ModuleDef.cpp
@@ -134,13 +134,13 @@ private:
void readAsInt(uint64_t *I) {
read();
if (Tok.K != Identifier || Tok.Value.getAsInteger(10, *I))
- error("integer expected");
+ fatal("integer expected");
}
void expect(Kind Expected, StringRef Msg) {
read();
if (Tok.K != Expected)
- error(Msg);
+ fatal(Msg);
}
void unget() { Stack.push_back(Tok); }
@@ -177,7 +177,7 @@ private:
parseVersion(&Config->MajorImageVersion, &Config->MinorImageVersion);
return;
default:
- error(Twine("unknown directive: ") + Tok.Value);
+ fatal("unknown directive: " + Tok.Value);
}
}
@@ -188,7 +188,7 @@ private:
if (Tok.K == Equal) {
read();
if (Tok.K != Identifier)
- error(Twine("identifier expected, but got ") + Tok.Value);
+ fatal("identifier expected, but got " + Tok.Value);
E.ExtName = E.Name;
E.Name = Tok.Value;
} else {
@@ -264,15 +264,15 @@ private:
void parseVersion(uint32_t *Major, uint32_t *Minor) {
read();
if (Tok.K != Identifier)
- error(Twine("identifier expected, but got ") + Tok.Value);
+ fatal("identifier expected, but got " + Tok.Value);
StringRef V1, V2;
std::tie(V1, V2) = Tok.Value.split('.');
if (V1.getAsInteger(10, *Major))
- error(Twine("integer expected, but got ") + Tok.Value);
+ fatal("integer expected, but got " + Tok.Value);
if (V2.empty())
*Minor = 0;
else if (V2.getAsInteger(10, *Minor))
- error(Twine("integer expected, but got ") + Tok.Value);
+ fatal("integer expected, but got " + Tok.Value);
}
Lexer Lex;
diff --git a/COFF/Options.td b/COFF/Options.td
index a21b8de76afb..e5c9c5b4635b 100644
--- a/COFF/Options.td
+++ b/COFF/Options.td
@@ -48,6 +48,7 @@ def manifestuac : P<"manifestuac", "User access control">;
def manifestfile : P<"manifestfile", "Manifest file path">;
def manifestdependency : P<"manifestdependency",
"Attributes for <dependency> in manifest file">;
+def manifestinput : P<"manifestinput", "Specify manifest file">;
// We cannot use multiclass P because class name "incl" is different
// from its command line option name. We do this because "include" is
@@ -110,6 +111,7 @@ def no_incremental : F<"incremental:no">;
def nologo : F<"nologo">;
def throwingnew : F<"throwingnew">;
def editandcontinue : F<"editandcontinue">;
+def fastfail : F<"fastfail">;
def delay : QF<"delay">;
def errorreport : QF<"errorreport">;
diff --git a/COFF/PDB.cpp b/COFF/PDB.cpp
index 786d28798bab..7606ccc680d3 100644
--- a/COFF/PDB.cpp
+++ b/COFF/PDB.cpp
@@ -38,7 +38,8 @@ void lld::coff::createPDB(StringRef Path) {
size_t FileSize = PageSize * 3;
ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
FileOutputBuffer::create(Path, FileSize);
- error(BufferOrErr, Twine("failed to open ") + Path);
+ if (auto EC = BufferOrErr.getError())
+ fatal(EC, "failed to open " + Path);
std::unique_ptr<FileOutputBuffer> Buffer = std::move(*BufferOrErr);
// Write the file header.
diff --git a/COFF/README.md b/COFF/README.md
index c1be560f4405..f1bfc9c15263 100644
--- a/COFF/README.md
+++ b/COFF/README.md
@@ -1,265 +1 @@
-The PE/COFF Linker
-==================
-
-This directory contains a linker for Windows operating system.
-Because the fundamental design of this port is different from
-the other ports of LLD, this port is separated to this directory.
-
-The linker is command-line compatible with MSVC linker and is
-generally 2x faster than that. It can be used to link real-world
-programs such as LLD itself or Clang, or even web browsers which
-are probably the largest open-source programs for Windows.
-
-This document is also applicable to ELF linker because the linker
-shares the same design as this COFF linker.
-
-Overall Design
---------------
-
-This is a list of important data types in this linker.
-
-* SymbolBody
-
- SymbolBody is a class for symbols. They may be created for symbols
- in object files or in archive file headers. The linker may create
- them out of nothing.
-
- There are mainly three types of SymbolBodies: Defined, Undefined, or
- Lazy. Defined symbols are for all symbols that are considered as
- "resolved", including real defined symbols, COMDAT symbols, common
- symbols, absolute symbols, linker-created symbols, etc. Undefined
- symbols are for undefined symbols, which need to be replaced by
- Defined symbols by the resolver. Lazy symbols represent symbols we
- found in archive file headers -- which can turn into Defined symbols
- if we read archieve members, but we haven't done that yet.
-
-* Symbol
-
- Symbol is a pointer to a SymbolBody. There's only one Symbol for
- each unique symbol name (this uniqueness is guaranteed by the symbol
- table). Because SymbolBodies are created for each file
- independently, there can be many SymbolBodies for the same
- name. Thus, the relationship between Symbols and SymbolBodies is 1:N.
-
- The resolver keeps the Symbol's pointer to always point to the "best"
- SymbolBody. Pointer mutation is the resolve operation in this
- linker.
-
- SymbolBodies have pointers to their Symbols. That means you can
- always find the best SymbolBody from any SymbolBody by following
- pointers twice. This structure makes it very easy to find
- replacements for symbols. For example, if you have an Undefined
- SymbolBody, you can find a Defined SymbolBody for that symbol just
- by going to its Symbol and then to SymbolBody, assuming the resolver
- have successfully resolved all undefined symbols.
-
-* Chunk
-
- Chunk represents a chunk of data that will occupy space in an
- output. Each regular section becomes a chunk.
- Chunks created for common or BSS symbols are not backed by sections.
- The linker may create chunks out of nothing to append additional
- data to an output.
-
- Chunks know about their size, how to copy their data to mmap'ed
- outputs, and how to apply relocations to them. Specifically,
- section-based chunks know how to read relocation tables and how to
- apply them.
-
-* SymbolTable
-
- SymbolTable is basically a hash table from strings to Symbols, with
- a logic to resolve symbol conflicts. It resolves conflicts by symbol
- type. For example, if we add Undefined and Defined symbols, the
- symbol table will keep the latter. If we add Defined and Lazy
- symbols, it will keep the former. If we add Lazy and Undefined, it
- will keep the former, but it will also trigger the Lazy symbol to
- load the archive member to actually resolve the symbol.
-
-* OutputSection
-
- OutputSection is a container of Chunks. A Chunk belongs to at most
- one OutputSection.
-
-There are mainly three actors in this linker.
-
-* InputFile
-
- InputFile is a superclass of file readers. We have a different
- subclass for each input file type, such as regular object file,
- archive file, etc. They are responsible for creating and owning
- SymbolBodies and Chunks.
-
-* Writer
-
- The writer is responsible for writing file headers and Chunks to a
- file. It creates OutputSections, put all Chunks into them, assign
- unique, non-overlapping addresses and file offsets to them, and then
- write them down to a file.
-
-* Driver
-
- The linking process is drived by the driver. The driver
-
- - processes command line options,
- - creates a symbol table,
- - creates an InputFile for each input file and put all symbols in it
- into the symbol table,
- - checks if there's no remaining undefined symbols,
- - creates a writer,
- - and passes the symbol table to the writer to write the result to a
- file.
-
-Performance
------------
-
-It's generally 2x faster than MSVC link.exe. It takes 3.5 seconds to
-self-host on my Xeon 2580 machine. MSVC linker takes 7.0 seconds to
-link the same executable. The resulting output is 65MB.
-The old LLD is buggy that it produces 120MB executable for some reason,
-and it takes 30 seconds to do that.
-
-We believe the performance difference comes from simplification and
-optimizations we made to the new port. Notable differences are listed
-below.
-
-* Reduced number of relocation table reads
-
- In the old design, relocation tables are read from beginning to
- construct graphs because they consist of graph edges. In the new
- design, they are not read until we actually apply relocations.
-
- This simplification has two benefits. One is that we don't create
- additional objects for relocations but instead consume relocation
- tables directly. The other is that it reduces number of relocation
- entries we have to read, because we won't read relocations for
- dead-stripped COMDAT sections. Large C++ programs tend to consist of
- lots of COMDAT sections. In the old design, the time to process
- relocation table is linear to size of input. In this new model, it's
- linear to size of output.
-
-* Reduced number of symbol table lookup
-
- Symbol table lookup can be a heavy operation because number of
- symbols can be very large and each symbol name can be very long
- (think of C++ mangled symbols -- time to compute a hash value for a
- string is linear to the length.)
-
- We look up the symbol table exactly only once for each symbol in the
- new design. This is I believe the minimum possible number. This is
- achieved by the separation of Symbol and SymbolBody. Once you get a
- pointer to a Symbol by looking up the symbol table, you can always
- get the latest symbol resolution result by just dereferencing a
- pointer. (I'm not sure if the idea is new to the linker. At least,
- all other linkers I've investigated so far seem to look up hash
- tables or sets more than once for each new symbol, but I may be
- wrong.)
-
-* Reduced number of file visits
-
- The symbol table implements the Windows linker semantics. We treat
- the symbol table as a bucket of all known symbols, including symbols
- in archive file headers. We put all symbols into one bucket as we
- visit new files. That means we visit each file only once.
-
- This is different from the Unix linker semantics, in which we only
- keep undefined symbols and visit each file one by one until we
- resolve all undefined symbols. In the Unix model, we have to visit
- archive files many times if there are circular dependencies between
- archives.
-
-* Avoiding creating additional objects or copying data
-
- The data structures described in the previous section are all thin
- wrappers for classes that LLVM libObject provides. We avoid copying
- data from libObject's objects to our objects. We read much less data
- than before. For example, we don't read symbol values until we apply
- relocations because these values are not relevant to symbol
- resolution. Again, COMDAT symbols may be discarded during symbol
- resolution, so reading their attributes too early could result in a
- waste. We use underlying objects directly where doing so makes
- sense.
-
-Parallelism
------------
-
-The abovementioned data structures are also chosen with
-multi-threading in mind. It should relatively be easy to make the
-symbol table a concurrent hash map, so that we let multiple workers
-work on symbol table concurrently. Symbol resolution in this design is
-a single pointer mutation, which allows the resolver work concurrently
-in a lock-free manner using atomic pointer compare-and-swap.
-
-It should also be easy to apply relocations and write chunks concurrently.
-
-We created an experimental multi-threaded linker using the Microsoft
-ConcRT concurrency library, and it was able to link itself in 0.5
-seconds, so we think the design is promising.
-
-Link-Time Optimization
-----------------------
-
-LTO is implemented by handling LLVM bitcode files as object files.
-The linker resolves symbols in bitcode files normally. If all symbols
-are successfully resolved, it then calls an LLVM libLTO function
-with all bitcode files to convert them to one big regular COFF file.
-Finally, the linker replaces bitcode symbols with COFF symbols,
-so that we can link the input files as if they were in the native
-format from the beginning.
-
-The details are described in this document.
-http://llvm.org/docs/LinkTimeOptimization.html
-
-Glossary
---------
-
-* RVA
-
- Short for Relative Virtual Address.
-
- Windows executables or DLLs are not position-independent; they are
- linked against a fixed address called an image base. RVAs are
- offsets from an image base.
-
- Default image bases are 0x140000000 for executables and 0x18000000
- for DLLs. For example, when we are creating an executable, we assume
- that the executable will be loaded at address 0x140000000 by the
- loader, so we apply relocations accordingly. Result texts and data
- will contain raw absolute addresses.
-
-* VA
-
- Short for Virtual Address. Equivalent to RVA + image base. It is
- rarely used. We almost always use RVAs instead.
-
-* Base relocations
-
- Relocation information for the loader. If the loader decides to map
- an executable or a DLL to a different address than their image
- bases, it fixes up binaries using information contained in the base
- relocation table. A base relocation table consists of a list of
- locations containing addresses. The loader adds a difference between
- RVA and actual load address to all locations listed there.
-
- Note that this run-time relocation mechanism is much simpler than ELF.
- There's no PLT or GOT. Images are relocated as a whole just
- by shifting entire images in memory by some offsets. Although doing
- this breaks text sharing, I think this mechanism is not actually bad
- on today's computers.
-
-* ICF
-
- Short for Identical COMDAT Folding.
-
- ICF is an optimization to reduce output size by merging COMDAT sections
- by not only their names but by their contents. If two COMDAT sections
- happen to have the same metadata, actual contents and relocations,
- they are merged by ICF. It is known as an effective technique,
- and it usually reduces C++ program's size by a few percent or more.
-
- Note that this is not entirely sound optimization. C/C++ require
- different functions have different addresses. If a program depends on
- that property, it would fail at runtime. However, that's not really an
- issue on Windows because MSVC link.exe enabled the optimization by
- default. As long as your program works with the linker's default
- settings, your program should be safe with ICF.
+See docs/NewLLD.rst
diff --git a/COFF/SymbolTable.cpp b/COFF/SymbolTable.cpp
index 5b7b89cd360a..df9da4c36650 100644
--- a/COFF/SymbolTable.cpp
+++ b/COFF/SymbolTable.cpp
@@ -14,7 +14,7 @@
#include "Symbols.h"
#include "lld/Core/Parallel.h"
#include "llvm/IR/LLVMContext.h"
-#include "llvm/LTO/LTOCodeGenerator.h"
+#include "llvm/LTO/legacy/LTOCodeGenerator.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/raw_ostream.h"
#include <utility>
@@ -164,7 +164,7 @@ void SymbolTable::reportRemainingUndefines(bool Resolve) {
llvm::errs() << File->getShortName() << ": undefined symbol: "
<< Sym->getName() << "\n";
if (!Config->Force)
- error("Link failed");
+ fatal("link failed");
}
void SymbolTable::addLazy(Lazy *New, std::vector<Symbol *> *Accum) {
@@ -211,7 +211,7 @@ void SymbolTable::addSymbol(SymbolBody *New) {
// equivalent (conflicting), or more preferable, respectively.
int Comp = Existing->compare(New);
if (Comp == 0)
- error(Twine("duplicate symbol: ") + Existing->getDebugName() + " and " +
+ fatal("duplicate symbol: " + Existing->getDebugName() + " and " +
New->getDebugName());
if (Comp < 0)
Sym->Body = New;
@@ -338,21 +338,25 @@ void SymbolTable::addCombinedLTOObject(ObjectFile *Obj) {
// diagnose them later in reportRemainingUndefines().
StringRef Name = Body->getName();
Symbol *Sym = insert(Body);
+ SymbolBody *Existing = Sym->Body;
+
+ if (Existing == Body)
+ continue;
- if (isa<DefinedBitcode>(Sym->Body)) {
+ if (isa<DefinedBitcode>(Existing)) {
Sym->Body = Body;
continue;
}
- if (auto *L = dyn_cast<Lazy>(Sym->Body)) {
+ if (auto *L = dyn_cast<Lazy>(Existing)) {
// We may see new references to runtime library symbols such as __chkstk
// here. These symbols must be wholly defined in non-bitcode files.
addMemberFile(L);
continue;
}
- SymbolBody *Existing = Sym->Body;
+
int Comp = Existing->compare(Body);
if (Comp == 0)
- error(Twine("LTO: unexpected duplicate symbol: ") + Name);
+ fatal("LTO: unexpected duplicate symbol: " + Name);
if (Comp < 0)
Sym->Body = Body;
}
@@ -369,7 +373,7 @@ void SymbolTable::addCombinedLTOObjects() {
// Create an object file and add it to the symbol table by replacing any
// DefinedBitcode symbols with the definitions in the object file.
- LTOCodeGenerator CG(getGlobalContext());
+ LTOCodeGenerator CG(BitcodeFile::Context);
CG.setOptLevel(Config->LTOOptLevel);
std::vector<ObjectFile *> Objs = createLTOObjects(&CG);
@@ -379,7 +383,7 @@ void SymbolTable::addCombinedLTOObjects() {
size_t NumBitcodeFiles = BitcodeFiles.size();
run();
if (BitcodeFiles.size() != NumBitcodeFiles)
- error("LTO: late loaded symbol created new bitcode reference");
+ fatal("LTO: late loaded symbol created new bitcode reference");
}
// Combine and compile bitcode files and then return the result
@@ -414,24 +418,23 @@ std::vector<ObjectFile *> SymbolTable::createLTOObjects(LTOCodeGenerator *CG) {
DisableVerify = false;
#endif
if (!CG->optimize(DisableVerify, false, false, false))
- error(""); // optimize() should have emitted any error message.
+ fatal(""); // optimize() should have emitted any error message.
Objs.resize(Config->LTOJobs);
// Use std::list to avoid invalidation of pointers in OSPtrs.
std::list<raw_svector_ostream> OSs;
std::vector<raw_pwrite_stream *> OSPtrs;
- for (SmallVector<char, 0> &Obj : Objs) {
+ for (SmallString<0> &Obj : Objs) {
OSs.emplace_back(Obj);
OSPtrs.push_back(&OSs.back());
}
if (!CG->compileOptimized(OSPtrs))
- error(""); // compileOptimized() should have emitted any error message.
+ fatal(""); // compileOptimized() should have emitted any error message.
std::vector<ObjectFile *> ObjFiles;
- for (SmallVector<char, 0> &Obj : Objs) {
- auto *ObjFile = new ObjectFile(
- MemoryBufferRef(StringRef(Obj.data(), Obj.size()), "<LTO object>"));
+ for (SmallString<0> &Obj : Objs) {
+ auto *ObjFile = new ObjectFile(MemoryBufferRef(Obj, "<LTO object>"));
Files.emplace_back(ObjFile);
ObjectFiles.push_back(ObjFile);
ObjFile->parse();
diff --git a/COFF/SymbolTable.h b/COFF/SymbolTable.h
index ce305bfa8743..8bf4387cdfff 100644
--- a/COFF/SymbolTable.h
+++ b/COFF/SymbolTable.h
@@ -115,7 +115,7 @@ private:
std::vector<std::future<InputFile *>> ObjectQueue;
std::vector<BitcodeFile *> BitcodeFiles;
- std::vector<SmallVector<char, 0>> Objs;
+ std::vector<SmallString<0>> Objs;
llvm::BumpPtrAllocator Alloc;
};
diff --git a/COFF/Symbols.cpp b/COFF/Symbols.cpp
index d732d76cfb06..6e2db6631ce7 100644
--- a/COFF/Symbols.cpp
+++ b/COFF/Symbols.cpp
@@ -162,32 +162,6 @@ std::string SymbolBody::getDebugName() {
return N;
}
-uint64_t Defined::getFileOff() {
- switch (kind()) {
- case DefinedImportDataKind:
- return cast<DefinedImportData>(this)->getFileOff();
- case DefinedImportThunkKind:
- return cast<DefinedImportThunk>(this)->getFileOff();
- case DefinedLocalImportKind:
- return cast<DefinedLocalImport>(this)->getFileOff();
- case DefinedCommonKind:
- return cast<DefinedCommon>(this)->getFileOff();
- case DefinedRegularKind:
- return cast<DefinedRegular>(this)->getFileOff();
-
- case DefinedBitcodeKind:
- llvm_unreachable("There is no file offset for a bitcode symbol.");
- case DefinedAbsoluteKind:
- llvm_unreachable("Cannot get a file offset for an absolute symbol.");
- case DefinedRelativeKind:
- llvm_unreachable("Cannot get a file offset for a relative symbol.");
- case LazyKind:
- case UndefinedKind:
- llvm_unreachable("Cannot get a file offset for an undefined symbol.");
- }
- llvm_unreachable("unknown symbol kind");
-}
-
COFFSymbolRef DefinedCOFF::getCOFFSymbol() {
size_t SymSize = File->getCOFFObj()->getSymbolTableEntrySize();
if (SymSize == sizeof(coff_symbol16))
@@ -225,7 +199,7 @@ std::unique_ptr<InputFile> Lazy::getMember() {
else if (Magic == file_magic::bitcode)
Obj.reset(new BitcodeFile(MBRef));
else
- error(Twine(File->getName()) + ": unknown file type");
+ fatal("unknown file type: " + File->getName());
Obj->setParentName(File->getName());
return Obj;
diff --git a/COFF/Symbols.h b/COFF/Symbols.h
index 7059fbc8bb15..f96c1fb3cc1d 100644
--- a/COFF/Symbols.h
+++ b/COFF/Symbols.h
@@ -125,10 +125,6 @@ public:
// writer sets and uses RVAs.
uint64_t getRVA();
- // Returns the file offset of this symbol in the final executable.
- // The writer uses this information to apply relocations.
- uint64_t getFileOff();
-
// Returns the RVA relative to the beginning of the output section.
// Used to implement SECREL relocation type.
uint64_t getSecrel();
diff --git a/COFF/Writer.cpp b/COFF/Writer.cpp
index 5575c8d6b320..d8077df95701 100644
--- a/COFF/Writer.cpp
+++ b/COFF/Writer.cpp
@@ -59,6 +59,7 @@ private:
void openFile(StringRef OutputPath);
template <typename PEHeaderTy> void writeHeader();
void fixSafeSEHSymbols();
+ void setSectionPermissions();
void writeSections();
void sortExceptionTable();
void applyRelocations();
@@ -114,6 +115,7 @@ public:
StringRef getName() { return Name; }
std::vector<Chunk *> &getChunks() { return Chunks; }
void addPermissions(uint32_t C);
+ void setPermissions(uint32_t C);
uint32_t getPermissions() { return Header.Characteristics & PermMask; }
uint32_t getCharacteristics() { return Header.Characteristics; }
uint64_t getRVA() { return Header.VirtualAddress; }
@@ -163,19 +165,23 @@ void OutputSection::addChunk(Chunk *C) {
Chunks.push_back(C);
C->setOutputSection(this);
uint64_t Off = Header.VirtualSize;
- Off = align(Off, C->getAlign());
+ Off = alignTo(Off, C->getAlign());
C->setRVA(Off);
C->setOutputSectionOff(Off);
Off += C->getSize();
Header.VirtualSize = Off;
if (C->hasData())
- Header.SizeOfRawData = align(Off, SectorSize);
+ Header.SizeOfRawData = alignTo(Off, SectorSize);
}
void OutputSection::addPermissions(uint32_t C) {
Header.Characteristics |= C & PermMask;
}
+void OutputSection::setPermissions(uint32_t C) {
+ Header.Characteristics = C & PermMask;
+}
+
// Write the section header to a given buffer.
void OutputSection::writeHeaderTo(uint8_t *Buf) {
auto *Hdr = reinterpret_cast<coff_section *>(Buf);
@@ -193,13 +199,13 @@ void OutputSection::writeHeaderTo(uint8_t *Buf) {
uint64_t Defined::getSecrel() {
if (auto *D = dyn_cast<DefinedRegular>(this))
return getRVA() - D->getChunk()->getOutputSection()->getRVA();
- error("SECREL relocation points to a non-regular symbol");
+ fatal("SECREL relocation points to a non-regular symbol");
}
uint64_t Defined::getSectionIndex() {
if (auto *D = dyn_cast<DefinedRegular>(this))
return D->getChunk()->getOutputSection()->SectionIndex;
- error("SECTION relocation points to a non-regular symbol");
+ fatal("SECTION relocation points to a non-regular symbol");
}
bool Defined::isExecutable() {
@@ -222,6 +228,7 @@ void Writer::run() {
createSection(".reloc");
assignAddresses();
removeEmptySections();
+ setSectionPermissions();
createSymbolAndStringTable();
openFile(Config->OutputFile);
if (Config->is64()) {
@@ -232,7 +239,8 @@ void Writer::run() {
fixSafeSEHSymbols();
writeSections();
sortExceptionTable();
- error(Buffer->commit(), "Failed to write the output file");
+ if (auto EC = Buffer->commit())
+ fatal(EC, "failed to write the output file");
}
static StringRef getOutputSection(StringRef Name) {
@@ -447,15 +455,15 @@ void Writer::createSymbolAndStringTable() {
OutputSection *LastSection = OutputSections.back();
// We position the symbol table to be adjacent to the end of the last section.
- uint64_t FileOff =
- LastSection->getFileOff() + align(LastSection->getRawSize(), SectorSize);
+ uint64_t FileOff = LastSection->getFileOff() +
+ alignTo(LastSection->getRawSize(), SectorSize);
if (!OutputSymtab.empty()) {
PointerToSymbolTable = FileOff;
FileOff += OutputSymtab.size() * sizeof(coff_symbol16);
}
if (!Strtab.empty())
FileOff += Strtab.size() + 4;
- FileSize = align(FileOff, SectorSize);
+ FileSize = alignTo(FileOff, SectorSize);
}
// Visits all sections to assign incremental, non-overlapping RVAs and
@@ -466,7 +474,7 @@ void Writer::assignAddresses() {
sizeof(coff_section) * OutputSections.size();
SizeOfHeaders +=
Config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header);
- SizeOfHeaders = align(SizeOfHeaders, SectorSize);
+ SizeOfHeaders = alignTo(SizeOfHeaders, SectorSize);
uint64_t RVA = 0x1000; // The first page is kept unmapped.
FileSize = SizeOfHeaders;
// Move DISCARDABLE (or non-memory-mapped) sections to the end of file because
@@ -480,10 +488,10 @@ void Writer::assignAddresses() {
addBaserels(Sec);
Sec->setRVA(RVA);
Sec->setFileOffset(FileSize);
- RVA += align(Sec->getVirtualSize(), PageSize);
- FileSize += align(Sec->getRawSize(), SectorSize);
+ RVA += alignTo(Sec->getVirtualSize(), PageSize);
+ FileSize += alignTo(Sec->getRawSize(), SectorSize);
}
- SizeOfImage = SizeOfHeaders + align(RVA - 0x1000, PageSize);
+ SizeOfImage = SizeOfHeaders + alignTo(RVA - 0x1000, PageSize);
}
template <typename PEHeaderTy> void Writer::writeHeader() {
@@ -596,13 +604,26 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
if (Symbol *Sym = Symtab->findUnderscore("_tls_used")) {
if (Defined *B = dyn_cast<Defined>(Sym->Body)) {
Dir[TLS_TABLE].RelativeVirtualAddress = B->getRVA();
- Dir[TLS_TABLE].Size = 40;
+ Dir[TLS_TABLE].Size = Config->is64()
+ ? sizeof(object::coff_tls_directory64)
+ : sizeof(object::coff_tls_directory32);
}
}
if (Symbol *Sym = Symtab->findUnderscore("_load_config_used")) {
- if (Defined *B = dyn_cast<Defined>(Sym->Body)) {
+ if (auto *B = dyn_cast<DefinedRegular>(Sym->Body)) {
+ SectionChunk *SC = B->getChunk();
+ assert(B->getRVA() >= SC->getRVA());
+ uint64_t OffsetInChunk = B->getRVA() - SC->getRVA();
+ if (!SC->hasData() || OffsetInChunk + 4 > SC->getSize())
+ fatal("_load_config_used is malformed");
+
+ ArrayRef<uint8_t> SecContents = SC->getContents();
+ uint32_t LoadConfigSize =
+ *reinterpret_cast<const ulittle32_t *>(&SecContents[OffsetInChunk]);
+ if (OffsetInChunk + LoadConfigSize > SC->getSize())
+ fatal("_load_config_used is too large");
Dir[LOAD_CONFIG_TABLE].RelativeVirtualAddress = B->getRVA();
- Dir[LOAD_CONFIG_TABLE].Size = Config->is64() ? 112 : 64;
+ Dir[LOAD_CONFIG_TABLE].Size = LoadConfigSize;
}
}
@@ -626,14 +647,14 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
// The first 4 bytes is length including itself.
Buf = reinterpret_cast<uint8_t *>(&SymbolTable[NumberOfSymbols]);
write32le(Buf, Strtab.size() + 4);
- memcpy(Buf + 4, Strtab.data(), Strtab.size());
+ if (!Strtab.empty())
+ memcpy(Buf + 4, Strtab.data(), Strtab.size());
}
void Writer::openFile(StringRef Path) {
- ErrorOr<std::unique_ptr<FileOutputBuffer>> BufferOrErr =
- FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable);
- error(BufferOrErr, Twine("failed to open ") + Path);
- Buffer = std::move(*BufferOrErr);
+ Buffer = check(
+ FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable),
+ "failed to open " + Path);
}
void Writer::fixSafeSEHSymbols() {
@@ -643,6 +664,17 @@ void Writer::fixSafeSEHSymbols() {
Config->SEHCount->setVA(SEHTable->getSize() / 4);
}
+// Handles /section options to allow users to overwrite
+// section attributes.
+void Writer::setSectionPermissions() {
+ for (auto &P : Config->Section) {
+ StringRef Name = P.first;
+ uint32_t Perm = P.second;
+ if (auto *Sec = findSection(Name))
+ Sec->setPermissions(Perm);
+ }
+}
+
// Write section contents to a mmap'ed file.
void Writer::writeSections() {
uint8_t *Buf = Buffer->getBufferStart();
diff --git a/ELF/CMakeLists.txt b/ELF/CMakeLists.txt
index 3dcb65ff8957..a1b65adc7400 100644
--- a/ELF/CMakeLists.txt
+++ b/ELF/CMakeLists.txt
@@ -2,25 +2,49 @@ set(LLVM_TARGET_DEFINITIONS Options.td)
tablegen(LLVM Options.inc -gen-opt-parser-defs)
add_public_tablegen_target(ELFOptionsTableGen)
-add_lld_library(lldELF2
+add_lld_library(lldELF
Driver.cpp
DriverUtils.cpp
+ EhFrame.cpp
Error.cpp
+ ICF.cpp
InputFiles.cpp
InputSection.cpp
+ LTO.cpp
LinkerScript.cpp
MarkLive.cpp
OutputSections.cpp
+ Relocations.cpp
+ ScriptParser.cpp
+ Strings.cpp
+ SymbolListFile.cpp
SymbolTable.cpp
Symbols.cpp
Target.cpp
+ Thunks.cpp
Writer.cpp
LINK_COMPONENTS
+ ${LLVM_TARGETS_TO_BUILD}
+ Analysis
+ BitReader
+ BitWriter
+ Codegen
+ Core
+ IPO
+ Linker
+ LTO
Object
Option
+ Passes
MC
Support
+ Target
+ TransformUtils
+
+ LINK_LIBS
+ lldConfig
+ ${PTHREAD_LIB}
)
-add_dependencies(lldELF2 ELFOptionsTableGen)
+add_dependencies(lldELF intrinsics_gen ELFOptionsTableGen)
diff --git a/ELF/Config.h b/ELF/Config.h
index c279b99b43c1..2ccd95e88775 100644
--- a/ELF/Config.h
+++ b/ELF/Config.h
@@ -17,10 +17,10 @@
#include <vector>
namespace lld {
-namespace elf2 {
+namespace elf {
class InputFile;
-class SymbolBody;
+struct Symbol;
enum ELFKind {
ELFNoneKind,
@@ -30,60 +30,105 @@ enum ELFKind {
ELF64BEKind
};
+enum class BuildIdKind { None, Fnv1, Md5, Sha1, Hexstring };
+
+enum class UnresolvedPolicy { NoUndef, Error, Warn, Ignore };
+
+struct SymbolVersion {
+ llvm::StringRef Name;
+ bool IsExternCpp;
+};
+
+// This struct contains symbols version definition that
+// can be found in version script if it is used for link.
+struct VersionDefinition {
+ VersionDefinition(llvm::StringRef Name, size_t Id) : Name(Name), Id(Id) {}
+ llvm::StringRef Name;
+ size_t Id;
+ std::vector<SymbolVersion> Globals;
+ size_t NameOff; // Offset in string table.
+};
+
// This struct contains the global configuration for the linker.
// Most fields are direct mapping from the command line options
// and such fields have the same name as the corresponding options.
// Most fields are initialized by the driver.
struct Configuration {
- SymbolBody *EntrySym = nullptr;
- SymbolBody *MipsGpDisp = nullptr;
+ Symbol *EntrySym = nullptr;
InputFile *FirstElf = nullptr;
llvm::StringRef DynamicLinker;
llvm::StringRef Entry;
llvm::StringRef Emulation;
llvm::StringRef Fini;
llvm::StringRef Init;
+ llvm::StringRef LtoAAPipeline;
+ llvm::StringRef LtoNewPmPasses;
llvm::StringRef OutputFile;
llvm::StringRef SoName;
llvm::StringRef Sysroot;
std::string RPath;
- llvm::MapVector<llvm::StringRef, std::vector<llvm::StringRef>> OutputSections;
+ std::vector<VersionDefinition> VersionDefinitions;
+ std::vector<llvm::StringRef> DynamicList;
std::vector<llvm::StringRef> SearchPaths;
std::vector<llvm::StringRef> Undefined;
+ std::vector<SymbolVersion> VersionScriptGlobals;
+ std::vector<uint8_t> BuildIdVector;
bool AllowMultipleDefinition;
bool AsNeeded = false;
bool Bsymbolic;
+ bool BsymbolicFunctions;
+ bool Demangle = true;
+ bool DisableVerify;
bool DiscardAll;
bool DiscardLocals;
bool DiscardNone;
+ bool EhFrameHdr;
bool EnableNewDtags;
bool ExportDynamic;
+ bool FatalWarnings;
bool GcSections;
bool GnuHash = false;
+ bool ICF;
bool Mips64EL = false;
- bool NoInhibitExec;
- bool NoUndefined;
+ bool NoGnuUnique;
+ bool NoUndefinedVersion;
+ bool Pic;
+ bool Pie;
bool PrintGcSections;
+ bool Rela;
+ bool Relocatable;
+ bool SaveTemps;
bool Shared;
bool Static = false;
bool StripAll;
+ bool StripDebug;
bool SysvHash = true;
+ bool Threads;
+ bool Trace;
bool Verbose;
+ bool WarnCommon;
+ bool ZCombreloc;
bool ZExecStack;
bool ZNodelete;
bool ZNow;
bool ZOrigin;
bool ZRelro;
+ UnresolvedPolicy UnresolvedSymbols;
+ BuildIdKind BuildId = BuildIdKind::None;
ELFKind EKind = ELFNoneKind;
+ uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL;
uint16_t EMachine = llvm::ELF::EM_NONE;
uint64_t EntryAddr = -1;
- unsigned Optimize = 0;
+ uint64_t ImageBase;
+ unsigned LtoJobs;
+ unsigned LtoO;
+ unsigned Optimize;
};
// The only instance of Configuration struct.
extern Configuration *Config;
-} // namespace elf2
+} // namespace elf
} // namespace lld
#endif
diff --git a/ELF/Driver.cpp b/ELF/Driver.cpp
index f00d97851e4a..c6ca2639236f 100644
--- a/ELF/Driver.cpp
+++ b/ELF/Driver.cpp
@@ -10,119 +10,218 @@
#include "Driver.h"
#include "Config.h"
#include "Error.h"
+#include "ICF.h"
#include "InputFiles.h"
+#include "InputSection.h"
+#include "LinkerScript.h"
+#include "Strings.h"
+#include "SymbolListFile.h"
#include "SymbolTable.h"
#include "Target.h"
#include "Writer.h"
-#include "llvm/ADT/STLExtras.h"
+#include "lld/Driver/Driver.h"
#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/raw_ostream.h"
+#include <cstdlib>
#include <utility>
using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::object;
+using namespace llvm::sys;
using namespace lld;
-using namespace lld::elf2;
+using namespace lld::elf;
-Configuration *elf2::Config;
-LinkerDriver *elf2::Driver;
+Configuration *elf::Config;
+LinkerDriver *elf::Driver;
+
+bool elf::link(ArrayRef<const char *> Args, raw_ostream &Error) {
+ HasError = false;
+ ErrorOS = &Error;
-void elf2::link(ArrayRef<const char *> Args) {
Configuration C;
LinkerDriver D;
+ ScriptConfiguration SC;
Config = &C;
Driver = &D;
- Driver->main(Args.slice(1));
+ ScriptConfig = &SC;
+
+ Driver->main(Args);
+ return !HasError;
}
+// Parses a linker -m option.
static std::pair<ELFKind, uint16_t> parseEmulation(StringRef S) {
- if (S == "elf32btsmip")
- return {ELF32BEKind, EM_MIPS};
- if (S == "elf32ltsmip")
- return {ELF32LEKind, EM_MIPS};
- if (S == "elf32ppc" || S == "elf32ppc_fbsd")
- return {ELF32BEKind, EM_PPC};
- if (S == "elf64ppc" || S == "elf64ppc_fbsd")
- return {ELF64BEKind, EM_PPC64};
- if (S == "elf_i386")
- return {ELF32LEKind, EM_386};
- if (S == "elf_x86_64")
- return {ELF64LEKind, EM_X86_64};
- if (S == "aarch64linux")
- return {ELF64LEKind, EM_AARCH64};
- if (S == "i386pe" || S == "i386pep" || S == "thumb2pe")
- error("Windows targets are not supported on the ELF frontend: " + S);
- error("Unknown emulation: " + S);
+ if (S.endswith("_fbsd"))
+ S = S.drop_back(5);
+
+ std::pair<ELFKind, uint16_t> Ret =
+ StringSwitch<std::pair<ELFKind, uint16_t>>(S)
+ .Case("aarch64linux", {ELF64LEKind, EM_AARCH64})
+ .Case("armelf_linux_eabi", {ELF32LEKind, EM_ARM})
+ .Case("elf32_x86_64", {ELF32LEKind, EM_X86_64})
+ .Case("elf32btsmip", {ELF32BEKind, EM_MIPS})
+ .Case("elf32ltsmip", {ELF32LEKind, EM_MIPS})
+ .Case("elf32ppc", {ELF32BEKind, EM_PPC})
+ .Case("elf64btsmip", {ELF64BEKind, EM_MIPS})
+ .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS})
+ .Case("elf64ppc", {ELF64BEKind, EM_PPC64})
+ .Case("elf_i386", {ELF32LEKind, EM_386})
+ .Case("elf_x86_64", {ELF64LEKind, EM_X86_64})
+ .Default({ELFNoneKind, EM_NONE});
+
+ if (Ret.first == ELFNoneKind) {
+ if (S == "i386pe" || S == "i386pep" || S == "thumb2pe")
+ error("Windows targets are not supported on the ELF frontend: " + S);
+ else
+ error("unknown emulation: " + S);
+ }
+ return Ret;
}
// Returns slices of MB by parsing MB as an archive file.
// Each slice consists of a member file in the archive.
-static std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef MB) {
- ErrorOr<std::unique_ptr<Archive>> FileOrErr = Archive::create(MB);
- error(FileOrErr, "Failed to parse archive");
- std::unique_ptr<Archive> File = std::move(*FileOrErr);
+std::vector<MemoryBufferRef>
+LinkerDriver::getArchiveMembers(MemoryBufferRef MB) {
+ std::unique_ptr<Archive> File =
+ check(Archive::create(MB), "failed to parse archive");
std::vector<MemoryBufferRef> V;
- for (const ErrorOr<Archive::Child> &C : File->children()) {
- error(C, "Could not get the child of the archive " + File->getFileName());
- ErrorOr<MemoryBufferRef> MbOrErr = C->getMemoryBufferRef();
- error(MbOrErr, "Could not get the buffer for a child of the archive " +
- File->getFileName());
- V.push_back(*MbOrErr);
+ Error Err;
+ for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) {
+ Archive::Child C = check(COrErr, "could not get the child of the archive " +
+ File->getFileName());
+ MemoryBufferRef MBRef =
+ check(C.getMemoryBufferRef(),
+ "could not get the buffer for a child of the archive " +
+ File->getFileName());
+ V.push_back(MBRef);
}
+ if (Err)
+ Error(Err);
+
+ // Take ownership of memory buffers created for members of thin archives.
+ for (std::unique_ptr<MemoryBuffer> &MB : File->takeThinBuffers())
+ OwningMBs.push_back(std::move(MB));
+
return V;
}
// Opens and parses a file. Path has to be resolved already.
// Newly created memory buffers are owned by this driver.
void LinkerDriver::addFile(StringRef Path) {
- using namespace llvm::sys::fs;
+ using namespace sys::fs;
if (Config->Verbose)
- llvm::outs() << Path << "\n";
- auto MBOrErr = MemoryBuffer::getFile(Path);
- error(MBOrErr, "cannot open " + Path);
- std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
- MemoryBufferRef MBRef = MB->getMemBufferRef();
- OwningMBs.push_back(std::move(MB)); // take MB ownership
+ outs() << Path << "\n";
+
+ Optional<MemoryBufferRef> Buffer = readFile(Path);
+ if (!Buffer.hasValue())
+ return;
+ MemoryBufferRef MBRef = *Buffer;
switch (identify_magic(MBRef.getBuffer())) {
case file_magic::unknown:
- readLinkerScript(&Alloc, MBRef);
+ readLinkerScript(MBRef);
return;
case file_magic::archive:
if (WholeArchive) {
for (MemoryBufferRef MB : getArchiveMembers(MBRef))
- Files.push_back(createObjectFile(MB));
+ Files.push_back(createObjectFile(MB, Path));
return;
}
Files.push_back(make_unique<ArchiveFile>(MBRef));
return;
case file_magic::elf_shared_object:
+ if (Config->Relocatable) {
+ error("attempted static link of dynamic object " + Path);
+ return;
+ }
Files.push_back(createSharedFile(MBRef));
return;
default:
- Files.push_back(createObjectFile(MBRef));
+ if (InLib)
+ Files.push_back(make_unique<LazyObjectFile>(MBRef));
+ else
+ Files.push_back(createObjectFile(MBRef));
+ }
+}
+
+Optional<MemoryBufferRef> LinkerDriver::readFile(StringRef Path) {
+ auto MBOrErr = MemoryBuffer::getFile(Path);
+ if (auto EC = MBOrErr.getError()) {
+ error(EC, "cannot open " + Path);
+ return None;
}
+ std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;
+ MemoryBufferRef MBRef = MB->getMemBufferRef();
+ OwningMBs.push_back(std::move(MB)); // take MB ownership
+
+ if (Cpio)
+ Cpio->append(relativeToRoot(Path), MBRef.getBuffer());
+
+ return MBRef;
+}
+
+// Add a given library by searching it from input search paths.
+void LinkerDriver::addLibrary(StringRef Name) {
+ std::string Path = searchLibrary(Name);
+ if (Path.empty())
+ error("unable to find library -l" + Name);
+ else
+ addFile(Path);
+}
+
+// This function is called on startup. We need this for LTO since
+// LTO calls LLVM functions to compile bitcode files to native code.
+// Technically this can be delayed until we read bitcode files, but
+// we don't bother to do lazily because the initialization is fast.
+static void initLLVM(opt::InputArgList &Args) {
+ InitializeAllTargets();
+ InitializeAllTargetMCs();
+ InitializeAllAsmPrinters();
+ InitializeAllAsmParsers();
+
+ // This is a flag to discard all but GlobalValue names.
+ // We want to enable it by default because it saves memory.
+ // Disable it only when a developer option (-save-temps) is given.
+ Driver->Context.setDiscardValueNames(!Config->SaveTemps);
+ Driver->Context.enableDebugTypeODRUniquing();
+
+ // Parse and evaluate -mllvm options.
+ std::vector<const char *> V;
+ V.push_back("lld (LLVM option parsing)");
+ for (auto *Arg : Args.filtered(OPT_mllvm))
+ V.push_back(Arg->getValue());
+ cl::ParseCommandLineOptions(V.size(), V.data());
}
// Some command line options or some combinations of them are not allowed.
// This function checks for such errors.
static void checkOptions(opt::InputArgList &Args) {
- // Traditional linkers can generate re-linkable object files instead
- // of executables or DSOs. We don't support that since the feature
- // does not seem to provide more value than the static archiver.
- if (Args.hasArg(OPT_relocatable))
- error("-r option is not supported. Use 'ar' command instead.");
-
// The MIPS ABI as of 2016 does not support the GNU-style symbol lookup
// table which is a relatively new feature.
if (Config->EMachine == EM_MIPS && Config->GnuHash)
- error("The .gnu.hash section is not compatible with the MIPS target.");
+ error("the .gnu.hash section is not compatible with the MIPS target.");
if (Config->EMachine == EM_AMDGPU && !Config->Entry.empty())
error("-e option is not valid for AMDGPU.");
+
+ if (Config->Pie && Config->Shared)
+ error("-shared and -pie may not be used together");
+
+ if (Config->Relocatable) {
+ if (Config->Shared)
+ error("-r and -shared may not be used together");
+ if (Config->GcSections)
+ error("-r and --gc-sections may not be used together");
+ if (Config->ICF)
+ error("-r and --icf may not be used together");
+ if (Config->Pie)
+ error("-r and -pie may not be used together");
+ }
}
static StringRef
@@ -132,6 +231,22 @@ getString(opt::InputArgList &Args, unsigned Key, StringRef Default = "") {
return Default;
}
+static int getInteger(opt::InputArgList &Args, unsigned Key, int Default) {
+ int V = Default;
+ if (auto *Arg = Args.getLastArg(Key)) {
+ StringRef S = Arg->getValue();
+ if (S.getAsInteger(10, V))
+ error(Arg->getSpelling() + ": number expected, but got " + S);
+ }
+ return V;
+}
+
+static const char *getReproduceOption(opt::InputArgList &Args) {
+ if (auto *Arg = Args.getLastArg(OPT_reproduce))
+ return Arg->getValue();
+ return getenv("LLD_REPRODUCE");
+}
+
static bool hasZOption(opt::InputArgList &Args, StringRef Key) {
for (auto *Arg : Args.filtered(OPT_z))
if (Key == Arg->getValue())
@@ -140,12 +255,33 @@ static bool hasZOption(opt::InputArgList &Args, StringRef Key) {
}
void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
- initSymbols();
+ ELFOptTable Parser;
+ opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));
+ if (Args.hasArg(OPT_help)) {
+ printHelp(ArgsArr[0]);
+ return;
+ }
+ if (Args.hasArg(OPT_version)) {
+ outs() << getVersionString();
+ return;
+ }
+
+ if (const char *Path = getReproduceOption(Args)) {
+ // Note that --reproduce is a debug option so you can ignore it
+ // if you are trying to understand the whole picture of the code.
+ Cpio.reset(CpioFile::create(Path));
+ if (Cpio) {
+ Cpio->append("response.txt", createResponseFile(Args));
+ Cpio->append("version.txt", getVersionString());
+ }
+ }
- opt::InputArgList Args = parseArgs(&Alloc, ArgsArr);
readConfigs(Args);
+ initLLVM(Args);
createFiles(Args);
checkOptions(Args);
+ if (HasError)
+ return;
switch (Config->EKind) {
case ELF32LEKind:
@@ -165,6 +301,25 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
}
}
+static UnresolvedPolicy getUnresolvedSymbolOption(opt::InputArgList &Args) {
+ if (Args.hasArg(OPT_noinhibit_exec))
+ return UnresolvedPolicy::Warn;
+ if (Args.hasArg(OPT_no_undefined) || hasZOption(Args, "defs"))
+ return UnresolvedPolicy::NoUndef;
+ if (Config->Relocatable)
+ return UnresolvedPolicy::Ignore;
+
+ if (auto *Arg = Args.getLastArg(OPT_unresolved_symbols)) {
+ StringRef S = Arg->getValue();
+ if (S == "ignore-all" || S == "ignore-in-object-files")
+ return UnresolvedPolicy::Ignore;
+ if (S == "ignore-in-shared-libs" || S == "report-all")
+ return UnresolvedPolicy::Error;
+ error("unknown --unresolved-symbols value: " + S);
+ }
+ return UnresolvedPolicy::Error;
+}
+
// Initializes Config members by the command line options.
void LinkerDriver::readConfigs(opt::InputArgList &Args) {
for (auto *Arg : Args.filtered(OPT_L))
@@ -185,38 +340,66 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
Config->AllowMultipleDefinition = Args.hasArg(OPT_allow_multiple_definition);
Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic);
+ Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions);
+ Config->Demangle = !Args.hasArg(OPT_no_demangle);
+ Config->DisableVerify = Args.hasArg(OPT_disable_verify);
Config->DiscardAll = Args.hasArg(OPT_discard_all);
Config->DiscardLocals = Args.hasArg(OPT_discard_locals);
Config->DiscardNone = Args.hasArg(OPT_discard_none);
+ Config->EhFrameHdr = Args.hasArg(OPT_eh_frame_hdr);
Config->EnableNewDtags = !Args.hasArg(OPT_disable_new_dtags);
Config->ExportDynamic = Args.hasArg(OPT_export_dynamic);
+ Config->FatalWarnings = Args.hasArg(OPT_fatal_warnings);
Config->GcSections = Args.hasArg(OPT_gc_sections);
- Config->NoInhibitExec = Args.hasArg(OPT_noinhibit_exec);
- Config->NoUndefined = Args.hasArg(OPT_no_undefined);
+ Config->ICF = Args.hasArg(OPT_icf);
+ Config->NoGnuUnique = Args.hasArg(OPT_no_gnu_unique);
+ Config->NoUndefinedVersion = Args.hasArg(OPT_no_undefined_version);
+ Config->Pie = Args.hasArg(OPT_pie);
Config->PrintGcSections = Args.hasArg(OPT_print_gc_sections);
+ Config->Relocatable = Args.hasArg(OPT_relocatable);
+ Config->SaveTemps = Args.hasArg(OPT_save_temps);
Config->Shared = Args.hasArg(OPT_shared);
Config->StripAll = Args.hasArg(OPT_strip_all);
+ Config->StripDebug = Args.hasArg(OPT_strip_debug);
+ Config->Threads = Args.hasArg(OPT_threads);
+ Config->Trace = Args.hasArg(OPT_trace);
Config->Verbose = Args.hasArg(OPT_verbose);
+ Config->WarnCommon = Args.hasArg(OPT_warn_common);
Config->DynamicLinker = getString(Args, OPT_dynamic_linker);
Config->Entry = getString(Args, OPT_entry);
Config->Fini = getString(Args, OPT_fini, "_fini");
Config->Init = getString(Args, OPT_init, "_init");
+ Config->LtoAAPipeline = getString(Args, OPT_lto_aa_pipeline);
+ Config->LtoNewPmPasses = getString(Args, OPT_lto_newpm_passes);
Config->OutputFile = getString(Args, OPT_o);
Config->SoName = getString(Args, OPT_soname);
Config->Sysroot = getString(Args, OPT_sysroot);
+ Config->Optimize = getInteger(Args, OPT_O, 1);
+ Config->LtoO = getInteger(Args, OPT_lto_O, 2);
+ if (Config->LtoO > 3)
+ error("invalid optimization level for LTO: " + getString(Args, OPT_lto_O));
+ Config->LtoJobs = getInteger(Args, OPT_lto_jobs, 1);
+ if (Config->LtoJobs == 0)
+ error("number of threads must be > 0");
+
+ Config->ZCombreloc = !hasZOption(Args, "nocombreloc");
Config->ZExecStack = hasZOption(Args, "execstack");
Config->ZNodelete = hasZOption(Args, "nodelete");
Config->ZNow = hasZOption(Args, "now");
Config->ZOrigin = hasZOption(Args, "origin");
Config->ZRelro = !hasZOption(Args, "norelro");
- if (auto *Arg = Args.getLastArg(OPT_O)) {
- StringRef Val = Arg->getValue();
- if (Val.getAsInteger(10, Config->Optimize))
- error("Invalid optimization level");
- }
+ if (Config->Relocatable)
+ Config->StripAll = false;
+
+ // --strip-all implies --strip-debug.
+ if (Config->StripAll)
+ Config->StripDebug = true;
+
+ // Config->Pic is true if we are generating position-independent code.
+ Config->Pic = Config->Pie || Config->Shared;
if (auto *Arg = Args.getLastArg(OPT_hash_style)) {
StringRef S = Arg->getValue();
@@ -226,19 +409,52 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
} else if (S == "both") {
Config->GnuHash = true;
} else if (S != "sysv")
- error("Unknown hash style: " + S);
+ error("unknown hash style: " + S);
+ }
+
+ // Parse --build-id or --build-id=<style>.
+ if (Args.hasArg(OPT_build_id))
+ Config->BuildId = BuildIdKind::Fnv1;
+ if (auto *Arg = Args.getLastArg(OPT_build_id_eq)) {
+ StringRef S = Arg->getValue();
+ if (S == "md5") {
+ Config->BuildId = BuildIdKind::Md5;
+ } else if (S == "sha1") {
+ Config->BuildId = BuildIdKind::Sha1;
+ } else if (S == "none") {
+ Config->BuildId = BuildIdKind::None;
+ } else if (S.startswith("0x")) {
+ Config->BuildId = BuildIdKind::Hexstring;
+ Config->BuildIdVector = parseHex(S.substr(2));
+ } else {
+ error("unknown --build-id style: " + S);
+ }
}
for (auto *Arg : Args.filtered(OPT_undefined))
Config->Undefined.push_back(Arg->getValue());
+
+ Config->UnresolvedSymbols = getUnresolvedSymbolOption(Args);
+
+ if (auto *Arg = Args.getLastArg(OPT_dynamic_list))
+ if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
+ parseDynamicList(*Buffer);
+
+ for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol))
+ Config->DynamicList.push_back(Arg->getValue());
+
+ if (auto *Arg = Args.getLastArg(OPT_version_script))
+ if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))
+ parseVersionScript(*Buffer);
}
void LinkerDriver::createFiles(opt::InputArgList &Args) {
for (auto *Arg : Args) {
switch (Arg->getOption().getID()) {
case OPT_l:
- addFile(searchLibrary(Arg->getValue()));
+ addLibrary(Arg->getValue());
break;
+ case OPT_alias_script_T:
case OPT_INPUT:
case OPT_script:
addFile(Arg->getValue());
@@ -261,75 +477,112 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) {
case OPT_no_whole_archive:
WholeArchive = false;
break;
+ case OPT_start_lib:
+ InLib = true;
+ break;
+ case OPT_end_lib:
+ InLib = false;
+ break;
}
}
- if (Files.empty())
+ if (Files.empty() && !HasError)
error("no input files.");
+
+ // If -m <machine_type> was not given, infer it from object files.
+ if (Config->EKind == ELFNoneKind) {
+ for (std::unique_ptr<InputFile> &F : Files) {
+ if (F->EKind == ELFNoneKind)
+ continue;
+ Config->EKind = F->EKind;
+ Config->EMachine = F->EMachine;
+ break;
+ }
+ }
}
+// Do actual linking. Note that when this function is called,
+// all linker scripts have already been parsed.
template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
SymbolTable<ELFT> Symtab;
- Target.reset(createTarget());
-
- if (!Config->Shared) {
- // Add entry symbol.
- //
- // There is no entry symbol for AMDGPU binaries, so skip adding one to avoid
- // having and undefined symbol.
- if (Config->Entry.empty() && Config->EMachine != EM_AMDGPU)
- Config->Entry = (Config->EMachine == EM_MIPS) ? "__start" : "_start";
-
- // In the assembly for 32 bit x86 the _GLOBAL_OFFSET_TABLE_ symbol
- // is magical and is used to produce a R_386_GOTPC relocation.
- // The R_386_GOTPC relocation value doesn't actually depend on the
- // symbol value, so it could use an index of STN_UNDEF which, according
- // to the spec, means the symbol value is 0.
- // Unfortunately both gas and MC keep the _GLOBAL_OFFSET_TABLE_ symbol in
- // the object file.
- // The situation is even stranger on x86_64 where the assembly doesn't
- // need the magical symbol, but gas still puts _GLOBAL_OFFSET_TABLE_ as
- // an undefined symbol in the .o files.
- // Given that the symbol is effectively unused, we just create a dummy
- // hidden one to avoid the undefined symbol error.
- Symtab.addIgnored("_GLOBAL_OFFSET_TABLE_");
- }
+ elf::Symtab<ELFT>::X = &Symtab;
+
+ std::unique_ptr<TargetInfo> TI(createTarget());
+ Target = TI.get();
+ LinkerScript<ELFT> LS;
+ Script<ELFT>::X = &LS;
+
+ Config->Rela = ELFT::Is64Bits || Config->EMachine == EM_X86_64;
+ Config->Mips64EL =
+ (Config->EMachine == EM_MIPS && Config->EKind == ELF64LEKind);
+
+ // Add entry symbol. Note that AMDGPU binaries have no entry points.
+ if (Config->Entry.empty() && !Config->Shared && !Config->Relocatable &&
+ Config->EMachine != EM_AMDGPU)
+ Config->Entry = (Config->EMachine == EM_MIPS) ? "__start" : "_start";
+
+ // Default output filename is "a.out" by the Unix tradition.
+ if (Config->OutputFile.empty())
+ Config->OutputFile = "a.out";
+
+ // Handle --trace-symbol.
+ for (auto *Arg : Args.filtered(OPT_trace_symbol))
+ Symtab.trace(Arg->getValue());
+ // Set either EntryAddr (if S is a number) or EntrySym (otherwise).
if (!Config->Entry.empty()) {
- // Set either EntryAddr (if S is a number) or EntrySym (otherwise).
StringRef S = Config->Entry;
if (S.getAsInteger(0, Config->EntryAddr))
Config->EntrySym = Symtab.addUndefined(S);
}
- if (Config->EMachine == EM_MIPS) {
- // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
- // start of function and gp pointer into GOT. Use 'strong' variant of
- // the addIgnored to prevent '_gp_disp' substitution.
- Config->MipsGpDisp = Symtab.addIgnoredStrong("_gp_disp");
-
- // Define _gp for MIPS. st_value of _gp symbol will be updated by Writer
- // so that it points to an absolute address which is relative to GOT.
- // See "Global Data Symbols" in Chapter 6 in the following document:
- // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
- Symtab.addAbsolute("_gp", ElfSym<ELFT>::MipsGp);
+ // Initialize Config->ImageBase.
+ if (auto *Arg = Args.getLastArg(OPT_image_base)) {
+ StringRef S = Arg->getValue();
+ if (S.getAsInteger(0, Config->ImageBase))
+ error(Arg->getSpelling() + ": number expected, but got " + S);
+ else if ((Config->ImageBase % Target->PageSize) != 0)
+ warning(Arg->getSpelling() + ": address isn't multiple of page size");
+ } else {
+ Config->ImageBase = Config->Pic ? 0 : Target->DefaultImageBase;
}
for (std::unique_ptr<InputFile> &F : Files)
Symtab.addFile(std::move(F));
+ if (HasError)
+ return; // There were duplicate symbols or incompatible files
- for (StringRef S : Config->Undefined)
- Symtab.addUndefinedOpt(S);
+ Symtab.scanUndefinedFlags();
+ Symtab.scanShlibUndefined();
+ Symtab.scanDynamicList();
+ Symtab.scanVersionScript();
+ Symtab.scanSymbolVersions();
+
+ Symtab.addCombinedLtoObject();
+ if (HasError)
+ return;
for (auto *Arg : Args.filtered(OPT_wrap))
Symtab.wrap(Arg->getValue());
- if (Config->OutputFile.empty())
- Config->OutputFile = "a.out";
-
// Write the result to the file.
- Symtab.scanShlibUndefined();
if (Config->GcSections)
- markLive<ELFT>(&Symtab);
+ markLive<ELFT>();
+ if (Config->ICF)
+ doIcf<ELFT>();
+
+ // MergeInputSection::splitIntoPieces needs to be called before
+ // any call of MergeInputSection::getOffset. Do that.
+ for (const std::unique_ptr<elf::ObjectFile<ELFT>> &F :
+ Symtab.getObjectFiles())
+ for (InputSectionBase<ELFT> *S : F->getSections()) {
+ if (!S || S == &InputSection<ELFT>::Discarded || !S->Live)
+ continue;
+ if (S->Compressed)
+ S->uncompress();
+ if (auto *MS = dyn_cast<MergeInputSection<ELFT>>(S))
+ MS->splitIntoPieces();
+ }
+
writeResult<ELFT>(&Symtab);
}
diff --git a/ELF/Driver.h b/ELF/Driver.h
index 720ef46dc710..6b9b9bb208e5 100644
--- a/ELF/Driver.h
+++ b/ELF/Driver.h
@@ -12,36 +12,54 @@
#include "SymbolTable.h"
#include "lld/Core/LLVM.h"
+#include "llvm/ADT/Optional.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSet.h"
#include "llvm/Option/ArgList.h"
+#include "llvm/Support/raw_ostream.h"
namespace lld {
-namespace elf2 {
+namespace elf {
extern class LinkerDriver *Driver;
-// Entry point of the ELF linker.
-void link(ArrayRef<const char *> Args);
+class CpioFile;
class LinkerDriver {
public:
void main(ArrayRef<const char *> Args);
void addFile(StringRef Path);
+ void addLibrary(StringRef Name);
+ llvm::LLVMContext Context; // to parse bitcode ifles
+ std::unique_ptr<CpioFile> Cpio; // for reproduce
private:
+ std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef MB);
+ llvm::Optional<MemoryBufferRef> readFile(StringRef Path);
void readConfigs(llvm::opt::InputArgList &Args);
void createFiles(llvm::opt::InputArgList &Args);
template <class ELFT> void link(llvm::opt::InputArgList &Args);
- llvm::BumpPtrAllocator Alloc;
+ // True if we are in --whole-archive and --no-whole-archive.
bool WholeArchive = false;
+
+ // True if we are in --start-lib and --end-lib.
+ bool InLib = false;
+
+ llvm::BumpPtrAllocator Alloc;
std::vector<std::unique_ptr<InputFile>> Files;
std::vector<std::unique_ptr<MemoryBuffer>> OwningMBs;
};
// Parses command line options.
-llvm::opt::InputArgList parseArgs(llvm::BumpPtrAllocator *A,
- ArrayRef<const char *> Args);
+class ELFOptTable : public llvm::opt::OptTable {
+public:
+ ELFOptTable();
+ llvm::opt::InputArgList parse(ArrayRef<const char *> Argv);
+
+private:
+ llvm::BumpPtrAllocator Alloc;
+};
// Create enum with OPT_xxx values for each option in Options.td
enum {
@@ -51,14 +69,43 @@ enum {
#undef OPTION
};
-// Parses a linker script. Calling this function updates the Symtab and Config.
-void readLinkerScript(llvm::BumpPtrAllocator *A, MemoryBufferRef MB);
+// This is the class to create a .cpio file for --reproduce.
+//
+// If "--reproduce foo" is given, we create a file "foo.cpio" and
+// copy all input files to the archive, along with a response file
+// to re-run the same command with the same inputs.
+// It is useful for reporting issues to LLD developers.
+//
+// Cpio as a file format is a deliberate choice. It's standardized in
+// POSIX and very easy to create. cpio command is available virtually
+// on all Unix systems. See
+// http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_07
+// for the format details.
+class CpioFile {
+public:
+ static CpioFile *create(StringRef OutputPath);
+ void append(StringRef Path, StringRef Data);
+
+private:
+ CpioFile(std::unique_ptr<llvm::raw_fd_ostream> OS, StringRef Basename);
+
+ std::unique_ptr<llvm::raw_fd_ostream> OS;
+ llvm::StringSet<> Seen;
+ std::string Basename;
+};
+
+void printHelp(const char *Argv0);
+std::string getVersionString();
+std::vector<uint8_t> parseHexstring(StringRef S);
+
+std::string createResponseFile(const llvm::opt::InputArgList &Args);
+std::string relativeToRoot(StringRef Path);
std::string findFromSearchPaths(StringRef Path);
std::string searchLibrary(StringRef Path);
std::string buildSysrootedPath(llvm::StringRef Dir, llvm::StringRef File);
-} // namespace elf2
+} // namespace elf
} // namespace lld
#endif
diff --git a/ELF/DriverUtils.cpp b/ELF/DriverUtils.cpp
index 965ed4f00a61..3f18259b4ae7 100644
--- a/ELF/DriverUtils.cpp
+++ b/ELF/DriverUtils.cpp
@@ -15,16 +15,20 @@
#include "Driver.h"
#include "Error.h"
+#include "lld/Config/Version.h"
#include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/Option/Option.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/StringSaver.h"
using namespace llvm;
+using namespace llvm::sys;
using namespace lld;
-using namespace lld::elf2;
+using namespace lld::elf;
// Create OptTable
@@ -34,55 +38,208 @@ using namespace lld::elf2;
#undef PREFIX
// Create table mapping all options defined in Options.td
-static const opt::OptTable::Info infoTable[] = {
+static const opt::OptTable::Info OptInfo[] = {
#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X6, X7, X8, X9, X10) \
{ \
X1, X2, X9, X10, OPT_##ID, opt::Option::KIND##Class, X8, X7, OPT_##GROUP, \
OPT_##ALIAS, X6 \
- } \
- ,
+ },
#include "Options.inc"
#undef OPTION
};
-class ELFOptTable : public opt::OptTable {
-public:
- ELFOptTable() : OptTable(infoTable) {}
-};
+ELFOptTable::ELFOptTable() : OptTable(OptInfo) {}
+
+static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) {
+ if (auto *Arg = Args.getLastArg(OPT_rsp_quoting)) {
+ StringRef S = Arg->getValue();
+ if (S != "windows" && S != "posix")
+ error("invalid response file quoting: " + S);
+ if (S == "windows")
+ return cl::TokenizeWindowsCommandLine;
+ return cl::TokenizeGNUCommandLine;
+ }
+ if (Triple(sys::getProcessTriple()).getOS() == Triple::Win32)
+ return cl::TokenizeWindowsCommandLine;
+ return cl::TokenizeGNUCommandLine;
+}
// Parses a given list of options.
-opt::InputArgList elf2::parseArgs(llvm::BumpPtrAllocator *A,
- ArrayRef<const char *> Argv) {
+opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> Argv) {
// Make InputArgList from string vectors.
- ELFOptTable Table;
unsigned MissingIndex;
unsigned MissingCount;
+ SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());
+
+ // We need to get the quoting style for response files before parsing all
+ // options so we parse here before and ignore all the options but
+ // --rsp-quoting.
+ opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount);
// Expand response files. '@<filename>' is replaced by the file's contents.
- SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());
- StringSaver Saver(*A);
- llvm::cl::ExpandResponseFiles(Saver, llvm::cl::TokenizeGNUCommandLine, Vec);
+ StringSaver Saver(Alloc);
+ cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), Vec);
// Parse options and then do error checking.
- opt::InputArgList Args = Table.ParseArgs(Vec, MissingIndex, MissingCount);
+ Args = this->ParseArgs(Vec, MissingIndex, MissingCount);
if (MissingCount)
error(Twine("missing arg value for \"") + Args.getArgString(MissingIndex) +
"\", expected " + Twine(MissingCount) +
(MissingCount == 1 ? " argument.\n" : " arguments"));
- iterator_range<opt::arg_iterator> Unknowns = Args.filtered(OPT_UNKNOWN);
- for (auto *Arg : Unknowns)
- warning("warning: unknown argument: " + Arg->getSpelling());
- if (Unknowns.begin() != Unknowns.end())
- error("unknown argument(s) found");
-
+ for (auto *Arg : Args.filtered(OPT_UNKNOWN))
+ error("unknown argument: " + Arg->getSpelling());
return Args;
}
-std::string elf2::findFromSearchPaths(StringRef Path) {
+void elf::printHelp(const char *Argv0) {
+ ELFOptTable Table;
+ Table.PrintHelp(outs(), Argv0, "lld", false);
+}
+
+std::string elf::getVersionString() {
+ std::string Version = getLLDVersion();
+ std::string Repo = getLLDRepositoryVersion();
+ if (Repo.empty())
+ return "LLD " + Version + "\n";
+ return "LLD " + Version + " " + Repo + "\n";
+}
+
+// Makes a given pathname an absolute path first, and then remove
+// beginning /. For example, "../foo.o" is converted to "home/john/foo.o",
+// assuming that the current directory is "/home/john/bar".
+std::string elf::relativeToRoot(StringRef Path) {
+ SmallString<128> Abs = Path;
+ if (std::error_code EC = fs::make_absolute(Abs))
+ fatal("make_absolute failed: " + EC.message());
+ path::remove_dots(Abs, /*remove_dot_dot=*/true);
+
+ // This is Windows specific. root_name() returns a drive letter
+ // (e.g. "c:") or a UNC name (//net). We want to keep it as part
+ // of the result.
+ SmallString<128> Res;
+ StringRef Root = path::root_name(Abs);
+ if (Root.endswith(":"))
+ Res = Root.drop_back();
+ else if (Root.startswith("//"))
+ Res = Root.substr(2);
+
+ path::append(Res, path::relative_path(Abs));
+ return Res.str();
+}
+
+CpioFile::CpioFile(std::unique_ptr<raw_fd_ostream> OS, StringRef S)
+ : OS(std::move(OS)), Basename(S) {}
+
+CpioFile *CpioFile::create(StringRef OutputPath) {
+ std::string Path = (OutputPath + ".cpio").str();
+ std::error_code EC;
+ auto OS = llvm::make_unique<raw_fd_ostream>(Path, EC, fs::F_None);
+ if (EC) {
+ error(EC, "--reproduce: failed to open " + Path);
+ return nullptr;
+ }
+ return new CpioFile(std::move(OS), path::filename(OutputPath));
+}
+
+static void writeMember(raw_fd_ostream &OS, StringRef Path, StringRef Data) {
+ // The c_dev/c_ino pair should be unique according to the spec,
+ // but no one seems to care.
+ OS << "070707"; // c_magic
+ OS << "000000"; // c_dev
+ OS << "000000"; // c_ino
+ OS << "100664"; // c_mode: C_ISREG | rw-rw-r--
+ OS << "000000"; // c_uid
+ OS << "000000"; // c_gid
+ OS << "000001"; // c_nlink
+ OS << "000000"; // c_rdev
+ OS << "00000000000"; // c_mtime
+ OS << format("%06o", Path.size() + 1); // c_namesize
+ OS << format("%011o", Data.size()); // c_filesize
+ OS << Path << '\0'; // c_name
+ OS << Data; // c_filedata
+}
+
+void CpioFile::append(StringRef Path, StringRef Data) {
+ if (!Seen.insert(Path).second)
+ return;
+
+ // Construct an in-archive filename so that /home/foo/bar is stored
+ // as baz/home/foo/bar where baz is the basename of the output file.
+ // (i.e. in that case we are creating baz.cpio.)
+ SmallString<128> Fullpath;
+ path::append(Fullpath, Basename, Path);
+
+ // Use unix path separators so the cpio can be extracted on both unix and
+ // windows.
+ std::replace(Fullpath.begin(), Fullpath.end(), '\\', '/');
+
+ writeMember(*OS, Fullpath, Data);
+
+ // Print the trailer and seek back.
+ // This way we have a valid archive if we crash.
+ uint64_t Pos = OS->tell();
+ writeMember(*OS, "TRAILER!!!", "");
+ OS->seek(Pos);
+}
+
+// Quote a given string if it contains a space character.
+static std::string quote(StringRef S) {
+ if (S.find(' ') == StringRef::npos)
+ return S;
+ return ("\"" + S + "\"").str();
+}
+
+static std::string rewritePath(StringRef S) {
+ if (fs::exists(S))
+ return relativeToRoot(S);
+ return S;
+}
+
+static std::string stringize(opt::Arg *Arg) {
+ std::string K = Arg->getSpelling();
+ if (Arg->getNumValues() == 0)
+ return K;
+ std::string V = quote(Arg->getValue());
+ if (Arg->getOption().getRenderStyle() == opt::Option::RenderJoinedStyle)
+ return K + V;
+ return K + " " + V;
+}
+
+// Reconstructs command line arguments so that so that you can re-run
+// the same command with the same inputs. This is for --reproduce.
+std::string elf::createResponseFile(const opt::InputArgList &Args) {
+ SmallString<0> Data;
+ raw_svector_ostream OS(Data);
+
+ // Copy the command line to the output while rewriting paths.
+ for (auto *Arg : Args) {
+ switch (Arg->getOption().getID()) {
+ case OPT_reproduce:
+ break;
+ case OPT_INPUT:
+ OS << quote(rewritePath(Arg->getValue())) << "\n";
+ break;
+ case OPT_L:
+ case OPT_dynamic_list:
+ case OPT_rpath:
+ case OPT_alias_script_T:
+ case OPT_script:
+ case OPT_version_script:
+ OS << Arg->getSpelling() << " "
+ << quote(rewritePath(Arg->getValue())) << "\n";
+ break;
+ default:
+ OS << stringize(Arg) << "\n";
+ }
+ }
+ return Data.str();
+}
+
+std::string elf::findFromSearchPaths(StringRef Path) {
for (StringRef Dir : Config->SearchPaths) {
std::string FullPath = buildSysrootedPath(Dir, Path);
- if (sys::fs::exists(FullPath))
+ if (fs::exists(FullPath))
return FullPath;
}
return "";
@@ -90,31 +247,30 @@ std::string elf2::findFromSearchPaths(StringRef Path) {
// Searches a given library from input search paths, which are filled
// from -L command line switches. Returns a path to an existent library file.
-std::string elf2::searchLibrary(StringRef Path) {
- std::vector<std::string> Names;
- if (Path[0] == ':') {
- Names.push_back(Path.drop_front());
- } else {
- if (!Config->Static)
- Names.push_back(("lib" + Path + ".so").str());
- Names.push_back(("lib" + Path + ".a").str());
- }
- for (const std::string &Name : Names) {
- std::string S = findFromSearchPaths(Name);
- if (!S.empty())
+std::string elf::searchLibrary(StringRef Path) {
+ if (Path.startswith(":"))
+ return findFromSearchPaths(Path.substr(1));
+ for (StringRef Dir : Config->SearchPaths) {
+ if (!Config->Static) {
+ std::string S = buildSysrootedPath(Dir, ("lib" + Path + ".so").str());
+ if (fs::exists(S))
+ return S;
+ }
+ std::string S = buildSysrootedPath(Dir, ("lib" + Path + ".a").str());
+ if (fs::exists(S))
return S;
}
- error("Unable to find library -l" + Path);
+ return "";
}
// Makes a path by concatenating Dir and File.
// If Dir starts with '=' the result will be preceded by Sysroot,
// which can be set with --sysroot command line switch.
-std::string elf2::buildSysrootedPath(StringRef Dir, StringRef File) {
+std::string elf::buildSysrootedPath(StringRef Dir, StringRef File) {
SmallString<128> Path;
if (Dir.startswith("="))
- sys::path::append(Path, Config->Sysroot, Dir.substr(1), File);
+ path::append(Path, Config->Sysroot, Dir.substr(1), File);
else
- sys::path::append(Path, Dir, File);
+ path::append(Path, Dir, File);
return Path.str();
}
diff --git a/ELF/EhFrame.cpp b/ELF/EhFrame.cpp
new file mode 100644
index 000000000000..b130ac1ca22d
--- /dev/null
+++ b/ELF/EhFrame.cpp
@@ -0,0 +1,167 @@
+//===- EhFrame.cpp -------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// .eh_frame section contains information on how to unwind the stack when
+// an exception is thrown. The section consists of sequence of CIE and FDE
+// records. The linker needs to merge CIEs and associate FDEs to CIEs.
+// That means the linker has to understand the format of the section.
+//
+// This file contains a few utility functions to read .eh_frame contents.
+//
+//===----------------------------------------------------------------------===//
+
+#include "EhFrame.h"
+#include "Error.h"
+
+#include "llvm/Object/ELF.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Support/Endian.h"
+
+using namespace llvm;
+using namespace llvm::ELF;
+using namespace llvm::dwarf;
+using namespace llvm::object;
+using namespace llvm::support::endian;
+
+namespace lld {
+namespace elf {
+
+// .eh_frame section is a sequence of records. Each record starts with
+// a 4 byte length field. This function reads the length.
+template <class ELFT> size_t readEhRecordSize(ArrayRef<uint8_t> D) {
+ const endianness E = ELFT::TargetEndianness;
+ if (D.size() < 4)
+ fatal("CIE/FDE too small");
+
+ // First 4 bytes of CIE/FDE is the size of the record.
+ // If it is 0xFFFFFFFF, the next 8 bytes contain the size instead,
+ // but we do not support that format yet.
+ uint64_t V = read32<E>(D.data());
+ if (V == UINT32_MAX)
+ fatal("CIE/FDE too large");
+ uint64_t Size = V + 4;
+ if (Size > D.size())
+ fatal("CIE/FIE ends past the end of the section");
+ return Size;
+}
+
+// Read a byte and advance D by one byte.
+static uint8_t readByte(ArrayRef<uint8_t> &D) {
+ if (D.empty())
+ fatal("corrupted or unsupported CIE information");
+ uint8_t B = D.front();
+ D = D.slice(1);
+ return B;
+}
+
+// Skip an integer encoded in the LEB128 format.
+// Actual number is not of interest because only the runtime needs it.
+// But we need to be at least able to skip it so that we can read
+// the field that follows a LEB128 number.
+static void skipLeb128(ArrayRef<uint8_t> &D) {
+ while (!D.empty()) {
+ uint8_t Val = D.front();
+ D = D.slice(1);
+ if ((Val & 0x80) == 0)
+ return;
+ }
+ fatal("corrupted or unsupported CIE information");
+}
+
+template <class ELFT> static size_t getAugPSize(unsigned Enc) {
+ switch (Enc & 0x0f) {
+ case DW_EH_PE_absptr:
+ case DW_EH_PE_signed:
+ return ELFT::Is64Bits ? 8 : 4;
+ case DW_EH_PE_udata2:
+ case DW_EH_PE_sdata2:
+ return 2;
+ case DW_EH_PE_udata4:
+ case DW_EH_PE_sdata4:
+ return 4;
+ case DW_EH_PE_udata8:
+ case DW_EH_PE_sdata8:
+ return 8;
+ }
+ fatal("unknown FDE encoding");
+}
+
+template <class ELFT> static void skipAugP(ArrayRef<uint8_t> &D) {
+ uint8_t Enc = readByte(D);
+ if ((Enc & 0xf0) == DW_EH_PE_aligned)
+ fatal("DW_EH_PE_aligned encoding is not supported");
+ size_t Size = getAugPSize<ELFT>(Enc);
+ if (Size >= D.size())
+ fatal("corrupted CIE");
+ D = D.slice(Size);
+}
+
+template <class ELFT> uint8_t getFdeEncoding(ArrayRef<uint8_t> D) {
+ if (D.size() < 8)
+ fatal("CIE too small");
+ D = D.slice(8);
+
+ uint8_t Version = readByte(D);
+ if (Version != 1 && Version != 3)
+ fatal("FDE version 1 or 3 expected, but got " + Twine((unsigned)Version));
+
+ const unsigned char *AugEnd = std::find(D.begin(), D.end(), '\0');
+ if (AugEnd == D.end())
+ fatal("corrupted CIE");
+ StringRef Aug(reinterpret_cast<const char *>(D.begin()), AugEnd - D.begin());
+ D = D.slice(Aug.size() + 1);
+
+ // Code alignment factor should always be 1 for .eh_frame.
+ if (readByte(D) != 1)
+ fatal("CIE code alignment must be 1");
+
+ // Skip data alignment factor.
+ skipLeb128(D);
+
+ // Skip the return address register. In CIE version 1 this is a single
+ // byte. In CIE version 3 this is an unsigned LEB128.
+ if (Version == 1)
+ readByte(D);
+ else
+ skipLeb128(D);
+
+ // We only care about an 'R' value, but other records may precede an 'R'
+ // record. Unfortunately records are not in TLV (type-length-value) format,
+ // so we need to teach the linker how to skip records for each type.
+ for (char C : Aug) {
+ if (C == 'R')
+ return readByte(D);
+ if (C == 'z') {
+ skipLeb128(D);
+ continue;
+ }
+ if (C == 'P') {
+ skipAugP<ELFT>(D);
+ continue;
+ }
+ if (C == 'L') {
+ readByte(D);
+ continue;
+ }
+ fatal("unknown .eh_frame augmentation string: " + Aug);
+ }
+ return DW_EH_PE_absptr;
+}
+
+template size_t readEhRecordSize<ELF32LE>(ArrayRef<uint8_t>);
+template size_t readEhRecordSize<ELF32BE>(ArrayRef<uint8_t>);
+template size_t readEhRecordSize<ELF64LE>(ArrayRef<uint8_t>);
+template size_t readEhRecordSize<ELF64BE>(ArrayRef<uint8_t>);
+
+template uint8_t getFdeEncoding<ELF32LE>(ArrayRef<uint8_t>);
+template uint8_t getFdeEncoding<ELF32BE>(ArrayRef<uint8_t>);
+template uint8_t getFdeEncoding<ELF64LE>(ArrayRef<uint8_t>);
+template uint8_t getFdeEncoding<ELF64BE>(ArrayRef<uint8_t>);
+}
+}
diff --git a/ELF/EhFrame.h b/ELF/EhFrame.h
new file mode 100644
index 000000000000..0d5a2ff2f417
--- /dev/null
+++ b/ELF/EhFrame.h
@@ -0,0 +1,22 @@
+//===- EhFrame.h ------------------------------------------------*- C++ -*-===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLD_ELF_EHFRAME_H
+#define LLD_ELF_EHFRAME_H
+
+#include "lld/Core/LLVM.h"
+
+namespace lld {
+namespace elf {
+template <class ELFT> size_t readEhRecordSize(ArrayRef<uint8_t> Data);
+template <class ELFT> uint8_t getFdeEncoding(ArrayRef<uint8_t> Data);
+}
+}
+
+#endif
diff --git a/ELF/Error.cpp b/ELF/Error.cpp
index e0701f7f4cc6..59a49c17b97c 100644
--- a/ELF/Error.cpp
+++ b/ELF/Error.cpp
@@ -8,31 +8,58 @@
//===----------------------------------------------------------------------===//
#include "Error.h"
+#include "Config.h"
#include "llvm/ADT/Twine.h"
+#include "llvm/Support/Error.h"
#include "llvm/Support/raw_ostream.h"
+using namespace llvm;
+
namespace lld {
-namespace elf2 {
+namespace elf {
+
+bool HasError;
+raw_ostream *ErrorOS;
-void warning(const Twine &Msg) { llvm::errs() << Msg << "\n"; }
+void log(const Twine &Msg) {
+ if (Config->Verbose)
+ outs() << Msg << "\n";
+}
+
+void warning(const Twine &Msg) {
+ if (Config->FatalWarnings)
+ error(Msg);
+ else
+ *ErrorOS << Msg << "\n";
+}
void error(const Twine &Msg) {
- llvm::errs() << Msg << "\n";
- exit(1);
+ *ErrorOS << Msg << "\n";
+ HasError = true;
}
void error(std::error_code EC, const Twine &Prefix) {
- if (!EC)
- return;
error(Prefix + ": " + EC.message());
}
-void error(std::error_code EC) {
- if (!EC)
- return;
- error(EC.message());
+void fatal(const Twine &Msg) {
+ *ErrorOS << Msg << "\n";
+ exit(1);
+}
+
+void fatal(const Twine &Msg, const Twine &Prefix) {
+ fatal(Prefix + ": " + Msg);
+}
+
+void check(std::error_code EC) {
+ if (EC)
+ fatal(EC.message());
+}
+
+void check(Error Err) {
+ check(errorToErrorCode(std::move(Err)));
}
-} // namespace elf2
+} // namespace elf
} // namespace lld
diff --git a/ELF/Error.h b/ELF/Error.h
index b1d2e7a8fc5b..552f50498464 100644
--- a/ELF/Error.h
+++ b/ELF/Error.h
@@ -13,20 +13,49 @@
#include "lld/Core/LLVM.h"
namespace lld {
-namespace elf2 {
+namespace elf {
+extern bool HasError;
+extern llvm::raw_ostream *ErrorOS;
+
+void log(const Twine &Msg);
void warning(const Twine &Msg);
-LLVM_ATTRIBUTE_NORETURN void error(const Twine &Msg);
+void error(const Twine &Msg);
void error(std::error_code EC, const Twine &Prefix);
-void error(std::error_code EC);
template <typename T> void error(const ErrorOr<T> &V, const Twine &Prefix) {
error(V.getError(), Prefix);
}
-template <typename T> void error(const ErrorOr<T> &V) { error(V.getError()); }
-} // namespace elf2
+LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);
+LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg, const Twine &Prefix);
+
+template <class T> T check(ErrorOr<T> E) {
+ if (auto EC = E.getError())
+ fatal(EC.message());
+ return std::move(*E);
+}
+
+template <class T> T check(Expected<T> E) {
+ if (!E)
+ fatal(errorToErrorCode(E.takeError()).message());
+ return std::move(*E);
+}
+
+template <class T> T check(ErrorOr<T> E, const Twine &Prefix) {
+ if (auto EC = E.getError())
+ fatal(EC.message(), Prefix);
+ return std::move(*E);
+}
+
+template <class T> T check(Expected<T> E, const Twine &Prefix) {
+ if (!E)
+ fatal(errorToErrorCode(E.takeError()).message(), Prefix);
+ return std::move(*E);
+}
+
+} // namespace elf
} // namespace lld
#endif
diff --git a/ELF/ICF.cpp b/ELF/ICF.cpp
new file mode 100644
index 000000000000..10a2603b3b3e
--- /dev/null
+++ b/ELF/ICF.cpp
@@ -0,0 +1,345 @@
+//===- ICF.cpp ------------------------------------------------------------===//
+//
+// The LLVM Linker
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// Identical Code Folding is a feature to merge sections not by name (which
+// is regular comdat handling) but by contents. If two non-writable sections
+// have the same data, relocations, attributes, etc., then the two
+// are considered identical and merged by the linker. This optimization
+// makes outputs smaller.
+//
+// ICF is theoretically a problem of reducing graphs by merging as many
+// identical subgraphs as possible if we consider sections as vertices and
+// relocations as edges. It may sound simple, but it is a bit more
+// complicated than you might think. The order of processing sections
+// matters because merging two sections can make other sections, whose
+// relocations now point to the same section, mergeable. Graphs may contain
+// cycles. We need a sophisticated algorithm to do this properly and
+// efficiently.
+//
+// What we do in this file is this. We split sections into groups. Sections
+// in the same group are considered identical.
+//
+// We begin by optimistically putting all sections into a single equivalence
+// class. Then we apply a series of checks that split this initial
+// equivalence class into more and more refined equivalence classes based on
+// the properties by which a section can be distinguished.
+//
+// We begin by checking that the section contents and flags are the
+// same. This only needs to be done once since these properties don't depend
+// on the current equivalence class assignment.
+//
+// Then we split the equivalence classes based on checking that their
+// relocations are the same, where relocation targets are compared by their
+// equivalence class, not the concrete section. This may need to be done
+// multiple times because as the equivalence classes are refined, two
+// sections that had a relocation target in the same equivalence class may
+// now target different equivalence classes, and hence these two sections
+// must be put in different equivalence classes (whereas in the previous
+// iteration they were not since the relocation target was the same.)
+//
+// Our algorithm is smart enough to merge the following mutually-recursive
+// functions.
+//
+// void foo() { bar(); }
+// void bar() { foo(); }
+//
+// This algorithm is so-called "optimistic" algorithm described in
+// http://research.google.com/pubs/pub36912.html. (Note that what GNU
+// gold implemented is different from the optimistic algorithm.)
+//
+//===----------------------------------------------------------------------===//
+
+#include "ICF.h"
+#include "Config.h"
+#include "OutputSections.h"
+#include "SymbolTable.h"
+
+#include "llvm/ADT/Hashing.h"
+#include "llvm/Object/ELF.h"
+#include "llvm/Support/ELF.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace lld;
+using namespace lld::elf;
+using namespace llvm;
+using namespace llvm::ELF;
+using namespace llvm::object;
+
+namespace lld {
+namespace elf {
+template <class ELFT> class ICF {
+ typedef typename ELFT::Shdr Elf_Shdr;
+ typedef typename ELFT::Sym Elf_Sym;
+ typedef typename ELFT::uint uintX_t;
+ typedef Elf_Rel_Impl<ELFT, false> Elf_Rel;
+
+ using Comparator = std::function<bool(const InputSection<ELFT> *,
+ const InputSection<ELFT> *)>;
+
+public:
+ void run();
+
+private:
+ uint64_t NextId = 1;
+
+ static void setLive(SymbolTable<ELFT> *S);
+ static uint64_t relSize(InputSection<ELFT> *S);
+ static uint64_t getHash(InputSection<ELFT> *S);
+ static bool isEligible(InputSectionBase<ELFT> *Sec);
+ static std::vector<InputSection<ELFT> *> getSections();
+
+ void segregate(InputSection<ELFT> **Begin, InputSection<ELFT> **End,
+ Comparator Eq);
+
+ void forEachGroup(std::vector<InputSection<ELFT> *> &V, Comparator Eq);
+
+ template <class RelTy>
+ static bool relocationEq(ArrayRef<RelTy> RA, ArrayRef<RelTy> RB);
+
+ template <class RelTy>
+ static bool variableEq(const InputSection<ELFT> *A,
+ const InputSection<ELFT> *B, ArrayRef<RelTy> RA,
+ ArrayRef<RelTy> RB);
+
+ static bool equalsConstant(const InputSection<ELFT> *A,
+ const InputSection<ELFT> *B);
+
+ static bool equalsVariable(const InputSection<ELFT> *A,
+ const InputSection<ELFT> *B);
+};
+}
+}
+
+// Returns a hash value for S. Note that the information about
+// relocation targets is not included in the hash value.
+template <class ELFT> uint64_t ICF<ELFT>::getHash(InputSection<ELFT> *S) {
+ uint64_t Flags = S->getSectionHdr()->sh_flags;
+ uint64_t H = hash_combine(Flags, S->getSize());
+ for (const Elf_Shdr *Rel : S->RelocSections)
+ H = hash_combine(H, (uint64_t)Rel->sh_size);
+ return H;
+}
+
+// Returns true if Sec is subject of ICF.
+template <class ELFT> bool ICF<ELFT>::isEligible(InputSectionBase<ELFT> *Sec) {
+ if (!Sec || Sec == &InputSection<ELFT>::Discarded || !Sec->Live)
+ return false;
+ auto *S = dyn_cast<InputSection<ELFT>>(Sec);
+ if (!S)
+ return false;
+
+ // .init and .fini contains instructions that must be executed to
+ // initialize and finalize the process. They cannot and should not
+ // be merged.
+ StringRef Name = S->getSectionName();
+ if (Name == ".init" || Name == ".fini")
+ return false;
+
+ const Elf_Shdr &H = *S->getSectionHdr();
+ return (H.sh_flags & SHF_ALLOC) && (~H.sh_flags & SHF_WRITE);
+}
+
+template <class ELFT>
+std::vector<InputSection<ELFT> *> ICF<ELFT>::getSections() {
+ std::vector<InputSection<ELFT> *> V;
+ for (const std::unique_ptr<ObjectFile<ELFT>> &F :
+ Symtab<ELFT>::X->getObjectFiles())
+ for (InputSectionBase<ELFT> *S : F->getSections())
+ if (isEligible(S))
+ V.push_back(cast<InputSection<ELFT>>(S));
+ return V;
+}
+
+// All sections between Begin and End must have the same group ID before
+// you call this function. This function compare sections between Begin
+// and End using Eq and assign new group IDs for new groups.
+template <class ELFT>
+void ICF<ELFT>::segregate(InputSection<ELFT> **Begin, InputSection<ELFT> **End,
+ Comparator Eq) {
+ // This loop rearranges [Begin, End) so that all sections that are
+ // equal in terms of Eq are contiguous. The algorithm is quadratic in
+ // the worst case, but that is not an issue in practice because the
+ // number of distinct sections in [Begin, End) is usually very small.
+ InputSection<ELFT> **I = Begin;
+ for (;;) {
+ InputSection<ELFT> *Head = *I;
+ auto Bound = std::stable_partition(
+ I + 1, End, [&](InputSection<ELFT> *S) { return Eq(Head, S); });
+ if (Bound == End)
+ return;
+ uint64_t Id = NextId++;
+ for (; I != Bound; ++I)
+ (*I)->GroupId = Id;
+ }
+}
+
+template <class ELFT>
+void ICF<ELFT>::forEachGroup(std::vector<InputSection<ELFT> *> &V,
+ Comparator Eq) {
+ for (InputSection<ELFT> **I = V.data(), **E = I + V.size(); I != E;) {
+ InputSection<ELFT> *Head = *I;
+ auto Bound = std::find_if(I + 1, E, [&](InputSection<ELFT> *S) {
+ return S->GroupId != Head->GroupId;
+ });
+ segregate(I, Bound, Eq);
+ I = Bound;
+ }
+}
+
+// Compare two lists of relocations.
+template <class ELFT>
+template <class RelTy>
+bool ICF<ELFT>::relocationEq(ArrayRef<RelTy> RelsA, ArrayRef<RelTy> RelsB) {
+ const RelTy *IA = RelsA.begin();
+ const RelTy *EA = RelsA.end();
+ const RelTy *IB = RelsB.begin();
+ const RelTy *EB = RelsB.end();
+ if (EA - IA != EB - IB)
+ return false;
+ for (; IA != EA; ++IA, ++IB)
+ if (IA->r_offset != IB->r_offset ||
+ IA->getType(Config->Mips64EL) != IB->getType(Config->Mips64EL) ||
+ getAddend<ELFT>(*IA) != getAddend<ELFT>(*IB))
+ return false;
+ return true;
+}
+
+// Compare "non-moving" part of two InputSections, namely everything
+// except relocation targets.
+template <class ELFT>
+bool ICF<ELFT>::equalsConstant(const InputSection<ELFT> *A,
+ const InputSection<ELFT> *B) {
+ if (A->RelocSections.size() != B->RelocSections.size())
+ return false;
+
+ for (size_t I = 0, E = A->RelocSections.size(); I != E; ++I) {
+ const Elf_Shdr *RA = A->RelocSections[I];
+ const Elf_Shdr *RB = B->RelocSections[I];
+ ELFFile<ELFT> &FileA = A->File->getObj();
+ ELFFile<ELFT> &FileB = B->File->getObj();
+ if (RA->sh_type == SHT_RELA) {
+ if (!relocationEq(FileA.relas(RA), FileB.relas(RB)))
+ return false;
+ } else {
+ if (!relocationEq(FileA.rels(RA), FileB.rels(RB)))
+ return false;
+ }
+ }
+
+ return A->getSectionHdr()->sh_flags == B->getSectionHdr()->sh_flags &&
+ A->getSize() == B->getSize() &&
+ A->getSectionData() == B->getSectionData();
+}
+
+template <class ELFT>
+template <class RelTy>