1 ## On Windows co-operative applications can be expected to open LLD's output
2 ## with FILE_SHARE_DELETE included in the sharing mode. This allows us to link
3 ## over the top of an existing file even if it is in use by another application.
5 # REQUIRES: system-windows, x86
6 # RUN: echo '.globl _start; _start:' > %t.s
7 # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-unknown %t.s -o %t.o
10 ## FILE_SHARE_WRITE = 2
11 ## FILE_SHARE_DELETE = 4
13 # RUN: %python %s %t.o 7
14 # RUN: not %python %s %t.o 3 2>&1 | FileCheck %s
15 # CHECK: error: failed to write output '{{.*}}': {{.*}}
19 from ctypes import wintypes as w
27 object_file = sys.argv[1]
28 share_flags = int(sys.argv[2])
30 @contextlib.contextmanager
31 def open_with_share_flags(filename, share_flags):
32 GENERIC_READ = 0x80000000
33 FILE_ATTRIBUTE_NORMAL = 0x80
35 INVALID_HANDLE_VALUE = w.HANDLE(-1).value
37 CreateFileA = ctypes.windll.kernel32.CreateFileA
38 CreateFileA.restype = w.HANDLE
39 h = CreateFileA(filename.encode('mbcs'), GENERIC_READ, share_flags,
40 None, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, None)
42 assert h != INVALID_HANDLE_VALUE, 'Failed to open ' + filename
46 ctypes.windll.kernel32.CloseHandle(h)
48 ## Ensure we have an empty directory for the output.
49 outdir = os.path.basename(__file__) + '.dir'
50 if os.path.exists(outdir):
54 ## Link on top of an open file.
55 elf = os.path.join(outdir, 'output_file.elf')
56 open(elf, 'wb').close()
57 with open_with_share_flags(elf, share_flags):
58 subprocess.check_call(['ld.lld.exe', object_file, '-o', elf])
60 ## Check the linker wrote the output file.
61 with open(elf, 'rb') as f:
62 assert f.read(4) == b'\x7fELF', "linker did not write output file correctly"
64 ## Check no temp files are left around.
65 ## It might take a while for Windows to remove them, so loop.
66 deleted = lambda: len(os.listdir(outdir)) == 1
71 assert deleted(), "temp file(s) not deleted after grace period"