File support-relro-in-delocator.patch of Package aws-efs-utils
diff -Nru vendor.orig/src/proxy/vendor/aws-lc-fips-sys-0.13.9/aws-lc/util/fipstools/delocate/delocate.go vendor/src/proxy/vendor/aws-lc-fips-sys-0.13.9/aws-lc/util/fipstools/delocate/delocate.go
--- vendor.orig/src/proxy/vendor/aws-lc-fips-sys-0.13.9/aws-lc/util/fipstools/delocate/delocate.go 1970-01-01 01:00:00.000000000 +0100
+++ vendor/src/proxy/vendor/aws-lc-fips-sys-0.13.9/aws-lc/util/fipstools/delocate/delocate.go 2025-11-07 14:32:34.107226406 +0100
@@ -27,6 +27,7 @@
"sort"
"strconv"
"strings"
+ "unicode"
"boringssl.googlesource.com/boringssl/util/ar"
"boringssl.googlesource.com/boringssl/util/fipstools/fipscommon"
@@ -97,6 +98,10 @@
// cpuCapUniqueSymbols represents the set of unique symbols for each
// discovered occurrence of OPENSSL_ia32cap_P.
cpuCapUniqueSymbols []*cpuCapUniqueSymbol
+ // relroLocalLabelToFuncMap contain mappings between local symbols found in
+ // relro sections and their corresponding function symbol. e.g. ".LC53" ->
+ // "aead_aes_gcm_seal_scatter".
+ relroLocalLabelToFuncMap map[string]string
// redirectors maps from out-call symbol name to the name of a
// redirector function for that symbol. E.g. “memcpy” ->
// “bcm_redirector_memcpy”.
@@ -205,6 +210,41 @@
return nil
}
+// skippedLine writes skipped line transform information to the output file.
+func (d *delocation) skippedLine(node *node32) {
+ if isNewLine(d.currentInput.contents, node) {
+ d.output.WriteString(fmt.Sprintf("# SKIPPED newline\n"))
+ } else {
+ d.output.WriteString(fmt.Sprintf("# SKIPPED %s\n", d.currentInput.contents[node.begin:node.end]))
+ }
+}
+
+// maybeSkipRelroStatement determines if a statement under a relro section can
+// be skipped
+func (d *delocation) maybeSkipRelroStatement(node *node32) bool {
+
+ if !isEndOfRelroSection(d.currentInput.contents, node) {
+ d.skippedLine(node)
+ return true
+ }
+
+ return false
+}
+
+// skipRelroSection identifies the relro section and skips all statements under
+// that section. It moves the AST node pointer to the last statement skipped.
+func (d *delocation) skipRelroSection(statement *node32) *node32 {
+ previousStatement := statement
+ for ; statement != nil; statement = statement.next {
+ if !d.maybeSkipRelroStatement(statement) {
+ break
+ }
+ previousStatement = statement
+ }
+
+ return previousStatement
+}
+
func (d *delocation) processDirective(statement, directive *node32) (*node32, error) {
assertNodeType(directive, ruleDirectiveName)
directiveName := d.contents(directive)
@@ -244,14 +284,13 @@
case "section":
section := args[0]
- if section == ".data.rel.ro" {
- // In a normal build, this is an indication of a
- // problem but any references from the module to this
- // section will result in a relocation and thus will
- // break the integrity check. ASAN can generate these
- // sections and so we will likely have to work around
- // that in the future.
- return nil, errors.New(".data.rel.ro section found in module")
+ if strings.HasPrefix(section, ".data.rel.ro") {
+ d.skippedLine(statement)
+ statement = d.skipRelroSection(statement.next)
+ if statement != nil {
+ break
+ }
+ return nil, fmt.Errorf("Failed to skip relro section %s", section)
}
sectionType, ok := sectionType(section)
@@ -722,7 +761,7 @@
/* ppc64le
[PABI]: “64-Bit ELF V2 ABI Specification. Power Architecture.” March 21st,
- 2017
+ 2017
(Also useful is “Power ISA Version 2.07 B”. Note that version three of that
document is /not/ good as that's POWER9 specific.)
@@ -735,8 +774,8 @@
A pointer to the TOC is maintained in r2 and the following pattern is used to
load the address of an element into a register:
- addis <address register>, 2, foo@toc@ha
- addi <address register>, <address register>, foo@toc@l
+ addis <address register>, 2, foo@toc@ha
+ addi <address register>, <address register>, foo@toc@l
The “addis” instruction shifts a signed constant left 16 bits and adds the
result to its second argument, saving the result in the first argument. The
@@ -765,8 +804,8 @@
r12 and store it in r2. For example:
foo:
- addis 2, 12, .TOC. - foo@ha
- addi 2, 2, .TOC. - foo@l
+ addis 2, 12, .TOC. - foo@ha
+ addi 2, 2, .TOC. - foo@l
(It's worth noting that the '@' operator binds very loosely, so the 3rd
arguments parse as (.TOC. - foo)@ha and (.TOC. - foo)@l.)
@@ -779,9 +818,9 @@
Firstly, calling, say, memcpy (which we assume to be in a different module)
won't actually jump directly to memcpy, or even a PLT resolution function.
It'll call a synthesised function that:
- a) saves r2 in the caller's stack frame
- b) loads the address of memcpy@PLT into r12
- c) jumps to r12.
+ a) saves r2 in the caller's stack frame
+ b) loads the address of memcpy@PLT into r12
+ c) jumps to r12.
As this synthesised function loads memcpy@PLT, a call to memcpy from the
compiled code just references “memcpy” directly, not “memcpy@PLT”.
@@ -1413,6 +1452,12 @@
return node != nil && node.pegRule == ruleBaseIndexScale && d.contents(node) == "(%rip)"
}
+type RelroRewrite struct {
+ isRelroRewrite bool
+ symbol string
+ mappedSymbol string
+}
+
func (d *delocation) processIntelInstruction(statement, instruction *node32) (*node32, error) {
assertNodeType(instruction, ruleInstructionName)
instructionName := d.contents(instruction)
@@ -1479,7 +1524,40 @@
switch section {
case "":
- if _, knownSymbol := d.symbols[symbol]; knownSymbol {
+ if _, knownSymbol := d.relroLocalLabelToFuncMap[symbol]; knownSymbol {
+ // Move instruction dereferencing known relro local symbol. Assume
+ // this form:
+ // movq .Labc(%rip), %xmm
+ // relroLocalLabelToFuncMap contains the mapping .Labc->foo.
+ // Transform to
+ // leaq .Lfoo_local_target(%rip), %reg
+ // movq %reg, %xmm
+ // This requires picking an un-used register for the register reg,
+ // that doesn't disturb the code-execution. It can't be the target
+ // register, because this can be a vector register that you can't lea
+ // to. Instead pick a suitable register, save on stack, and reload
+ // a posteriori.
+ // First sanity check number of arguments
+ if len(argNodes) != 2 {
+ panic(fmt.Sprintf("Expected only two arguments\n"))
+ }
+
+ // Get the function symbol that is relocated in a relro section
+ symbol = localTargetName(d.relroLocalLabelToFuncMap[symbol])
+
+ // Transform the opcode and arguments
+ instructionName = "leaq"
+ targetReg := d.contents(argNodes[1])
+ saveRegWrapper, tempReg := saveRegister(d.output, []string{targetReg})
+ wrappers = append(wrappers, saveRegWrapper)
+ wrappers = append(wrappers, func(k func()) {
+ d.output.WriteString(fmt.Sprintf("\tleaq\t%s(%%rip), %s\n", symbol, tempReg))
+ d.output.WriteString(fmt.Sprintf("\tmovq\t%s, %s\n", tempReg, targetReg))
+ })
+ // This will cause the "replacement" string to be set below. But since
+ // we are using wrappers, it's not used.
+ changed = true
+ } else if _, knownSymbol := d.symbols[symbol]; knownSymbol {
symbol = localTargetName(symbol)
changed = true
}
@@ -1835,6 +1913,274 @@
w.WriteString(".size " + funcName + ", .-" + funcName + "\n")
}
+func isNewLine(file string, node *node32) bool {
+ statementName := file[node.begin:node.end];
+ if statementName == "\n" {
+ return true
+ }
+ return false
+}
+
+// isEndOfRelroSection determines if we have reached the end of a relro section.
+// Returns true if we have, false otherwise.
+func isEndOfRelroSection(file string, lineRootNode *node32) bool {
+
+ // The method used to determine whether we have reached the end of a relro
+ // section is to match on all patterns we know the relro section build from.
+ // If we cannot match such a pattern, or if we meet an unexpected pattern,
+ // we return true.
+
+ /* Relro section pattern
+ Statement "\n"
+ */
+ if isNewLine(file, lineRootNode) {
+ return false
+ }
+
+ nodeNext := lineRootNode.up
+
+ /* Relro section pattern
+ Statement "\t.align 8\n"
+ WS "\t"
+ Directive ".align 8"
+ DirectiveName "align"
+ WS " "
+ Args "8"
+ Arg "8"
+ */
+ if matchPatternSearchSubtree(nodeNext, func(node *node32) bool {
+ directiveName := file[node.begin:node.end];
+ if directiveName == "align" {
+ return true
+ }
+ return false
+ }, ruleDirective, ruleDirectiveName) {
+ return false
+ }
+
+ /* Relro section pattern
+ Statement ".LC0:"
+ Label ".LC0:"
+ LocalSymbol ".LC0"
+ */
+ if matchPatternSearchSubtree(nodeNext, func(node *node32) bool {
+ symbolName := file[node.begin:node.end];
+ if strings.HasPrefix(symbolName, ".L") {
+ return true
+ }
+ return false
+ }, ruleLabel, ruleLocalSymbol) {
+ return false
+ }
+
+ /* Relro section pattern
+ Statement "\t.quad\tfoo_init\n"
+ WS "\t"
+ LabelContainingDirective ".quad\tfoo_init"
+ LabelContainingDirectiveName ".quad"
+ WS "\t"
+ SymbolArgs "foo_init" <-- function symbol
+ SymbolArg "foo_init"
+ SymbolExpr "foo_init"
+ SymbolAtom "foo_init"
+ SymbolName "foo_init"
+ */
+ if matchPatternSearchSubtree(nodeNext, func(node *node32) bool {
+ directiveName := file[node.begin:node.end];
+ if directiveName == ".quad" {
+ return true
+ }
+ return false
+ }, ruleLabelContainingDirective, ruleLabelContainingDirectiveName) {
+ return false
+ }
+
+ return true
+}
+
+// isProbablyAfunctionSymbolx86 sanity checks whether a string represents a
+// valid symbol for either ELF or MachO. Does not work for COFF.
+func isProbablyAValidSymbol(symbol string) error {
+ if len(symbol) == 0 {
+ return fmt.Errorf("function symbol %s cannot be empty", symbol)
+ }
+
+ if len(symbol) > 255 {
+ return fmt.Errorf("function symbol %q too long", symbol)
+ }
+
+ if !unicode.IsLetter(rune(symbol[0])) && symbol[0] != '_' {
+ return fmt.Errorf("function symbol %q must start with letter or underscore", symbol)
+ }
+
+ // Usually allows letters, numbers, underscores, and sometimes dots
+ for i, char := range symbol {
+ if !unicode.IsLetter(char) &&
+ !unicode.IsDigit(char) &&
+ char != '_' &&
+ char != '.' {
+ return fmt.Errorf("invalid character for function symbol %q at position %d: %c", symbol, i, char)
+ }
+ }
+
+ if strings.HasPrefix(symbol, ".") {
+ return fmt.Errorf("function symbol %q cannot start with dot", symbol)
+ }
+
+ if strings.Contains(symbol, "@@") {
+ return fmt.Errorf("invalid function symbol %q format: contains @@", symbol)
+ }
+
+ return nil
+}
+
+func findLocalLabelsForRelro(file string, node *node32, relroLocalLabelToFuncMap map[string]string) error {
+ /* .data.rel.ro[.local] pattern
+ Statement "\t.align 8\n"
+ WS "\t"
+ Directive ".align 8"
+ DirectiveName "align"
+ WS " "
+ Args "8"
+ Arg "8"
+ Statement ".LC0:"
+ Label ".LC0:"
+ LocalSymbol ".LC0" <-- local symbol
+ Statement "\n"
+ Statement "\t.quad\tfoo_init\n"
+ WS "\t"
+ LabelContainingDirective ".quad\tfoo_init"
+ LabelContainingDirectiveName ".quad"
+ WS "\t"
+ SymbolArgs "foo_init" <-- function symbol
+ SymbolArg "foo_init"
+ SymbolExpr "foo_init"
+ SymbolAtom "foo_init"
+ SymbolName "foo_init"
+ */
+
+ currentLineRootNode := node
+ for ; currentLineRootNode != nil; currentLineRootNode = currentLineRootNode.next {
+
+ // First, we search for a local symbol in each subtree, skipping the
+ // statement node.
+ localSymbolName := ""
+ if matchPatternSearchSubtree(currentLineRootNode.up, func(node *node32) bool {
+ symbolName := file[node.begin:node.end];
+ if _, exists := relroLocalLabelToFuncMap[symbolName]; exists {
+ panic(fmt.Sprintf("Duplicate symbol found: %q", symbolName))
+ }
+
+ // Sanity check that we have found what we expect to find
+ if !strings.HasPrefix(symbolName, ".L") {
+ panic(fmt.Sprintf("Symbol name syntax is not what was expected: %q", symbolName))
+ }
+
+ localSymbolName = symbolName
+ return true
+ }, ruleLabel, ruleLocalSymbol) {
+
+ // Reaching this point, we have found a local symbol. Now we need to
+ // search for the function symbol. First advance to next statement/line.
+ currentLineRootNode = currentLineRootNode.next
+
+ // We might need to skip a newline
+ if isNewLine(file, currentLineRootNode) {
+ currentLineRootNode = currentLineRootNode.next
+ }
+
+ // The function name should be an argument to a directive
+ if !matchPatternSearchSubtree(currentLineRootNode.up, func(node *node32) bool {
+ functionSymbolName := file[node.begin:node.end]
+ if err := isProbablyAValidSymbol(functionSymbolName); err != nil {
+ panic(err)
+ }
+
+ relroLocalLabelToFuncMap[localSymbolName] = functionSymbolName
+ return true
+ }, ruleLabelContainingDirective, ruleSymbolArgs) {
+ return fmt.Errorf("After finding %q under a .data.rel.ro[.local] section, expected to find a function name\n", localSymbolName)
+ }
+
+ continue
+ }
+
+ // Check if we are at the end of the relro section.
+ if isEndOfRelroSection(file, currentLineRootNode) {
+ break
+ }
+ }
+
+ return nil
+}
+
+// relroLocalLabelToFuncMapping finds relro related sections and maps local
+// labels to function names. Stores the mapping in relroLocalLabelToFuncMap.
+func relroLocalLabelToFuncMapping(input inputFile, relroLocalLabelToFuncMap map[string]string) error {
+
+ /* Assumed pattern
+ Statement "\t.section\t.data.rel.ro.local\n"
+ WS "\t"
+ Directive ".section\t.data.rel.ro.local"
+ DirectiveName "section"
+ WS "\t"
+ Args ".data.rel.ro.local"
+ Arg ".data.rel.ro.local"
+ */
+
+ matchRelRoCb := func(node *node32) bool {
+ sectionType := input.contents[node.begin:node.end];
+ if strings.HasPrefix(sectionType, ".data.rel.ro") ||
+ strings.HasPrefix(sectionType, ".ldata.rel.ro") {
+ return true
+ }
+ return false
+ }
+
+ // Iterate through input file to locate all relro sections. If we find a relro
+ // section then we extract all local symbol <-> function symbol mappings and
+ // save them in relroLocalLabelToFuncMap.
+ currentLineRootNode := input.ast.up
+ for ; currentLineRootNode != nil; currentLineRootNode = currentLineRootNode.next {
+ if matchPatternOneLine(currentLineRootNode, matchRelRoCb,
+ ruleStatement, ruleDirective, ruleArgs, ruleArg) {
+ if err := findLocalLabelsForRelro(input.contents, currentLineRootNode.next, relroLocalLabelToFuncMap); err != nil {
+ return err
+ }
+
+ continue
+ }
+
+ // Sometimes a .set directive is used to alias two local symbol. If we find
+ // one of these, check if the alias is one of our mappings. If it is,
+ // map the aliased value to the known function name.
+ if matchPatternSearchSubtree(currentLineRootNode.up, func(node *node32) bool {
+ directiveName := input.contents[node.begin:node.end];
+ if directiveName == ".set" {
+ return true
+ }
+ return false
+ }, ruleLabelContainingDirective, ruleLabelContainingDirectiveName) {
+
+ if !matchPatternSearchSubtree(currentLineRootNode.up, func(node *node32) bool {
+ labelNames := strings.Split(input.contents[node.begin:node.end], ",")
+ if _, exists := relroLocalLabelToFuncMap[labelNames[1]]; !exists {
+ // Doesn't exist, carry on.
+ return true
+ }
+ relroLocalLabelToFuncMap[labelNames[0]] = relroLocalLabelToFuncMap[labelNames[1]]
+ return true
+ }, ruleLabelContainingDirective, ruleSymbolArgs) {
+ return errors.New("Parsing error for .set directive")
+ }
+
+ continue
+ }
+ }
+
+ return nil
+}
+
func transform(w stringWriter, includes []string, inputs []inputFile, startEndDebugDirectives bool) error {
// symbols contains all defined symbols.
symbols := make(map[string]struct{})
@@ -1849,6 +2195,8 @@
// checksums in .file directives. If it does so, then this script needs
// to match that behaviour otherwise warnings result.
fileDirectivesContainMD5 := false
+ // TODO
+ relroLocalLabelToFuncMap := make(map[string]string)
// OPENSSL_ia32cap_get will be synthesized by this script.
symbols["OPENSSL_ia32cap_get"] = struct{}{}
@@ -1861,6 +2209,11 @@
w.WriteString(fmt.Sprintf("#include <%s>\n", relative))
}
+ processor := x86_64
+ if len(inputs) > 0 {
+ processor = detectProcessor(inputs[0])
+ }
+
for _, input := range inputs {
forEachPath(input.ast.up, func(node *node32) {
symbol := input.contents[node.begin:node.end]
@@ -1923,11 +2276,12 @@
}
}
}, ruleStatement, ruleLocationDirective)
- }
- processor := x86_64
- if len(inputs) > 0 {
- processor = detectProcessor(inputs[0])
+ if processor == x86_64 {
+ if err := relroLocalLabelToFuncMapping(input, relroLocalLabelToFuncMap); err != nil {
+ return err
+ }
+ }
}
commentIndicator := "#"
@@ -1942,6 +2296,7 @@
commentIndicator: commentIndicator,
output: w,
cpuCapUniqueSymbols: []*cpuCapUniqueSymbol{},
+ relroLocalLabelToFuncMap: relroLocalLabelToFuncMap,
redirectors: make(map[string]string),
bssAccessorsNeeded: make(map[string]string),
tocLoaders: make(map[string]struct{}),
@@ -2348,6 +2703,50 @@
}
}
+func matchPatternSearchSubtree(node *node32, matchNode func(*node32) bool, rules ...pegRule) bool {
+ if node == nil {
+ return false
+ }
+
+ rule := rules[0]
+ childRules := rules[1:]
+
+ for ; node != nil; node = node.next {
+ if rule != node.pegRule {
+ continue
+ }
+
+ if len(childRules) == 0 {
+ return matchNode(node)
+ }
+
+ if matchPatternSearchSubtree(node.up, matchNode, childRules...) {
+ return true
+ }
+ }
+
+ return false
+}
+
+func matchPatternOneLine(lineRootNode *node32, matchNode func(*node32) bool, rules ...pegRule) bool {
+ if lineRootNode == nil || len(rules) == 0 {
+ return false
+ }
+
+ rule := rules[0]
+ childRules := rules[1:]
+
+ if rule != lineRootNode.pegRule {
+ return false
+ }
+
+ if len(childRules) == 0 {
+ return matchNode(lineRootNode)
+ }
+
+ return matchPatternSearchSubtree(lineRootNode.up, matchNode, childRules...)
+}
+
func forEachPath(node *node32, cb func(*node32), rules ...pegRule) {
if node == nil {
return
diff -Nru vendor.orig/src/proxy/vendor/aws-lc-fips-sys-0.13.9/aws-lc/util/fipstools/delocate/delocate_test.go vendor/src/proxy/vendor/aws-lc-fips-sys-0.13.9/aws-lc/util/fipstools/delocate/delocate_test.go
--- vendor.orig/src/proxy/vendor/aws-lc-fips-sys-0.13.9/aws-lc/util/fipstools/delocate/delocate_test.go 1970-01-01 01:00:00.000000000 +0100
+++ vendor/src/proxy/vendor/aws-lc-fips-sys-0.13.9/aws-lc/util/fipstools/delocate/delocate_test.go 2025-11-07 14:32:34.108146224 +0100
@@ -56,6 +56,7 @@
{"x86_64-Sections", nil, []string{"in.s"}, "out.s", true},
{"x86_64-ThreeArg", nil, []string{"in.s"}, "out.s", true},
{"x86_64-FourArg", nil, []string{"in.s"}, "out.s", true},
+ {"x86_64-Relro", nil, []string{"in.s"}, "out.s", true},
{"aarch64-Basic", nil, []string{"in.s"}, "out.s", true},
}
diff -Nru vendor.orig/src/proxy/vendor/aws-lc-fips-sys-0.13.9/aws-lc/util/fipstools/delocate/testdata/x86_64-Relro/in.s vendor/src/proxy/vendor/aws-lc-fips-sys-0.13.9/aws-lc/util/fipstools/delocate/testdata/x86_64-Relro/in.s
--- vendor.orig/src/proxy/vendor/aws-lc-fips-sys-0.13.9/aws-lc/util/fipstools/delocate/testdata/x86_64-Relro/in.s 1970-01-01 01:00:00.000000000 +0100
+++ vendor/src/proxy/vendor/aws-lc-fips-sys-0.13.9/aws-lc/util/fipstools/delocate/testdata/x86_64-Relro/in.s 2025-11-07 14:32:34.108400458 +0100
@@ -0,0 +1,47 @@
+ .text
+ .globl foo
+foo:
+ ret
+ .globl foofoo
+foofoo:
+ ret
+
+ # relro references.
+ movq %rdx, %xmm1
+ movl $419, (%rax)
+ movups %xmm0, 4(%rax)
+ movq .L00(%rip), %xmm0
+ movl $2, 20(%rax)
+ punpcklqdq %xmm1, %xmm0
+ movups %xmm0, 24(%rax)
+ addq $8, %rsp
+
+ movq .LC02(%rip), %xmm2
+
+ .section .data.rel.ro.local,"aw"
+ .align 8
+.L00:
+ .quad foo
+.LC02:
+ .quad foofoo
+
+ # Should be left alone.
+ .section .init_array,"aw"
+ .align 8
+ .quad oof
+
+ .section .data.rel.ro
+ .align 8
+.LD100:
+ .quad foofoofoo
+
+ # Should be left alone.
+ .section .rodata
+ .align 16
+
+ .text
+ movq .LD100(%rip), %xmm1
+
+ .globl foofoofoo
+foofoofoo:
+ ret
diff -Nru vendor.orig/src/proxy/vendor/aws-lc-fips-sys-0.13.9/aws-lc/util/fipstools/delocate/testdata/x86_64-Relro/out.s vendor/src/proxy/vendor/aws-lc-fips-sys-0.13.9/aws-lc/util/fipstools/delocate/testdata/x86_64-Relro/out.s
--- vendor.orig/src/proxy/vendor/aws-lc-fips-sys-0.13.9/aws-lc/util/fipstools/delocate/testdata/x86_64-Relro/out.s 1970-01-01 01:00:00.000000000 +0100
+++ vendor/src/proxy/vendor/aws-lc-fips-sys-0.13.9/aws-lc/util/fipstools/delocate/testdata/x86_64-Relro/out.s 2025-11-07 14:32:34.108510627 +0100
@@ -0,0 +1,127 @@
+.text
+.file 1 "inserted_by_delocate.c"
+.loc 1 1 0
+.type BORINGSSL_bcm_text_hash, @object
+.size BORINGSSL_bcm_text_hash, 32
+BORINGSSL_bcm_text_hash:
+.byte 0xae
+.byte 0x2c
+.byte 0xea
+.byte 0x2a
+.byte 0xbd
+.byte 0xa6
+.byte 0xf3
+.byte 0xec
+.byte 0x97
+.byte 0x7f
+.byte 0x9b
+.byte 0xf6
+.byte 0x94
+.byte 0x9a
+.byte 0xfc
+.byte 0x83
+.byte 0x68
+.byte 0x27
+.byte 0xcb
+.byte 0xa0
+.byte 0xa0
+.byte 0x9f
+.byte 0x6b
+.byte 0x6f
+.byte 0xde
+.byte 0x52
+.byte 0xcd
+.byte 0xe2
+.byte 0xcd
+.byte 0xff
+.byte 0x31
+.byte 0x80
+BORINGSSL_bcm_text_start:
+ .text
+ .globl foo
+.Lfoo_local_target:
+foo:
+ ret
+ .globl foofoo
+.Lfoofoo_local_target:
+foofoo:
+ ret
+
+ # relro references.
+ movq %rdx, %xmm1
+ movl $419, (%rax)
+ movups %xmm0, 4(%rax)
+# WAS movq .L00(%rip), %xmm0
+ leaq -128(%rsp), %rsp
+ pushq %rax
+ leaq .Lfoo_local_target(%rip), %rax
+ movq %rax, %xmm0
+ popq %rax
+ leaq 128(%rsp), %rsp
+ movl $2, 20(%rax)
+ punpcklqdq %xmm1, %xmm0
+ movups %xmm0, 24(%rax)
+ addq $8, %rsp
+
+# WAS movq .LC02(%rip), %xmm2
+ leaq -128(%rsp), %rsp
+ pushq %rax
+ leaq .Lfoofoo_local_target(%rip), %rax
+ movq %rax, %xmm2
+ popq %rax
+ leaq 128(%rsp), %rsp
+
+# SKIPPED .section .data.rel.ro.local,"aw"
+
+# SKIPPED .align 8
+
+# SKIPPED .L00:
+# SKIPPED newline
+# SKIPPED .quad foo
+
+# SKIPPED .LC02:
+# SKIPPED newline
+# SKIPPED .quad foofoo
+
+# SKIPPED newline
+ # Should be left alone.
+ .section .init_array,"aw"
+ .align 8
+ .quad oof
+
+# SKIPPED .section .data.rel.ro
+
+# SKIPPED .align 8
+
+# SKIPPED .LD100:
+# SKIPPED newline
+# SKIPPED .quad foofoofoo
+
+# SKIPPED newline
+ # Should be left alone.
+# WAS .section .rodata
+.text
+ .align 16
+
+ .text
+# WAS movq .LD100(%rip), %xmm1
+ leaq -128(%rsp), %rsp
+ pushq %rax
+ leaq .Lfoofoofoo_local_target(%rip), %rax
+ movq %rax, %xmm1
+ popq %rax
+ leaq 128(%rsp), %rsp
+
+ .globl foofoofoo
+.Lfoofoofoo_local_target:
+foofoofoo:
+ ret
+.text
+.loc 1 2 0
+BORINGSSL_bcm_text_end:
+.type OPENSSL_ia32cap_get, @function
+.globl OPENSSL_ia32cap_get
+.LOPENSSL_ia32cap_get_local_target:
+OPENSSL_ia32cap_get:
+ leaq OPENSSL_ia32cap_P(%rip), %rax
+ ret