Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.
 
 
 
 
 
 

1601 строка
46 KiB

  1. // Copyright (c) 2017, Google Inc.
  2. //
  3. // Permission to use, copy, modify, and/or distribute this software for any
  4. // purpose with or without fee is hereby granted, provided that the above
  5. // copyright notice and this permission notice appear in all copies.
  6. //
  7. // THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  8. // WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  9. // MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
  10. // SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  11. // WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
  12. // OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  13. // CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */
  14. // delocate performs several transformations of textual assembly code. See
  15. // crypto/fipsmodule/FIPS.md for an overview.
  16. package main
  17. import (
  18. "errors"
  19. "flag"
  20. "fmt"
  21. "io/ioutil"
  22. "os"
  23. "sort"
  24. "strconv"
  25. "strings"
  26. )
  27. // inputFile represents a textual assembly file.
  28. type inputFile struct {
  29. path string
  30. // index is a unique identifer given to this file. It's used for
  31. // mapping local symbols.
  32. index int
  33. // isArchive indicates that the input should be processed as an ar
  34. // file.
  35. isArchive bool
  36. // contents contains the contents of the file.
  37. contents string
  38. // ast points to the head of the syntax tree.
  39. ast *node32
  40. }
  41. type stringWriter interface {
  42. WriteString(string) (int, error)
  43. }
  44. type processorType int
  45. const (
  46. ppc64le processorType = iota + 1
  47. x86_64
  48. )
  49. // delocation holds the state needed during a delocation operation.
  50. type delocation struct {
  51. processor processorType
  52. output stringWriter
  53. // symbols is the set of symbols defined in the module.
  54. symbols map[string]struct{}
  55. // localEntrySymbols is the set of symbols with .localentry directives.
  56. localEntrySymbols map[string]struct{}
  57. // redirectors maps from out-call symbol name to the name of a
  58. // redirector function for that symbol. E.g. “memcpy” ->
  59. // “bcm_redirector_memcpy”.
  60. redirectors map[string]string
  61. // bssAccessorsNeeded maps from a BSS symbol name to the symbol that
  62. // should be used to reference it. E.g. “P384_data_storage” ->
  63. // “P384_data_storage”.
  64. bssAccessorsNeeded map[string]string
  65. // tocLoaders is a set of symbol names for which TOC helper functions
  66. // are required. (ppc64le only.)
  67. tocLoaders map[string]struct{}
  68. // gotExternalsNeeded is a set of symbol names for which we need
  69. // “delta” symbols: symbols that contain the offset from their location
  70. // to the memory in question.
  71. gotExternalsNeeded map[string]struct{}
  72. currentInput inputFile
  73. }
  74. func (d *delocation) contents(node *node32) string {
  75. return d.currentInput.contents[node.begin:node.end]
  76. }
  77. // writeNode writes out an AST node.
  78. func (d *delocation) writeNode(node *node32) {
  79. if _, err := d.output.WriteString(d.contents(node)); err != nil {
  80. panic(err)
  81. }
  82. }
  83. func (d *delocation) writeCommentedNode(node *node32) {
  84. line := d.contents(node)
  85. if _, err := d.output.WriteString("# WAS " + strings.TrimSpace(line) + "\n"); err != nil {
  86. panic(err)
  87. }
  88. }
  89. func locateError(err error, with *node32, in inputFile) error {
  90. posMap := translatePositions([]rune(in.contents), []int{int(with.begin)})
  91. var line int
  92. for _, pos := range posMap {
  93. line = pos.line
  94. }
  95. return fmt.Errorf("error while processing %q on line %d: %q", in.contents[with.begin:with.end], line, err)
  96. }
  97. func (d *delocation) processInput(input inputFile) (err error) {
  98. d.currentInput = input
  99. var origStatement *node32
  100. defer func() {
  101. if err := recover(); err != nil {
  102. panic(locateError(fmt.Errorf("%s", err), origStatement, input))
  103. }
  104. }()
  105. for statement := input.ast.up; statement != nil; statement = statement.next {
  106. assertNodeType(statement, ruleStatement)
  107. origStatement = statement
  108. node := skipWS(statement.up)
  109. if node == nil {
  110. d.writeNode(statement)
  111. continue
  112. }
  113. switch node.pegRule {
  114. case ruleGlobalDirective, ruleComment, ruleLocationDirective:
  115. d.writeNode(statement)
  116. case ruleDirective:
  117. statement, err = d.processDirective(statement, node.up)
  118. case ruleLabelContainingDirective:
  119. statement, err = d.processLabelContainingDirective(statement, node.up)
  120. case ruleLabel:
  121. statement, err = d.processLabel(statement, node.up)
  122. case ruleInstruction:
  123. switch d.processor {
  124. case x86_64:
  125. statement, err = d.processIntelInstruction(statement, node.up)
  126. case ppc64le:
  127. statement, err = d.processPPCInstruction(statement, node.up)
  128. default:
  129. panic("unknown processor")
  130. }
  131. default:
  132. panic(fmt.Sprintf("unknown top-level statement type %q", rul3s[node.pegRule]))
  133. }
  134. if err != nil {
  135. return locateError(err, origStatement, input)
  136. }
  137. }
  138. return nil
  139. }
  140. func (d *delocation) processDirective(statement, directive *node32) (*node32, error) {
  141. assertNodeType(directive, ruleDirectiveName)
  142. directiveName := d.contents(directive)
  143. var args []string
  144. forEachPath(directive, func(arg *node32) {
  145. // If the argument is a quoted string, use the raw contents.
  146. // (Note that this doesn't unescape the string, but that's not
  147. // needed so far.
  148. if arg.up != nil {
  149. arg = arg.up
  150. assertNodeType(arg, ruleQuotedArg)
  151. if arg.up == nil {
  152. args = append(args, "")
  153. return
  154. }
  155. arg = arg.up
  156. assertNodeType(arg, ruleQuotedText)
  157. }
  158. args = append(args, d.contents(arg))
  159. }, ruleArgs, ruleArg)
  160. switch directiveName {
  161. case "comm", "lcomm":
  162. if len(args) < 1 {
  163. return nil, errors.New("comm directive has no arguments")
  164. }
  165. d.bssAccessorsNeeded[args[0]] = args[0]
  166. d.writeNode(statement)
  167. case "data":
  168. // ASAN and some versions of MSAN are adding a .data section,
  169. // and adding references to symbols within it to the code. We
  170. // will have to work around this in the future.
  171. return nil, errors.New(".data section found in module")
  172. case "section":
  173. section := args[0]
  174. if section == ".data.rel.ro" {
  175. // In a normal build, this is an indication of a
  176. // problem but any references from the module to this
  177. // section will result in a relocation and thus will
  178. // break the integrity check. ASAN can generate these
  179. // sections and so we will likely have to work around
  180. // that in the future.
  181. return nil, errors.New(".data.rel.ro section found in module")
  182. }
  183. sectionType, ok := sectionType(section)
  184. if !ok {
  185. // Unknown sections are permitted in order to be robust
  186. // to different compiler modes.
  187. d.writeNode(statement)
  188. break
  189. }
  190. switch sectionType {
  191. case ".rodata", ".text":
  192. // Move .rodata to .text so it may be accessed without
  193. // a relocation. GCC with -fmerge-constants will place
  194. // strings into separate sections, so we move all
  195. // sections named like .rodata. Also move .text.startup
  196. // so the self-test function is also in the module.
  197. d.writeCommentedNode(statement)
  198. d.output.WriteString(".text\n")
  199. case ".data":
  200. // See above about .data
  201. return nil, errors.New(".data section found in module")
  202. case ".init_array", ".fini_array", ".ctors", ".dtors":
  203. // init_array/ctors/dtors contains function
  204. // pointers to constructor/destructor
  205. // functions. These contain relocations, but
  206. // they're in a different section anyway.
  207. d.writeNode(statement)
  208. break
  209. case ".debug", ".note", ".toc":
  210. d.writeNode(statement)
  211. break
  212. case ".bss":
  213. d.writeNode(statement)
  214. return d.handleBSS(statement)
  215. }
  216. default:
  217. d.writeNode(statement)
  218. }
  219. return statement, nil
  220. }
  221. func (d *delocation) processLabelContainingDirective(statement, directive *node32) (*node32, error) {
  222. // The symbols within directives need to be mapped so that local
  223. // symbols in two different .s inputs don't collide.
  224. changed := false
  225. assertNodeType(directive, ruleLabelContainingDirectiveName)
  226. name := d.contents(directive)
  227. node := directive.next
  228. assertNodeType(node, ruleWS)
  229. node = node.next
  230. assertNodeType(node, ruleSymbolArgs)
  231. var args []string
  232. for node = skipWS(node.up); node != nil; node = skipWS(node.next) {
  233. assertNodeType(node, ruleSymbolArg)
  234. arg := node.up
  235. var mapped string
  236. for term := arg; term != nil; term = term.next {
  237. if term.pegRule != ruleLocalSymbol {
  238. mapped += d.contents(term)
  239. continue
  240. }
  241. oldSymbol := d.contents(term)
  242. newSymbol := d.mapLocalSymbol(oldSymbol)
  243. if newSymbol != oldSymbol {
  244. changed = true
  245. }
  246. mapped += newSymbol
  247. }
  248. args = append(args, mapped)
  249. }
  250. if !changed {
  251. d.writeNode(statement)
  252. } else {
  253. d.writeCommentedNode(statement)
  254. d.output.WriteString("\t" + name + "\t" + strings.Join(args, ", ") + "\n")
  255. }
  256. if name == ".localentry" {
  257. d.output.WriteString(localEntryName(args[0]) + ":\n")
  258. }
  259. return statement, nil
  260. }
  261. func (d *delocation) processLabel(statement, label *node32) (*node32, error) {
  262. symbol := d.contents(label)
  263. switch label.pegRule {
  264. case ruleLocalLabel:
  265. d.output.WriteString(symbol + ":\n")
  266. case ruleLocalSymbol:
  267. // symbols need to be mapped so that local symbols from two
  268. // different .s inputs don't collide.
  269. d.output.WriteString(d.mapLocalSymbol(symbol) + ":\n")
  270. case ruleSymbolName:
  271. d.output.WriteString(localTargetName(symbol) + ":\n")
  272. d.writeNode(statement)
  273. default:
  274. return nil, fmt.Errorf("unknown label type %q", rul3s[label.pegRule])
  275. }
  276. return statement, nil
  277. }
  278. // instructionArgs collects all the arguments to an instruction.
  279. func instructionArgs(node *node32) (argNodes []*node32) {
  280. for node = skipWS(node); node != nil; node = skipWS(node.next) {
  281. assertNodeType(node, ruleInstructionArg)
  282. argNodes = append(argNodes, node.up)
  283. }
  284. return argNodes
  285. }
  286. /* ppc64le
  287. [PABI]: “64-Bit ELF V2 ABI Specification. Power Architecture.” March 21st,
  288. 2017
  289. (Also useful is “Power ISA Version 2.07 B”. Note that version three of that
  290. document is /not/ good as that's POWER9 specific.)
  291. ppc64le doesn't have IP-relative addressing and does a lot to work around this.
  292. Rather than reference a PLT and GOT direction, it has a single structure called
  293. the TOC (Table Of Contents). Within the TOC is the contents of .rodata, .data,
  294. .got, .plt, .bss, etc sections [PABI;3.3].
  295. A pointer to the TOC is maintained in r2 and the following pattern is used to
  296. load the address of an element into a register:
  297. addis <address register>, 2, foo@toc@ha
  298. addi <address register>, <address register>, foo@toc@l
  299. The “addis” instruction shifts a signed constant left 16 bits and adds the
  300. result to its second argument, saving the result in the first argument. The
  301. “addi” instruction does the same, but without shifting. Thus the “@toc@ha"
  302. suffix on a symbol means “the top 16 bits of the TOC offset” and “@toc@l” means
  303. “the bottom 16 bits of the offset”. However, note that both values are signed,
  304. thus offsets in the top half of a 64KB chunk will have an @ha value that's one
  305. greater than expected and a negative @l value.
  306. The TOC is specific to a “module” (basically an executable or shared object).
  307. This means that there's not a single TOC in a process and that r2 needs to
  308. change as control moves between modules. Thus functions have two entry points:
  309. the “global” entry point and the “local” entry point. Jumps from within the
  310. same module can use the local entry while jumps from other modules must use the
  311. global entry. The global entry establishes the correct value of r2 before
  312. running the function and the local entry skips that code.
  313. The global entry point for a function is defined by its label. The local entry
  314. is a power-of-two number of bytes from the global entry, set by the
  315. “.localentry” directive. (ppc64le instructions are always 32 bits, so an offset
  316. of 1 or 2 bytes is treated as an offset of zero.)
  317. In order to help the global entry code set r2 to point to the local TOC, r12 is
  318. set to the address of the global entry point when called [PABI;2.2.1.1]. Thus
  319. the global entry will typically use an addis+addi pair to add a known offset to
  320. r12 and store it in r2. For example:
  321. foo:
  322. addis 2, 12, .TOC. - foo@ha
  323. addi 2, 2, .TOC. - foo@l
  324. (It's worth noting that the '@' operator binds very loosely, so the 3rd
  325. arguments parse as (.TOC. - foo)@ha and (.TOC. - foo)@l.)
  326. When calling a function, the compiler doesn't know whether that function is in
  327. the same module or not. Thus it doesn't know whether r12 needs to be set nor
  328. whether r2 will be clobbered on return. Rather than always assume the worst,
  329. the linker fixes stuff up once it knows that a call is going out of module:
  330. Firstly, calling, say, memcpy (which we assume to be in a different module)
  331. won't actually jump directly to memcpy, or even a PLT resolution function.
  332. It'll call a synthesised function that:
  333. a) saves r2 in the caller's stack frame
  334. b) loads the address of memcpy@PLT into r12
  335. c) jumps to r12.
  336. As this synthesised function loads memcpy@PLT, a call to memcpy from the
  337. compiled code just references “memcpy” directly, not “memcpy@PLT”.
  338. Since it jumps directly to memcpy@PLT, it can't restore r2 on return. Thus
  339. calls must be followed by a nop. If the call ends up going out-of-module, the
  340. linker will rewrite that nop to load r2 from the stack.
  341. Speaking of the stack, the stack pointer is kept in r1 and there's a 288-byte
  342. red-zone. The format of the stack frame is defined [PABI;2.2.2] and must be
  343. followed as called functions will write into their parent's stack frame. For
  344. example, the synthesised out-of-module trampolines will save r2 24 bytes into
  345. the caller's frame and all non-leaf functions save the return address 16 bytes
  346. into the caller's frame.
  347. A final point worth noting: some RISC ISAs have r0 wired to zero: all reads
  348. result in zero and all writes are discarded. POWER does something a little like
  349. that, but r0 is only special in certain argument positions for certain
  350. instructions. You just have to read the manual to know which they are.
  351. Delocation is easier than Intel because there's just TOC references, but it's
  352. also harder because there's no IP-relative addressing.
  353. Jumps are IP-relative however, and have a 24-bit immediate value. So we can
  354. jump to functions that set a register to the needed value. (r3 is the
  355. return-value register and so that's what is generally used here.) */
  356. // isPPC64LEAPair recognises an addis+addi pair that's adding the offset of
  357. // source to relative and writing the result to target.
  358. func (d *delocation) isPPC64LEAPair(statement *node32) (target, source, relative string, ok bool) {
  359. instruction := skipWS(statement.up).up
  360. assertNodeType(instruction, ruleInstructionName)
  361. name1 := d.contents(instruction)
  362. args1 := instructionArgs(instruction.next)
  363. statement = statement.next
  364. instruction = skipWS(statement.up).up
  365. assertNodeType(instruction, ruleInstructionName)
  366. name2 := d.contents(instruction)
  367. args2 := instructionArgs(instruction.next)
  368. if name1 != "addis" ||
  369. len(args1) != 3 ||
  370. name2 != "addi" ||
  371. len(args2) != 3 {
  372. return "", "", "", false
  373. }
  374. target = d.contents(args1[0])
  375. relative = d.contents(args1[1])
  376. source1 := d.contents(args1[2])
  377. source2 := d.contents(args2[2])
  378. if !strings.HasSuffix(source1, "@ha") ||
  379. !strings.HasSuffix(source2, "@l") ||
  380. source1[:len(source1)-3] != source2[:len(source2)-2] ||
  381. d.contents(args2[0]) != target ||
  382. d.contents(args2[1]) != target {
  383. return "", "", "", false
  384. }
  385. source = source1[:len(source1)-3]
  386. ok = true
  387. return
  388. }
  389. // establishTOC writes the global entry prelude for a function. The standard
  390. // prelude involves relocations so this version moves the relocation outside
  391. // the integrity-checked area.
  392. func establishTOC(w stringWriter) {
  393. w.WriteString("999:\n")
  394. w.WriteString("\taddis 2, 12, .LBORINGSSL_external_toc-999b@ha\n")
  395. w.WriteString("\taddi 2, 2, .LBORINGSSL_external_toc-999b@l\n")
  396. w.WriteString("\tld 12, 0(2)\n")
  397. w.WriteString("\tadd 2, 2, 12\n")
  398. }
  399. // loadTOCFuncName returns the name of a synthesized function that sets r3 to
  400. // the value of “symbol+offset”.
  401. func loadTOCFuncName(symbol, offset string) string {
  402. symbol = strings.Replace(symbol, ".", "_dot_", -1)
  403. ret := ".Lbcm_loadtoc_" + symbol
  404. if len(offset) != 0 {
  405. offset = strings.Replace(offset, "+", "_plus_", -1)
  406. offset = strings.Replace(offset, "-", "_minus_", -1)
  407. ret += "_" + offset
  408. }
  409. return ret
  410. }
  411. func (d *delocation) loadFromTOC(w stringWriter, symbol, offset, dest string) wrapperFunc {
  412. d.tocLoaders[symbol+"\x00"+offset] = struct{}{}
  413. return func(k func()) {
  414. w.WriteString("\taddi 1, 1, -288\n") // Clear the red zone.
  415. w.WriteString("\tmflr " + dest + "\n") // Stash the link register.
  416. w.WriteString("\tstd " + dest + ", -8(1)\n")
  417. // The TOC loader will use r3, so stash it if necessary.
  418. if dest != "3" {
  419. w.WriteString("\tstd 3, -16(1)\n")
  420. }
  421. // Because loadTOCFuncName returns a “.L” name, we don't need a
  422. // nop after this call.
  423. w.WriteString("\tbl " + loadTOCFuncName(symbol, offset) + "\n")
  424. // Cycle registers around. We need r3 -> destReg, -8(1) ->
  425. // lr and, optionally, -16(1) -> r3.
  426. w.WriteString("\tstd 3, -24(1)\n")
  427. w.WriteString("\tld 3, -8(1)\n")
  428. w.WriteString("\tmtlr 3\n")
  429. w.WriteString("\tld " + dest + ", -24(1)\n")
  430. if dest != "3" {
  431. w.WriteString("\tld 3, -16(1)\n")
  432. }
  433. w.WriteString("\taddi 1, 1, 288\n")
  434. k()
  435. }
  436. }
  437. func (d *delocation) gatherOffsets(symRef *node32, offsets string) (*node32, string) {
  438. for symRef != nil && symRef.pegRule == ruleOffset {
  439. offset := d.contents(symRef)
  440. if offset[0] != '+' && offset[0] != '-' {
  441. offset = "+" + offset
  442. }
  443. offsets = offsets + offset
  444. symRef = symRef.next
  445. }
  446. return symRef, offsets
  447. }
  448. func (d *delocation) parseMemRef(memRef *node32) (symbol, offset, section string, didChange, symbolIsLocal bool, nextRef *node32) {
  449. if memRef.pegRule != ruleSymbolRef {
  450. return "", "", "", false, false, memRef
  451. }
  452. symRef := memRef.up
  453. nextRef = memRef.next
  454. // (Offset* '+')?
  455. symRef, offset = d.gatherOffsets(symRef, offset)
  456. // (LocalSymbol / SymbolName)
  457. symbol = d.contents(symRef)
  458. if symRef.pegRule == ruleLocalSymbol {
  459. symbolIsLocal = true
  460. mapped := d.mapLocalSymbol(symbol)
  461. if mapped != symbol {
  462. symbol = mapped
  463. didChange = true
  464. }
  465. }
  466. symRef = symRef.next
  467. // Offset*
  468. symRef, offset = d.gatherOffsets(symRef, offset)
  469. // ('@' Section / Offset*)?
  470. if symRef != nil {
  471. assertNodeType(symRef, ruleSection)
  472. section = d.contents(symRef)
  473. symRef = symRef.next
  474. symRef, offset = d.gatherOffsets(symRef, offset)
  475. }
  476. if symRef != nil {
  477. panic(fmt.Sprintf("unexpected token in SymbolRef: %q", rul3s[symRef.pegRule]))
  478. }
  479. return
  480. }
  481. func (d *delocation) processPPCInstruction(statement, instruction *node32) (*node32, error) {
  482. assertNodeType(instruction, ruleInstructionName)
  483. instructionName := d.contents(instruction)
  484. isBranch := instructionName[0] == 'b'
  485. argNodes := instructionArgs(instruction.next)
  486. var wrappers wrapperStack
  487. var args []string
  488. changed := false
  489. Args:
  490. for i, arg := range argNodes {
  491. fullArg := arg
  492. isIndirect := false
  493. if arg.pegRule == ruleIndirectionIndicator {
  494. arg = arg.next
  495. isIndirect = true
  496. }
  497. switch arg.pegRule {
  498. case ruleRegisterOrConstant, ruleLocalLabelRef:
  499. args = append(args, d.contents(fullArg))
  500. case ruleTOCRefLow:
  501. return nil, errors.New("Found low TOC reference outside preamble pattern")
  502. case ruleTOCRefHigh:
  503. target, _, relative, ok := d.isPPC64LEAPair(statement)
  504. if !ok {
  505. return nil, errors.New("Found high TOC reference outside preamble pattern")
  506. }
  507. if relative != "12" {
  508. return nil, fmt.Errorf("preamble is relative to %q, not r12", relative)
  509. }
  510. if target != "2" {
  511. return nil, fmt.Errorf("preamble is setting %q, not r2", target)
  512. }
  513. statement = statement.next
  514. establishTOC(d.output)
  515. instructionName = ""
  516. changed = true
  517. break Args
  518. case ruleMemoryRef:
  519. symbol, offset, section, didChange, symbolIsLocal, memRef := d.parseMemRef(arg.up)
  520. changed = didChange
  521. if len(symbol) > 0 {
  522. if _, localEntrySymbol := d.localEntrySymbols[symbol]; localEntrySymbol && isBranch {
  523. symbol = localEntryName(symbol)
  524. changed = true
  525. } else if _, knownSymbol := d.symbols[symbol]; knownSymbol {
  526. symbol = localTargetName(symbol)
  527. changed = true
  528. } else if !symbolIsLocal && !isSynthesized(symbol) && len(section) == 0 {
  529. changed = true
  530. d.redirectors[symbol] = redirectorName(symbol)
  531. symbol = redirectorName(symbol)
  532. // TODO(davidben): This should sanity-check the next
  533. // instruction is a nop and ideally remove it.
  534. wrappers = append(wrappers, func(k func()) {
  535. k()
  536. // Like the linker's PLT stubs, redirector functions
  537. // expect callers to restore r2.
  538. d.output.WriteString("\tld 2, 24(1)\n")
  539. })
  540. }
  541. }
  542. switch section {
  543. case "":
  544. case "tls":
  545. // This section identifier just tells the
  546. // assembler to use r13, the pointer to the
  547. // thread-local data [PABI;3.7.3.3].
  548. case "toc@ha":
  549. // Delete toc@ha instructions. Per
  550. // [PABI;3.6.3], the linker is allowed to erase
  551. // toc@ha instructions. We take advantage of
  552. // this by unconditionally erasing the toc@ha
  553. // instructions and doing the full lookup when
  554. // processing toc@l.
  555. //
  556. // Note that any offset here applies before @ha
  557. // and @l. That is, 42+foo@toc@ha is
  558. // #ha(42+foo-.TOC.), not 42+#ha(foo-.TOC.). Any
  559. // corresponding toc@l references are required
  560. // by the ABI to have the same offset. The
  561. // offset will be incorporated in full when
  562. // those are processed.
  563. if instructionName != "addis" || len(argNodes) != 3 || i != 2 || args[1] != "2" {
  564. return nil, errors.New("can't process toc@ha reference")
  565. }
  566. changed = true
  567. instructionName = ""
  568. break Args
  569. case "toc@l":
  570. // Per [PAB;3.6.3], this instruction must take
  571. // as input a register which was the output of
  572. // a toc@ha computation and compute the actual
  573. // address of some symbol. The toc@ha
  574. // computation was elided, so we ignore that
  575. // input register and compute the address
  576. // directly.
  577. changed = true
  578. // For all supported toc@l instructions, the
  579. // destination register is the first argument.
  580. destReg := args[0]
  581. wrappers = append(wrappers, d.loadFromTOC(d.output, symbol, offset, destReg))
  582. switch instructionName {
  583. case "addi":
  584. // The original instruction was:
  585. // addi destReg, tocHaReg, offset+symbol@toc@l
  586. instructionName = ""
  587. case "ld", "lhz", "lwz":
  588. // The original instruction was:
  589. // l?? destReg, offset+symbol@toc@l(tocHaReg)
  590. //
  591. // We transform that into the
  592. // equivalent dereference of destReg:
  593. // l?? destReg, 0(destReg)
  594. origInstructionName := instructionName
  595. instructionName = ""
  596. assertNodeType(memRef, ruleBaseIndexScale)
  597. assertNodeType(memRef.up, ruleRegisterOrConstant)
  598. if memRef.next != nil || memRef.up.next != nil {
  599. return nil, errors.New("expected single register in BaseIndexScale for ld argument")
  600. }
  601. baseReg := destReg
  602. if baseReg == "0" {
  603. // Register zero is special as the base register for a load.
  604. // Avoid it by spilling and using r3 instead.
  605. baseReg = "3"
  606. wrappers = append(wrappers, func(k func()) {
  607. d.output.WriteString("\taddi 1, 1, -288\n") // Clear the red zone.
  608. d.output.WriteString("\tstd " + baseReg + ", -8(1)\n")
  609. d.output.WriteString("\tmr " + baseReg + ", " + destReg + "\n")
  610. k()
  611. d.output.WriteString("\tld " + baseReg + ", -8(1)\n")
  612. d.output.WriteString("\taddi 1, 1, 288\n") // Clear the red zone.
  613. })
  614. }
  615. wrappers = append(wrappers, func(k func()) {
  616. d.output.WriteString("\t" + origInstructionName + " " + destReg + ", 0(" + baseReg + ")\n")
  617. })
  618. default:
  619. return nil, fmt.Errorf("can't process TOC argument to %q", instructionName)
  620. }
  621. default:
  622. return nil, fmt.Errorf("Unknown section type %q", section)
  623. }
  624. argStr := ""
  625. if isIndirect {
  626. argStr += "*"
  627. }
  628. argStr += symbol
  629. if len(offset) > 0 {
  630. argStr += offset
  631. }
  632. if len(section) > 0 {
  633. argStr += "@"
  634. argStr += section
  635. }
  636. for ; memRef != nil; memRef = memRef.next {
  637. argStr += d.contents(memRef)
  638. }
  639. args = append(args, argStr)
  640. default:
  641. panic(fmt.Sprintf("unknown instruction argument type %q", rul3s[arg.pegRule]))
  642. }
  643. }
  644. if changed {
  645. d.writeCommentedNode(statement)
  646. var replacement string
  647. if len(instructionName) > 0 {
  648. replacement = "\t" + instructionName + "\t" + strings.Join(args, ", ") + "\n"
  649. }
  650. wrappers.do(func() {
  651. d.output.WriteString(replacement)
  652. })
  653. } else {
  654. d.writeNode(statement)
  655. }
  656. return statement, nil
  657. }
  658. /* Intel */
  659. type instructionType int
  660. const (
  661. instrPush instructionType = iota
  662. instrMove
  663. // instrTransformingMove is essentially a move, but it performs some
  664. // transformation of the data during the process.
  665. instrTransformingMove
  666. instrJump
  667. instrConditionalMove
  668. instrOther
  669. )
  670. func classifyInstruction(instr string, args []*node32) instructionType {
  671. switch instr {
  672. case "push", "pushq":
  673. if len(args) == 1 {
  674. return instrPush
  675. }
  676. case "mov", "movq", "vmovq", "movsd", "vmovsd":
  677. if len(args) == 2 {
  678. return instrMove
  679. }
  680. case "cmovneq", "cmoveq":
  681. if len(args) == 2 {
  682. return instrConditionalMove
  683. }
  684. case "call", "callq", "jmp", "jo", "jno", "js", "jns", "je", "jz", "jne", "jnz", "jb", "jnae", "jc", "jnb", "jae", "jnc", "jbe", "jna", "ja", "jnbe", "jl", "jnge", "jge", "jnl", "jle", "jng", "jg", "jnle", "jp", "jpe", "jnp", "jpo":
  685. if len(args) == 1 {
  686. return instrJump
  687. }
  688. case "vpbroadcastq":
  689. if len(args) == 2 {
  690. return instrTransformingMove
  691. }
  692. }
  693. return instrOther
  694. }
  695. func push(w stringWriter) wrapperFunc {
  696. return func(k func()) {
  697. w.WriteString("\tpushq %rax\n")
  698. k()
  699. w.WriteString("\txchg %rax, (%rsp)\n")
  700. }
  701. }
  702. func (d *delocation) loadFromGOT(w stringWriter, destination, symbol, section string, redzoneCleared bool) wrapperFunc {
  703. d.gotExternalsNeeded[symbol+"@"+section] = struct{}{}
  704. return func(k func()) {
  705. if !redzoneCleared {
  706. w.WriteString("\tleaq -128(%rsp), %rsp\n") // Clear the red zone.
  707. }
  708. w.WriteString("\tpushf\n")
  709. w.WriteString(fmt.Sprintf("\tleaq %s_%s_external(%%rip), %s\n", symbol, section, destination))
  710. w.WriteString(fmt.Sprintf("\taddq (%s), %s\n", destination, destination))
  711. w.WriteString(fmt.Sprintf("\tmovq (%s), %s\n", destination, destination))
  712. w.WriteString("\tpopf\n")
  713. if !redzoneCleared {
  714. w.WriteString("\tleaq\t128(%rsp), %rsp\n")
  715. }
  716. }
  717. }
  718. func saveRegister(w stringWriter) wrapperFunc {
  719. return func(k func()) {
  720. w.WriteString("\tleaq -128(%rsp), %rsp\n") // Clear the red zone.
  721. w.WriteString("\tpushq %rax\n")
  722. k()
  723. w.WriteString("\tpopq %rax\n")
  724. w.WriteString("\tleaq 128(%rsp), %rsp\n")
  725. }
  726. }
  727. func moveTo(w stringWriter, target string, isAVX bool) wrapperFunc {
  728. return func(k func()) {
  729. k()
  730. prefix := ""
  731. if isAVX {
  732. prefix = "v"
  733. }
  734. w.WriteString("\t" + prefix + "movq %rax, " + target + "\n")
  735. }
  736. }
  737. func finalTransform(w stringWriter, transformInstruction, reg string) wrapperFunc {
  738. return func(k func()) {
  739. k()
  740. w.WriteString("\t" + transformInstruction + " " + reg + ", " + reg + "\n")
  741. }
  742. }
  743. func isValidLEATarget(reg string) bool {
  744. return !strings.HasPrefix(reg, "%xmm") && !strings.HasPrefix(reg, "%ymm") && !strings.HasPrefix(reg, "%zmm")
  745. }
  746. func undoConditionalMove(w stringWriter, instr string) wrapperFunc {
  747. var invertedCondition string
  748. switch instr {
  749. case "cmoveq":
  750. invertedCondition = "ne"
  751. case "cmovneq":
  752. invertedCondition = "e"
  753. default:
  754. panic(fmt.Sprintf("don't know how to handle conditional move instruction %q", instr))
  755. }
  756. return func(k func()) {
  757. w.WriteString("\tj" + invertedCondition + " 999f\n")
  758. k()
  759. w.WriteString("999:\n")
  760. }
  761. }
  762. func (d *delocation) isRIPRelative(node *node32) bool {
  763. return node != nil && node.pegRule == ruleBaseIndexScale && d.contents(node) == "(%rip)"
  764. }
  765. func (d *delocation) processIntelInstruction(statement, instruction *node32) (*node32, error) {
  766. assertNodeType(instruction, ruleInstructionName)
  767. instructionName := d.contents(instruction)
  768. argNodes := instructionArgs(instruction.next)
  769. var wrappers wrapperStack
  770. var args []string
  771. changed := false
  772. Args:
  773. for i, arg := range argNodes {
  774. fullArg := arg
  775. isIndirect := false
  776. if arg.pegRule == ruleIndirectionIndicator {
  777. arg = arg.next
  778. isIndirect = true
  779. }
  780. switch arg.pegRule {
  781. case ruleRegisterOrConstant, ruleLocalLabelRef:
  782. args = append(args, d.contents(fullArg))
  783. case ruleMemoryRef:
  784. symbol, offset, section, didChange, symbolIsLocal, memRef := d.parseMemRef(arg.up)
  785. changed = didChange
  786. if symbol == "OPENSSL_ia32cap_P" {
  787. var ok bool
  788. if section == "GOTPCREL" {
  789. ok = instructionName == "movq"
  790. } else if section == "" {
  791. ok = instructionName == "leaq"
  792. }
  793. if !ok {
  794. return nil, fmt.Errorf("instruction %q referenced OPENSSL_ia32cap_P in section %q, should be a movq from GOTPCREL or a direct leaq", instructionName, section)
  795. }
  796. if i != 0 || len(argNodes) != 2 || !d.isRIPRelative(memRef) || len(offset) > 0 {
  797. return nil, fmt.Errorf("invalid OPENSSL_ia32cap_P reference in instruction %q", instructionName)
  798. }
  799. target := argNodes[1]
  800. assertNodeType(target, ruleRegisterOrConstant)
  801. reg := d.contents(target)
  802. if !strings.HasPrefix(reg, "%r") {
  803. return nil, fmt.Errorf("tried to load OPENSSL_ia32cap_P into %q, which is not a standard register.", reg)
  804. }
  805. changed = true
  806. wrappers = append(wrappers, func(k func()) {
  807. d.output.WriteString("\tleaq\t-128(%rsp), %rsp\n") // Clear the red zone.
  808. d.output.WriteString("\tpushfq\n")
  809. d.output.WriteString("\tleaq\tOPENSSL_ia32cap_addr_delta(%rip), " + reg + "\n")
  810. d.output.WriteString("\taddq\t(" + reg + "), " + reg + "\n")
  811. d.output.WriteString("\tpopfq\n")
  812. d.output.WriteString("\tleaq\t128(%rsp), %rsp\n")
  813. })
  814. break Args
  815. }
  816. switch section {
  817. case "":
  818. if _, knownSymbol := d.symbols[symbol]; knownSymbol {
  819. symbol = localTargetName(symbol)
  820. changed = true
  821. }
  822. case "PLT":
  823. if classifyInstruction(instructionName, argNodes) != instrJump {
  824. return nil, fmt.Errorf("Cannot rewrite PLT reference for non-jump instruction %q", instructionName)
  825. }
  826. if _, knownSymbol := d.symbols[symbol]; knownSymbol {
  827. symbol = localTargetName(symbol)
  828. changed = true
  829. } else if !symbolIsLocal && !isSynthesized(symbol) {
  830. // Unknown symbol via PLT is an
  831. // out-call from the module, e.g.
  832. // memcpy.
  833. d.redirectors[symbol+"@"+section] = redirectorName(symbol)
  834. symbol = redirectorName(symbol)
  835. }
  836. changed = true
  837. case "GOTPCREL":
  838. if len(offset) > 0 {
  839. return nil, errors.New("loading from GOT with offset is unsupported")
  840. }
  841. if i != 0 {
  842. return nil, errors.New("GOT access must be source operand")
  843. }
  844. if !d.isRIPRelative(memRef) {
  845. return nil, errors.New("GOT access must be IP-relative")
  846. }
  847. useGOT := false
  848. if _, knownSymbol := d.symbols[symbol]; knownSymbol {
  849. symbol = localTargetName(symbol)
  850. changed = true
  851. } else if !isSynthesized(symbol) {
  852. useGOT = true
  853. }
  854. // Reduce the instruction to movq symbol@GOTPCREL, targetReg.
  855. var targetReg string
  856. switch classifyInstruction(instructionName, argNodes) {
  857. case instrPush:
  858. wrappers = append(wrappers, push(d.output))
  859. targetReg = "%rax"
  860. case instrConditionalMove:
  861. wrappers = append(wrappers, undoConditionalMove(d.output, instructionName))
  862. fallthrough
  863. case instrMove:
  864. assertNodeType(argNodes[1], ruleRegisterOrConstant)
  865. targetReg = d.contents(argNodes[1])
  866. case instrTransformingMove:
  867. assertNodeType(argNodes[1], ruleRegisterOrConstant)
  868. targetReg = d.contents(argNodes[1])
  869. wrappers = append(wrappers, finalTransform(d.output, instructionName, targetReg))
  870. if isValidLEATarget(targetReg) {
  871. return nil, errors.New("Currently transforming moves are assumed to target XMM registers. Otherwise we'll pop %rax before reading it to do the transform.")
  872. }
  873. default:
  874. return nil, fmt.Errorf("Cannot rewrite GOTPCREL reference for instruction %q", instructionName)
  875. }
  876. var redzoneCleared bool
  877. if !isValidLEATarget(targetReg) {
  878. // Sometimes the compiler will load from the GOT to an
  879. // XMM register, which is not a valid target of an LEA
  880. // instruction.
  881. wrappers = append(wrappers, saveRegister(d.output))
  882. isAVX := strings.HasPrefix(instructionName, "v")
  883. wrappers = append(wrappers, moveTo(d.output, targetReg, isAVX))
  884. targetReg = "%rax"
  885. redzoneCleared = true
  886. }
  887. if useGOT {
  888. wrappers = append(wrappers, d.loadFromGOT(d.output, targetReg, symbol, section, redzoneCleared))
  889. } else {
  890. wrappers = append(wrappers, func(k func()) {
  891. d.output.WriteString(fmt.Sprintf("\tleaq\t%s(%%rip), %s\n", symbol, targetReg))
  892. })
  893. }
  894. changed = true
  895. break Args
  896. default:
  897. return nil, fmt.Errorf("Unknown section type %q", section)
  898. }
  899. if !changed && len(section) > 0 {
  900. panic("section was not handled")
  901. }
  902. section = ""
  903. argStr := ""
  904. if isIndirect {
  905. argStr += "*"
  906. }
  907. argStr += symbol
  908. argStr += offset
  909. for ; memRef != nil; memRef = memRef.next {
  910. argStr += d.contents(memRef)
  911. }
  912. args = append(args, argStr)
  913. default:
  914. panic(fmt.Sprintf("unknown instruction argument type %q", rul3s[arg.pegRule]))
  915. }
  916. }
  917. if changed {
  918. d.writeCommentedNode(statement)
  919. replacement := "\t" + instructionName + "\t" + strings.Join(args, ", ") + "\n"
  920. wrappers.do(func() {
  921. d.output.WriteString(replacement)
  922. })
  923. } else {
  924. d.writeNode(statement)
  925. }
  926. return statement, nil
  927. }
  928. func (d *delocation) handleBSS(statement *node32) (*node32, error) {
  929. lastStatement := statement
  930. for statement = statement.next; statement != nil; lastStatement, statement = statement, statement.next {
  931. node := skipWS(statement.up)
  932. if node == nil {
  933. d.writeNode(statement)
  934. continue
  935. }
  936. switch node.pegRule {
  937. case ruleGlobalDirective, ruleComment, ruleInstruction, ruleLocationDirective:
  938. d.writeNode(statement)
  939. case ruleDirective:
  940. directive := node.up
  941. assertNodeType(directive, ruleDirectiveName)
  942. directiveName := d.contents(directive)
  943. if directiveName == "text" || directiveName == "section" || directiveName == "data" {
  944. return lastStatement, nil
  945. }
  946. d.writeNode(statement)
  947. case ruleLabel:
  948. label := node.up
  949. d.writeNode(statement)
  950. if label.pegRule != ruleLocalSymbol {
  951. symbol := d.contents(label)
  952. localSymbol := localTargetName(symbol)
  953. d.output.WriteString(fmt.Sprintf("\n%s:\n", localSymbol))
  954. d.bssAccessorsNeeded[symbol] = localSymbol
  955. }
  956. case ruleLabelContainingDirective:
  957. var err error
  958. statement, err = d.processLabelContainingDirective(statement, node.up)
  959. if err != nil {
  960. return nil, err
  961. }
  962. default:
  963. return nil, fmt.Errorf("unknown BSS statement type %q in %q", rul3s[node.pegRule], d.contents(statement))
  964. }
  965. }
  966. return lastStatement, nil
  967. }
  968. func transform(w stringWriter, inputs []inputFile) error {
  969. // symbols contains all defined symbols.
  970. symbols := make(map[string]struct{})
  971. // localEntrySymbols contains all symbols with a .localentry directive.
  972. localEntrySymbols := make(map[string]struct{})
  973. // fileNumbers is the set of IDs seen in .file directives.
  974. fileNumbers := make(map[int]struct{})
  975. // maxObservedFileNumber contains the largest seen file number in a
  976. // .file directive. Zero is not a valid number.
  977. maxObservedFileNumber := 0
  978. for _, input := range inputs {
  979. forEachPath(input.ast.up, func(node *node32) {
  980. symbol := input.contents[node.begin:node.end]
  981. if _, ok := symbols[symbol]; ok {
  982. panic(fmt.Sprintf("Duplicate symbol found: %q in %q", symbol, input.path))
  983. }
  984. symbols[symbol] = struct{}{}
  985. }, ruleStatement, ruleLabel, ruleSymbolName)
  986. forEachPath(input.ast.up, func(node *node32) {
  987. node = node.up
  988. assertNodeType(node, ruleLabelContainingDirectiveName)
  989. directive := input.contents[node.begin:node.end]
  990. if directive != ".localentry" {
  991. return
  992. }
  993. // Extract the first argument.
  994. node = skipWS(node.next)
  995. assertNodeType(node, ruleSymbolArgs)
  996. node = node.up
  997. assertNodeType(node, ruleSymbolArg)
  998. symbol := input.contents[node.begin:node.end]
  999. if _, ok := localEntrySymbols[symbol]; ok {
  1000. panic(fmt.Sprintf("Duplicate .localentry directive found: %q in %q", symbol, input.path))
  1001. }
  1002. localEntrySymbols[symbol] = struct{}{}
  1003. }, ruleStatement, ruleLabelContainingDirective)
  1004. forEachPath(input.ast.up, func(node *node32) {
  1005. assertNodeType(node, ruleLocationDirective)
  1006. directive := input.contents[node.begin:node.end]
  1007. if !strings.HasPrefix(directive, ".file") {
  1008. return
  1009. }
  1010. parts := strings.Fields(directive)
  1011. if len(parts) == 2 {
  1012. // This is a .file directive with just a
  1013. // filename. Clang appears to generate just one
  1014. // of these at the beginning of the output for
  1015. // the compilation unit. Ignore it.
  1016. return
  1017. }
  1018. fileNo, err := strconv.Atoi(parts[1])
  1019. if err != nil {
  1020. panic(fmt.Sprintf("Failed to parse file number from .file: %q", directive))
  1021. }
  1022. if _, ok := fileNumbers[fileNo]; ok {
  1023. panic(fmt.Sprintf("Duplicate file number %d observed", fileNo))
  1024. }
  1025. fileNumbers[fileNo] = struct{}{}
  1026. if fileNo > maxObservedFileNumber {
  1027. maxObservedFileNumber = fileNo
  1028. }
  1029. }, ruleStatement, ruleLocationDirective)
  1030. }
  1031. processor := x86_64
  1032. if len(inputs) > 0 {
  1033. processor = detectProcessor(inputs[0])
  1034. }
  1035. d := &delocation{
  1036. symbols: symbols,
  1037. localEntrySymbols: localEntrySymbols,
  1038. processor: processor,
  1039. output: w,
  1040. redirectors: make(map[string]string),
  1041. bssAccessorsNeeded: make(map[string]string),
  1042. tocLoaders: make(map[string]struct{}),
  1043. gotExternalsNeeded: make(map[string]struct{}),
  1044. }
  1045. w.WriteString(".text\n")
  1046. w.WriteString(fmt.Sprintf(".file %d \"inserted_by_delocate.c\"\n", maxObservedFileNumber + 1))
  1047. w.WriteString(fmt.Sprintf(".loc %d 1 0\n", maxObservedFileNumber + 1))
  1048. w.WriteString("BORINGSSL_bcm_text_start:\n")
  1049. for _, input := range inputs {
  1050. if err := d.processInput(input); err != nil {
  1051. return err
  1052. }
  1053. }
  1054. w.WriteString(".text\n")
  1055. w.WriteString(fmt.Sprintf(".loc %d 2 0\n", maxObservedFileNumber + 1))
  1056. w.WriteString("BORINGSSL_bcm_text_end:\n")
  1057. // Emit redirector functions. Each is a single jump instruction.
  1058. var redirectorNames []string
  1059. for name := range d.redirectors {
  1060. redirectorNames = append(redirectorNames, name)
  1061. }
  1062. sort.Strings(redirectorNames)
  1063. for _, name := range redirectorNames {
  1064. redirector := d.redirectors[name]
  1065. if d.processor == ppc64le {
  1066. w.WriteString(".section \".toc\", \"aw\"\n")
  1067. w.WriteString(".Lredirector_toc_" + name + ":\n")
  1068. w.WriteString(".quad " + name + "\n")
  1069. w.WriteString(".text\n")
  1070. w.WriteString(".type " + redirector + ", @function\n")
  1071. w.WriteString(redirector + ":\n")
  1072. // |name| will clobber r2, so save it. This is matched by a restore in
  1073. // redirector calls.
  1074. w.WriteString("\tstd 2, 24(1)\n")
  1075. // Load and call |name|'s global entry point.
  1076. w.WriteString("\taddis 12, 2, .Lredirector_toc_" + name + "@toc@ha\n")
  1077. w.WriteString("\tld 12, .Lredirector_toc_" + name + "@toc@l(12)\n")
  1078. w.WriteString("\tmtctr 12\n")
  1079. w.WriteString("\tbctr\n")
  1080. } else {
  1081. w.WriteString(".type " + redirector + ", @function\n")
  1082. w.WriteString(redirector + ":\n")
  1083. w.WriteString("\tjmp\t" + name + "\n")
  1084. }
  1085. }
  1086. var accessorNames []string
  1087. for accessor := range d.bssAccessorsNeeded {
  1088. accessorNames = append(accessorNames, accessor)
  1089. }
  1090. sort.Strings(accessorNames)
  1091. // Emit BSS accessor functions. Each is a single LEA followed by RET.
  1092. for _, name := range accessorNames {
  1093. funcName := accessorName(name)
  1094. w.WriteString(".type " + funcName + ", @function\n")
  1095. w.WriteString(funcName + ":\n")
  1096. target := d.bssAccessorsNeeded[name]
  1097. if d.processor == ppc64le {
  1098. w.WriteString("\taddis 3, 2, " + target + "@toc@ha\n")
  1099. w.WriteString("\taddi 3, 3, " + target + "@toc@l\n")
  1100. w.WriteString("\tblr\n")
  1101. } else {
  1102. w.WriteString("\tleaq\t" + target + "(%rip), %rax\n\tret\n")
  1103. }
  1104. }
  1105. if d.processor == ppc64le {
  1106. loadTOCNames := sortedSet(d.tocLoaders)
  1107. for _, symbolAndOffset := range loadTOCNames {
  1108. parts := strings.SplitN(symbolAndOffset, "\x00", 2)
  1109. symbol, offset := parts[0], parts[1]
  1110. funcName := loadTOCFuncName(symbol, offset)
  1111. ref := symbol + offset
  1112. w.WriteString(".type " + funcName[2:] + ", @function\n")
  1113. w.WriteString(funcName[2:] + ":\n")
  1114. w.WriteString(funcName + ":\n")
  1115. w.WriteString("\taddis 3, 2, " + ref + "@toc@ha\n")
  1116. w.WriteString("\taddi 3, 3, " + ref + "@toc@l\n")
  1117. w.WriteString("\tblr\n")
  1118. }
  1119. w.WriteString(".LBORINGSSL_external_toc:\n")
  1120. w.WriteString(".quad .TOC.-.LBORINGSSL_external_toc\n")
  1121. } else {
  1122. externalNames := sortedSet(d.gotExternalsNeeded)
  1123. for _, name := range externalNames {
  1124. parts := strings.SplitN(name, "@", 2)
  1125. symbol, section := parts[0], parts[1]
  1126. w.WriteString(".type " + symbol + "_" + section + "_external, @object\n")
  1127. w.WriteString(".size " + symbol + "_" + section + "_external, 8\n")
  1128. w.WriteString(symbol + "_" + section + "_external:\n")
  1129. // Ideally this would be .quad foo@GOTPCREL, but clang's
  1130. // assembler cannot emit a 64-bit GOTPCREL relocation. Instead,
  1131. // we manually sign-extend the value, knowing that the GOT is
  1132. // always at the end, thus foo@GOTPCREL has a positive value.
  1133. w.WriteString("\t.long " + symbol + "@" + section + "\n")
  1134. w.WriteString("\t.long 0\n")
  1135. }
  1136. w.WriteString(".type OPENSSL_ia32cap_get, @function\n")
  1137. w.WriteString("OPENSSL_ia32cap_get:\n")
  1138. w.WriteString("\tleaq OPENSSL_ia32cap_P(%rip), %rax\n")
  1139. w.WriteString("\tret\n")
  1140. w.WriteString(".extern OPENSSL_ia32cap_P\n")
  1141. w.WriteString(".type OPENSSL_ia32cap_addr_delta, @object\n")
  1142. w.WriteString(".size OPENSSL_ia32cap_addr_delta, 8\n")
  1143. w.WriteString("OPENSSL_ia32cap_addr_delta:\n")
  1144. w.WriteString(".quad OPENSSL_ia32cap_P-OPENSSL_ia32cap_addr_delta\n")
  1145. }
  1146. w.WriteString(".type BORINGSSL_bcm_text_hash, @object\n")
  1147. w.WriteString(".size BORINGSSL_bcm_text_hash, 64\n")
  1148. w.WriteString("BORINGSSL_bcm_text_hash:\n")
  1149. for _, b := range uninitHashValue {
  1150. w.WriteString(".byte 0x" + strconv.FormatUint(uint64(b), 16) + "\n")
  1151. }
  1152. return nil
  1153. }
  1154. func parseInputs(inputs []inputFile) error {
  1155. for i, input := range inputs {
  1156. var contents string
  1157. if input.isArchive {
  1158. arFile, err := os.Open(input.path)
  1159. if err != nil {
  1160. return err
  1161. }
  1162. defer arFile.Close()
  1163. ar, err := ParseAR(arFile)
  1164. if err != nil {
  1165. return err
  1166. }
  1167. if len(ar) != 1 {
  1168. return fmt.Errorf("expected one file in archive, but found %d", len(ar))
  1169. }
  1170. for _, c := range ar {
  1171. contents = string(c)
  1172. }
  1173. } else {
  1174. inBytes, err := ioutil.ReadFile(input.path)
  1175. if err != nil {
  1176. return err
  1177. }
  1178. contents = string(inBytes)
  1179. }
  1180. asm := Asm{Buffer: contents, Pretty: true}
  1181. asm.Init()
  1182. if err := asm.Parse(); err != nil {
  1183. return fmt.Errorf("error while parsing %q: %s", input.path, err)
  1184. }
  1185. ast := asm.AST()
  1186. inputs[i].contents = contents
  1187. inputs[i].ast = ast
  1188. }
  1189. return nil
  1190. }
  1191. func main() {
  1192. // The .a file, if given, is expected to be an archive of textual
  1193. // assembly sources. That's odd, but CMake really wants to create
  1194. // archive files so it's the only way that we can make it work.
  1195. arInput := flag.String("a", "", "Path to a .a file containing assembly sources")
  1196. outFile := flag.String("o", "", "Path to output assembly")
  1197. flag.Parse()
  1198. if len(*outFile) == 0 {
  1199. fmt.Fprintf(os.Stderr, "Must give argument to -o.\n")
  1200. os.Exit(1)
  1201. }
  1202. var inputs []inputFile
  1203. if len(*arInput) > 0 {
  1204. inputs = append(inputs, inputFile{
  1205. path: *arInput,
  1206. index: 0,
  1207. isArchive: true,
  1208. })
  1209. }
  1210. for i, path := range flag.Args() {
  1211. if len(path) == 0 {
  1212. continue
  1213. }
  1214. inputs = append(inputs, inputFile{
  1215. path: path,
  1216. index: i + 1,
  1217. })
  1218. }
  1219. if err := parseInputs(inputs); err != nil {
  1220. fmt.Fprintf(os.Stderr, "%s\n", err)
  1221. os.Exit(1)
  1222. }
  1223. out, err := os.OpenFile(*outFile, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644)
  1224. if err != nil {
  1225. panic(err)
  1226. }
  1227. defer out.Close()
  1228. if err := transform(out, inputs); err != nil {
  1229. fmt.Fprintf(os.Stderr, "%s\n", err)
  1230. os.Exit(1)
  1231. }
  1232. }
  1233. func forEachPath(node *node32, cb func(*node32), rules ...pegRule) {
  1234. if node == nil {
  1235. return
  1236. }
  1237. if len(rules) == 0 {
  1238. cb(node)
  1239. return
  1240. }
  1241. rule := rules[0]
  1242. childRules := rules[1:]
  1243. for ; node != nil; node = node.next {
  1244. if node.pegRule != rule {
  1245. continue
  1246. }
  1247. if len(childRules) == 0 {
  1248. cb(node)
  1249. } else {
  1250. forEachPath(node.up, cb, childRules...)
  1251. }
  1252. }
  1253. }
  1254. func skipNodes(node *node32, ruleToSkip pegRule) *node32 {
  1255. for ; node != nil && node.pegRule == ruleToSkip; node = node.next {
  1256. }
  1257. return node
  1258. }
  1259. func skipWS(node *node32) *node32 {
  1260. return skipNodes(node, ruleWS)
  1261. }
  1262. func assertNodeType(node *node32, expected pegRule) {
  1263. if rule := node.pegRule; rule != expected {
  1264. panic(fmt.Sprintf("node was %q, but wanted %q", rul3s[rule], rul3s[expected]))
  1265. }
  1266. }
  1267. type wrapperFunc func(func())
  1268. type wrapperStack []wrapperFunc
  1269. func (w *wrapperStack) do(baseCase func()) {
  1270. if len(*w) == 0 {
  1271. baseCase()
  1272. return
  1273. }
  1274. wrapper := (*w)[0]
  1275. *w = (*w)[1:]
  1276. wrapper(func() { w.do(baseCase) })
  1277. }
  1278. // localTargetName returns the name of the local target label for a global
  1279. // symbol named name.
  1280. func localTargetName(name string) string {
  1281. return ".L" + name + "_local_target"
  1282. }
  1283. func localEntryName(name string) string {
  1284. return ".L" + name + "_local_entry"
  1285. }
  1286. func isSynthesized(symbol string) bool {
  1287. return strings.HasSuffix(symbol, "_bss_get") ||
  1288. symbol == "OPENSSL_ia32cap_get" ||
  1289. strings.HasPrefix(symbol, "BORINGSSL_bcm_text_")
  1290. }
  1291. func redirectorName(symbol string) string {
  1292. return "bcm_redirector_" + symbol
  1293. }
  1294. // sectionType returns the type of a section. I.e. a section called “.text.foo”
  1295. // is a “.text” section.
  1296. func sectionType(section string) (string, bool) {
  1297. if len(section) == 0 || section[0] != '.' {
  1298. return "", false
  1299. }
  1300. i := strings.Index(section[1:], ".")
  1301. if i != -1 {
  1302. section = section[:i+1]
  1303. }
  1304. if strings.HasPrefix(section, ".debug_") {
  1305. return ".debug", true
  1306. }
  1307. return section, true
  1308. }
  1309. // accessorName returns the name of the accessor function for a BSS symbol
  1310. // named name.
  1311. func accessorName(name string) string {
  1312. return name + "_bss_get"
  1313. }
  1314. func (d *delocation) mapLocalSymbol(symbol string) string {
  1315. if d.currentInput.index == 0 {
  1316. return symbol
  1317. }
  1318. return symbol + "_BCM_" + strconv.Itoa(d.currentInput.index)
  1319. }
  1320. func detectProcessor(input inputFile) processorType {
  1321. for statement := input.ast.up; statement != nil; statement = statement.next {
  1322. node := skipNodes(statement.up, ruleWS)
  1323. if node == nil || node.pegRule != ruleInstruction {
  1324. continue
  1325. }
  1326. instruction := node.up
  1327. instructionName := input.contents[instruction.begin:instruction.end]
  1328. switch instructionName {
  1329. case "movq", "call", "leaq":
  1330. return x86_64
  1331. case "addis", "addi", "mflr":
  1332. return ppc64le
  1333. }
  1334. }
  1335. panic("processed entire input and didn't recognise any instructions.")
  1336. }
  1337. func sortedSet(m map[string]struct{}) []string {
  1338. ret := make([]string, 0, len(m))
  1339. for key := range m {
  1340. ret = append(ret, key)
  1341. }
  1342. sort.Strings(ret)
  1343. return ret
  1344. }