delocate: put emitted labels in a specific file.

Otherwise Clang has to assign a file entry to the label which conflicts with
later, explicit, file entries.

Change-Id: Ifc782821517aa7b48ba3ef304d4468f2bc850ac2
Reviewed-on: https://boringssl-review.googlesource.com/27544
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
diff --git a/util/fipstools/delocate.go b/util/fipstools/delocate.go
index 7f45b87..827e446 100644
--- a/util/fipstools/delocate.go
+++ b/util/fipstools/delocate.go
@@ -1158,6 +1158,11 @@
 	symbols := make(map[string]struct{})
 	// localEntrySymbols contains all symbols with a .localentry directive.
 	localEntrySymbols := make(map[string]struct{})
+	// fileNumbers is the set of IDs seen in .file directives.
+	fileNumbers := make(map[int]struct{})
+	// maxObservedFileNumber contains the largest seen file number in a
+	// .file directive. Zero is not a valid number.
+	maxObservedFileNumber := 0
 
 	for _, input := range inputs {
 		forEachPath(input.ast.up, func(node *node32) {
@@ -1186,6 +1191,35 @@
 			}
 			localEntrySymbols[symbol] = struct{}{}
 		}, ruleStatement, ruleLabelContainingDirective)
+
+		forEachPath(input.ast.up, func(node *node32) {
+			assertNodeType(node, ruleLocationDirective)
+			directive := input.contents[node.begin:node.end]
+			if !strings.HasPrefix(directive, ".file") {
+				return
+			}
+			parts := strings.Fields(directive)
+			if len(parts) == 2 {
+				// This is a .file directive with just a
+				// filename. Clang appears to generate just one
+				// of these at the beginning of the output for
+				// the compilation unit. Ignore it.
+				return
+			}
+			fileNo, err := strconv.Atoi(parts[1])
+			if err != nil {
+				panic(fmt.Sprintf("Failed to parse file number from .file: %q", directive))
+			}
+
+			if _, ok := fileNumbers[fileNo]; ok {
+				panic(fmt.Sprintf("Duplicate file number %d observed", fileNo))
+			}
+			fileNumbers[fileNo] = struct{}{}
+
+			if fileNo > maxObservedFileNumber {
+				maxObservedFileNumber = fileNo
+			}
+		}, ruleStatement, ruleLocationDirective)
 	}
 
 	processor := x86_64
@@ -1204,7 +1238,10 @@
 		gotExternalsNeeded: make(map[string]struct{}),
 	}
 
-	w.WriteString(".text\nBORINGSSL_bcm_text_start:\n")
+	w.WriteString(".text\n")
+	w.WriteString(fmt.Sprintf(".file %d \"inserted_by_delocate.c\"\n", maxObservedFileNumber + 1))
+	w.WriteString(fmt.Sprintf(".loc %d 1 0\n", maxObservedFileNumber + 1))
+	w.WriteString("BORINGSSL_bcm_text_start:\n")
 
 	for _, input := range inputs {
 		if err := d.processInput(input); err != nil {
@@ -1212,7 +1249,9 @@
 		}
 	}
 
-	w.WriteString(".text\nBORINGSSL_bcm_text_end:\n")
+	w.WriteString(".text\n")
+	w.WriteString(fmt.Sprintf(".loc %d 2 0\n", maxObservedFileNumber + 1))
+	w.WriteString("BORINGSSL_bcm_text_end:\n")
 
 	// Emit redirector functions. Each is a single jump instruction.
 	var redirectorNames []string
diff --git a/util/fipstools/testdata/ppc64le-GlobalEntry/out.s b/util/fipstools/testdata/ppc64le-GlobalEntry/out.s
index 56f5b5f..304f697 100644
--- a/util/fipstools/testdata/ppc64le-GlobalEntry/out.s
+++ b/util/fipstools/testdata/ppc64le-GlobalEntry/out.s
@@ -1,4 +1,6 @@
 .text
+.file 1 "inserted_by_delocate.c"
+.loc 1 1 0
 BORINGSSL_bcm_text_start:
 	.text
 .Lfoo_local_target:
@@ -19,6 +21,7 @@
 
 	bl
 .text
+.loc 1 2 0
 BORINGSSL_bcm_text_end:
 .LBORINGSSL_external_toc:
 .quad .TOC.-.LBORINGSSL_external_toc
diff --git a/util/fipstools/testdata/ppc64le-LoadToR0/out.s b/util/fipstools/testdata/ppc64le-LoadToR0/out.s
index c42dbe0..5fdbeb8 100644
--- a/util/fipstools/testdata/ppc64le-LoadToR0/out.s
+++ b/util/fipstools/testdata/ppc64le-LoadToR0/out.s
@@ -1,4 +1,6 @@
 .text
+.file 1 "inserted_by_delocate.c"
+.loc 1 1 0
 BORINGSSL_bcm_text_start:
 	.text
 .Lfoo_local_target:
@@ -23,6 +25,7 @@
 	ld 3, -8(1)
 	addi 1, 1, 288
 .text
+.loc 1 2 0
 BORINGSSL_bcm_text_end:
 .type bcm_loadtoc_bar, @function
 bcm_loadtoc_bar:
diff --git a/util/fipstools/testdata/ppc64le-Sample/out.s b/util/fipstools/testdata/ppc64le-Sample/out.s
index 5823d62..e3d682e 100644
--- a/util/fipstools/testdata/ppc64le-Sample/out.s
+++ b/util/fipstools/testdata/ppc64le-Sample/out.s
@@ -1,4 +1,6 @@
 .text
+.file 1 "inserted_by_delocate.c"
+.loc 1 1 0
 BORINGSSL_bcm_text_start:
 	.file	"foo.c"
 	.abiversion 2
@@ -415,6 +417,7 @@
 	.ident	"GCC: (Ubuntu 4.9.2-10ubuntu13) 4.9.2"
 	.section	.note.GNU-stack,"",@progbits
 .text
+.loc 1 2 0
 BORINGSSL_bcm_text_end:
 .section ".toc", "aw"
 .Lredirector_toc_fprintf:
diff --git a/util/fipstools/testdata/ppc64le-Sample2/out.s b/util/fipstools/testdata/ppc64le-Sample2/out.s
index 3e9c3cb..54cbd6f 100644
--- a/util/fipstools/testdata/ppc64le-Sample2/out.s
+++ b/util/fipstools/testdata/ppc64le-Sample2/out.s
@@ -1,4 +1,6 @@
 .text
+.file 1 "inserted_by_delocate.c"
+.loc 1 1 0
 BORINGSSL_bcm_text_start:
 	.file	"foo.c"
 	.abiversion 2
@@ -534,6 +536,7 @@
 	.ident	"GCC: (Ubuntu 4.9.2-10ubuntu13) 4.9.2"
 	.section	.note.GNU-stack,"",@progbits
 .text
+.loc 1 2 0
 BORINGSSL_bcm_text_end:
 .section ".toc", "aw"
 .Lredirector_toc___fprintf_chk:
diff --git a/util/fipstools/testdata/ppc64le-TOCWithOffset/out.s b/util/fipstools/testdata/ppc64le-TOCWithOffset/out.s
index b43523a..2fff0ef 100644
--- a/util/fipstools/testdata/ppc64le-TOCWithOffset/out.s
+++ b/util/fipstools/testdata/ppc64le-TOCWithOffset/out.s
@@ -1,4 +1,6 @@
 .text
+.file 1 "inserted_by_delocate.c"
+.loc 1 1 0
 BORINGSSL_bcm_text_start:
 	.text
 .Lfoo_local_target:
@@ -99,6 +101,7 @@
 	ld 3, -16(1)
 	addi 1, 1, 288
 .text
+.loc 1 2 0
 BORINGSSL_bcm_text_end:
 .type bcm_loadtoc__dot_Lfoo_local_target, @function
 bcm_loadtoc__dot_Lfoo_local_target:
diff --git a/util/fipstools/testdata/x86_64-BSS/out.s b/util/fipstools/testdata/x86_64-BSS/out.s
index 77dc40d..5c576d9 100644
--- a/util/fipstools/testdata/x86_64-BSS/out.s
+++ b/util/fipstools/testdata/x86_64-BSS/out.s
@@ -1,4 +1,6 @@
 .text
+.file 1 "inserted_by_delocate.c"
+.loc 1 1 0
 BORINGSSL_bcm_text_start:
 	.text
 	movq %rax, %rax
@@ -41,6 +43,7 @@
 
 	.quad 0
 .text
+.loc 1 2 0
 BORINGSSL_bcm_text_end:
 .type aes_128_ctr_generic_storage_bss_get, @function
 aes_128_ctr_generic_storage_bss_get:
diff --git a/util/fipstools/testdata/x86_64-Basic/out.s b/util/fipstools/testdata/x86_64-Basic/out.s
index a03b5d7..02a6025 100644
--- a/util/fipstools/testdata/x86_64-Basic/out.s
+++ b/util/fipstools/testdata/x86_64-Basic/out.s
@@ -1,4 +1,6 @@
 .text
+.file 2 "inserted_by_delocate.c"
+.loc 2 1 0
 BORINGSSL_bcm_text_start:
 	# Most instructions and lines should pass unaltered. This is made up of
 	# copy-and-pasted bits of compiler output and likely does not actually
@@ -51,6 +53,7 @@
 .size	foo, .-foo
 .type	foo, @function
 .text
+.loc 2 2 0
 BORINGSSL_bcm_text_end:
 .type OPENSSL_ia32cap_get, @function
 OPENSSL_ia32cap_get:
diff --git a/util/fipstools/testdata/x86_64-GOTRewrite/out.s b/util/fipstools/testdata/x86_64-GOTRewrite/out.s
index 0420af6..0485c87 100644
--- a/util/fipstools/testdata/x86_64-GOTRewrite/out.s
+++ b/util/fipstools/testdata/x86_64-GOTRewrite/out.s
@@ -1,4 +1,6 @@
 .text
+.file 1 "inserted_by_delocate.c"
+.loc 1 1 0
 BORINGSSL_bcm_text_start:
 	.text
 .Lfoo_local_target:
@@ -148,6 +150,7 @@
 
 .comm foobar,64,32
 .text
+.loc 1 2 0
 BORINGSSL_bcm_text_end:
 .type foobar_bss_get, @function
 foobar_bss_get:
diff --git a/util/fipstools/testdata/x86_64-LabelRewrite/out.s b/util/fipstools/testdata/x86_64-LabelRewrite/out.s
index 5dd8feb..4a01853 100644
--- a/util/fipstools/testdata/x86_64-LabelRewrite/out.s
+++ b/util/fipstools/testdata/x86_64-LabelRewrite/out.s
@@ -1,4 +1,6 @@
 .text
+.file 1 "inserted_by_delocate.c"
+.loc 1 1 0
 BORINGSSL_bcm_text_start:
 	.type foo, @function
 	.globl foo
@@ -82,6 +84,7 @@
 	.quad	.L2_BCM_1-.L1_BCM_1
 
 .text
+.loc 1 2 0
 BORINGSSL_bcm_text_end:
 .type bcm_redirector_memcpy, @function
 bcm_redirector_memcpy:
diff --git a/util/fipstools/testdata/x86_64-Sections/out.s b/util/fipstools/testdata/x86_64-Sections/out.s
index 768fef3..ba427ad 100644
--- a/util/fipstools/testdata/x86_64-Sections/out.s
+++ b/util/fipstools/testdata/x86_64-Sections/out.s
@@ -1,4 +1,6 @@
 .text
+.file 1 "inserted_by_delocate.c"
+.loc 1 1 0
 BORINGSSL_bcm_text_start:
 	# .text stays in .text
 	.text
@@ -43,6 +45,7 @@
 	.byte	0x1
 	.long	.L3
 .text
+.loc 1 2 0
 BORINGSSL_bcm_text_end:
 .type OPENSSL_ia32cap_get, @function
 OPENSSL_ia32cap_get: