program.go 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584
  1. //
  2. // Copyright 2024 CloudWeGo Authors
  3. //
  4. // Licensed under the Apache License, Version 2.0 (the "License");
  5. // you may not use this file except in compliance with the License.
  6. // You may obtain a copy of the License at
  7. //
  8. // http://www.apache.org/licenses/LICENSE-2.0
  9. //
  10. // Unless required by applicable law or agreed to in writing, software
  11. // distributed under the License is distributed on an "AS IS" BASIS,
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. // See the License for the specific language governing permissions and
  14. // limitations under the License.
  15. //
  16. package x86_64
  17. import (
  18. "fmt"
  19. "math"
  20. "math/bits"
  21. "github.com/cloudwego/iasm/expr"
  22. )
  23. type (
  24. _PseudoType int
  25. _InstructionEncoder func(*Program, ...interface{}) *Instruction
  26. )
  27. const (
  28. _PseudoNop _PseudoType = iota + 1
  29. _PseudoByte
  30. _PseudoWord
  31. _PseudoLong
  32. _PseudoQuad
  33. _PseudoData
  34. _PseudoAlign
  35. )
  36. func (self _PseudoType) String() string {
  37. switch self {
  38. case _PseudoNop:
  39. return ".nop"
  40. case _PseudoByte:
  41. return ".byte"
  42. case _PseudoWord:
  43. return ".word"
  44. case _PseudoLong:
  45. return ".long"
  46. case _PseudoQuad:
  47. return ".quad"
  48. case _PseudoData:
  49. return ".data"
  50. case _PseudoAlign:
  51. return ".align"
  52. default:
  53. panic("unreachable")
  54. }
  55. }
  56. type _Pseudo struct {
  57. kind _PseudoType
  58. data []byte
  59. uint uint64
  60. expr *expr.Expr
  61. }
  62. func (self *_Pseudo) free() {
  63. if self.expr != nil {
  64. self.expr.Free()
  65. }
  66. }
  67. func (self *_Pseudo) encode(m *[]byte, pc uintptr) int {
  68. switch self.kind {
  69. case _PseudoNop:
  70. return 0
  71. case _PseudoByte:
  72. self.encodeByte(m)
  73. return 1
  74. case _PseudoWord:
  75. self.encodeWord(m)
  76. return 2
  77. case _PseudoLong:
  78. self.encodeLong(m)
  79. return 4
  80. case _PseudoQuad:
  81. self.encodeQuad(m)
  82. return 8
  83. case _PseudoData:
  84. self.encodeData(m)
  85. return len(self.data)
  86. case _PseudoAlign:
  87. self.encodeAlign(m, pc)
  88. return self.alignSize(pc)
  89. default:
  90. panic("invalid pseudo instruction")
  91. }
  92. }
  93. func (self *_Pseudo) evalExpr(low int64, high int64) int64 {
  94. if v, err := self.expr.Evaluate(); err != nil {
  95. panic(err)
  96. } else if v < low || v > high {
  97. panic(fmt.Sprintf("expression out of range [%d, %d]: %d", low, high, v))
  98. } else {
  99. return v
  100. }
  101. }
  102. func (self *_Pseudo) alignSize(pc uintptr) int {
  103. if !ispow2(self.uint) {
  104. panic(fmt.Sprintf("aligment should be a power of 2, not %d", self.uint))
  105. } else {
  106. return align(int(pc), bits.TrailingZeros64(self.uint)) - int(pc)
  107. }
  108. }
  109. func (self *_Pseudo) encodeData(m *[]byte) {
  110. if m != nil {
  111. *m = append(*m, self.data...)
  112. }
  113. }
  114. func (self *_Pseudo) encodeByte(m *[]byte) {
  115. if m != nil {
  116. append8(m, byte(self.evalExpr(math.MinInt8, math.MaxUint8)))
  117. }
  118. }
  119. func (self *_Pseudo) encodeWord(m *[]byte) {
  120. if m != nil {
  121. append16(m, uint16(self.evalExpr(math.MinInt16, math.MaxUint16)))
  122. }
  123. }
  124. func (self *_Pseudo) encodeLong(m *[]byte) {
  125. if m != nil {
  126. append32(m, uint32(self.evalExpr(math.MinInt32, math.MaxUint32)))
  127. }
  128. }
  129. func (self *_Pseudo) encodeQuad(m *[]byte) {
  130. if m != nil {
  131. if v, err := self.expr.Evaluate(); err != nil {
  132. panic(err)
  133. } else {
  134. append64(m, uint64(v))
  135. }
  136. }
  137. }
  138. func (self *_Pseudo) encodeAlign(m *[]byte, pc uintptr) {
  139. if m != nil {
  140. if self.expr == nil {
  141. expandmm(m, self.alignSize(pc), 0)
  142. } else {
  143. expandmm(m, self.alignSize(pc), byte(self.evalExpr(math.MinInt8, math.MaxUint8)))
  144. }
  145. }
  146. }
  147. // Operands represents a sequence of operand required by an instruction.
  148. type Operands [_N_args]interface{}
  149. // InstructionDomain represents the domain of an instruction.
  150. type InstructionDomain uint8
  151. const (
  152. DomainGeneric InstructionDomain = iota
  153. DomainMMXSSE
  154. DomainAVX
  155. DomainFMA
  156. DomainCrypto
  157. DomainMask
  158. DomainAMDSpecific
  159. DomainMisc
  160. DomainPseudo
  161. )
  162. type (
  163. _BranchType uint8
  164. )
  165. const (
  166. _B_none _BranchType = iota
  167. _B_conditional
  168. _B_unconditional
  169. )
  170. // Instruction represents an unencoded instruction.
  171. type Instruction struct {
  172. next *Instruction
  173. pc uintptr
  174. nb int
  175. len int
  176. argc int
  177. name string
  178. argv Operands
  179. forms [_N_forms]_Encoding
  180. pseudo _Pseudo
  181. branch _BranchType
  182. domain InstructionDomain
  183. prefix []byte
  184. }
  185. func (self *Instruction) add(flags int, encoder func(m *_Encoding, v []interface{})) {
  186. self.forms[self.len].flags = flags
  187. self.forms[self.len].encoder = encoder
  188. self.len++
  189. }
  190. func (self *Instruction) free() {
  191. self.clear()
  192. self.pseudo.free()
  193. //freeInstruction(self)
  194. }
  195. func (self *Instruction) clear() {
  196. for i := 0; i < self.argc; i++ {
  197. if v, ok := self.argv[i].(Disposable); ok {
  198. v.Free()
  199. }
  200. }
  201. }
  202. func (self *Instruction) check(e *_Encoding) bool {
  203. if (e.flags & _F_rel1) != 0 {
  204. return isRel8(self.argv[0])
  205. } else if (e.flags & _F_rel4) != 0 {
  206. return isRel32(self.argv[0]) || isLabel(self.argv[0])
  207. } else {
  208. return true
  209. }
  210. }
  211. func (self *Instruction) encode(m *[]byte) int {
  212. n := math.MaxInt64
  213. p := (*_Encoding)(nil)
  214. /* encode prefixes if any */
  215. if self.nb = len(self.prefix); m != nil {
  216. *m = append(*m, self.prefix...)
  217. }
  218. /* check for pseudo-instructions */
  219. if self.pseudo.kind != 0 {
  220. self.nb += self.pseudo.encode(m, self.pc)
  221. return self.nb
  222. }
  223. /* find the shortest encoding */
  224. for i := 0; i < self.len; i++ {
  225. if e := &self.forms[i]; self.check(e) {
  226. if v := e.encode(self.argv[:self.argc]); v < n {
  227. n = v
  228. p = e
  229. }
  230. }
  231. }
  232. /* add to buffer if needed */
  233. if m != nil {
  234. *m = append(*m, p.bytes[:n]...)
  235. }
  236. /* update the instruction length */
  237. self.nb += n
  238. return self.nb
  239. }
  240. /** Instruction Prefixes **/
  241. const (
  242. _P_cs = 0x2e
  243. _P_ds = 0x3e
  244. _P_es = 0x26
  245. _P_fs = 0x64
  246. _P_gs = 0x65
  247. _P_ss = 0x36
  248. _P_lock = 0xf0
  249. )
  250. // CS overrides the memory operation of this instruction to CS.
  251. func (self *Instruction) CS() *Instruction {
  252. self.prefix = append(self.prefix, _P_cs)
  253. return self
  254. }
  255. // DS overrides the memory operation of this instruction to DS,
  256. // this is the default section for most instructions if not specified.
  257. func (self *Instruction) DS() *Instruction {
  258. self.prefix = append(self.prefix, _P_ds)
  259. return self
  260. }
  261. // ES overrides the memory operation of this instruction to ES.
  262. func (self *Instruction) ES() *Instruction {
  263. self.prefix = append(self.prefix, _P_es)
  264. return self
  265. }
  266. // FS overrides the memory operation of this instruction to FS.
  267. func (self *Instruction) FS() *Instruction {
  268. self.prefix = append(self.prefix, _P_fs)
  269. return self
  270. }
  271. // GS overrides the memory operation of this instruction to GS.
  272. func (self *Instruction) GS() *Instruction {
  273. self.prefix = append(self.prefix, _P_gs)
  274. return self
  275. }
  276. // SS overrides the memory operation of this instruction to SS.
  277. func (self *Instruction) SS() *Instruction {
  278. self.prefix = append(self.prefix, _P_ss)
  279. return self
  280. }
  281. // LOCK causes the processor's LOCK# signal to be asserted during execution of
  282. // the accompanying instruction (turns the instruction into an atomic instruction).
  283. // In a multiprocessor environment, the LOCK# signal insures that the processor
  284. // has exclusive use of any shared memory while the signal is asserted.
  285. func (self *Instruction) LOCK() *Instruction {
  286. self.prefix = append(self.prefix, _P_lock)
  287. return self
  288. }
  289. /** Basic Instruction Properties **/
  290. // Name returns the instruction name.
  291. func (self *Instruction) Name() string {
  292. return self.name
  293. }
  294. // Domain returns the domain of this instruction.
  295. func (self *Instruction) Domain() InstructionDomain {
  296. return self.domain
  297. }
  298. // Operands returns the operands of this instruction.
  299. func (self *Instruction) Operands() []interface{} {
  300. return self.argv[:self.argc]
  301. }
  302. // Program represents a sequence of instructions.
  303. type Program struct {
  304. arch *Arch
  305. head *Instruction
  306. tail *Instruction
  307. }
  308. const (
  309. _N_near = 2 // near-branch (-128 ~ +127) takes 2 bytes to encode
  310. _N_far_cond = 6 // conditional far-branch takes 6 bytes to encode
  311. _N_far_uncond = 5 // unconditional far-branch takes 5 bytes to encode
  312. )
  313. func (self *Program) clear() {
  314. for p, q := self.head, self.head; p != nil; p = q {
  315. q = p.next
  316. p.free()
  317. }
  318. }
  319. func (self *Program) alloc(name string, argc int, argv Operands) *Instruction {
  320. p := self.tail
  321. q := newInstruction(name, argc, argv)
  322. /* attach to tail if any */
  323. if p != nil {
  324. p.next = q
  325. } else {
  326. self.head = q
  327. }
  328. /* set the new tail */
  329. self.tail = q
  330. return q
  331. }
  332. func (self *Program) pseudo(kind _PseudoType) (p *Instruction) {
  333. p = self.alloc(kind.String(), 0, Operands{})
  334. p.domain = DomainPseudo
  335. p.pseudo.kind = kind
  336. return
  337. }
  338. func (self *Program) require(isa ISA) {
  339. if !self.arch.HasISA(isa) {
  340. panic("ISA '" + isa.String() + "' was not enabled")
  341. }
  342. }
  343. func (self *Program) branchSize(p *Instruction) int {
  344. switch p.branch {
  345. case _B_none:
  346. panic("p is not a branch")
  347. case _B_conditional:
  348. return _N_far_cond
  349. case _B_unconditional:
  350. return _N_far_uncond
  351. default:
  352. panic("invalid instruction")
  353. }
  354. }
  355. /** Pseudo-Instructions **/
  356. // Byte is a pseudo-instruction to add raw byte to the assembled code.
  357. func (self *Program) Byte(v *expr.Expr) (p *Instruction) {
  358. p = self.pseudo(_PseudoByte)
  359. p.pseudo.expr = v
  360. return
  361. }
  362. // Word is a pseudo-instruction to add raw uint16 as little-endian to the assembled code.
  363. func (self *Program) Word(v *expr.Expr) (p *Instruction) {
  364. p = self.pseudo(_PseudoWord)
  365. p.pseudo.expr = v
  366. return
  367. }
  368. // Long is a pseudo-instruction to add raw uint32 as little-endian to the assembled code.
  369. func (self *Program) Long(v *expr.Expr) (p *Instruction) {
  370. p = self.pseudo(_PseudoLong)
  371. p.pseudo.expr = v
  372. return
  373. }
  374. // Quad is a pseudo-instruction to add raw uint64 as little-endian to the assembled code.
  375. func (self *Program) Quad(v *expr.Expr) (p *Instruction) {
  376. p = self.pseudo(_PseudoQuad)
  377. p.pseudo.expr = v
  378. return
  379. }
  380. // Data is a pseudo-instruction to add raw bytes to the assembled code.
  381. func (self *Program) Data(v []byte) (p *Instruction) {
  382. p = self.pseudo(_PseudoData)
  383. p.pseudo.data = v
  384. return
  385. }
  386. // Align is a pseudo-instruction to ensure the PC is aligned to a certain value.
  387. func (self *Program) Align(align uint64, padding *expr.Expr) (p *Instruction) {
  388. p = self.pseudo(_PseudoAlign)
  389. p.pseudo.uint = align
  390. p.pseudo.expr = padding
  391. return
  392. }
  393. /** Program Assembler **/
  394. // Free returns the Program object into pool.
  395. // Any operation performed after Free is undefined behavior.
  396. //
  397. // NOTE: This also frees all the instructions, labels, memory
  398. //
  399. // operands and expressions associated with this program.
  400. func (self *Program) Free() {
  401. self.clear()
  402. //freeProgram(self)
  403. }
  404. // Link pins a label at the current position.
  405. func (self *Program) Link(p *Label) {
  406. if p.Dest != nil {
  407. panic("lable was alreay linked")
  408. } else {
  409. p.Dest = self.pseudo(_PseudoNop)
  410. }
  411. }
  412. // Assemble assembles and links the entire program into machine code.
  413. func (self *Program) Assemble(pc uintptr) (ret []byte) {
  414. orig := pc
  415. next := true
  416. offs := uintptr(0)
  417. /* Pass 0: PC-precompute, assume all labeled branches are far-branches. */
  418. for p := self.head; p != nil; p = p.next {
  419. if p.pc = pc; !isLabel(p.argv[0]) || p.branch == _B_none {
  420. pc += uintptr(p.encode(nil))
  421. } else {
  422. pc += uintptr(self.branchSize(p))
  423. }
  424. }
  425. /* allocate space for the machine code */
  426. nb := int(pc - orig)
  427. ret = make([]byte, 0, nb)
  428. /* Pass 1: adjust all the jumps */
  429. for next {
  430. next = false
  431. offs = uintptr(0)
  432. /* scan all the branches */
  433. for p := self.head; p != nil; p = p.next {
  434. var ok bool
  435. var lb *Label
  436. /* re-calculate the alignment here */
  437. if nb = p.nb; p.pseudo.kind == _PseudoAlign {
  438. p.pc -= offs
  439. offs += uintptr(nb - p.encode(nil))
  440. continue
  441. }
  442. /* adjust the program counter */
  443. p.pc -= offs
  444. lb, ok = p.argv[0].(*Label)
  445. /* only care about labeled far-branches */
  446. if !ok || p.nb == _N_near || p.branch == _B_none {
  447. continue
  448. }
  449. /* calculate the jump offset */
  450. size := self.branchSize(p)
  451. diff := lb.offset(p.pc, size)
  452. /* too far to be a near jump */
  453. if diff > 127 || diff < -128 {
  454. p.nb = size
  455. continue
  456. }
  457. /* a far jump becomes a near jump, calculate
  458. * the PC adjustment value and assemble again */
  459. next = true
  460. p.nb = _N_near
  461. offs += uintptr(size - _N_near)
  462. }
  463. }
  464. /* Pass 3: link all the cross-references */
  465. for p := self.head; p != nil; p = p.next {
  466. for i := 0; i < p.argc; i++ {
  467. var ok bool
  468. var lb *Label
  469. var op *MemoryOperand
  470. /* resolve labels */
  471. if lb, ok = p.argv[i].(*Label); ok {
  472. p.argv[i] = lb.offset(p.pc, p.nb)
  473. continue
  474. }
  475. /* check for memory operands */
  476. if op, ok = p.argv[i].(*MemoryOperand); !ok {
  477. continue
  478. }
  479. /* check for label references */
  480. if op.Addr.Type != Reference {
  481. continue
  482. }
  483. /* replace the label with the real offset */
  484. op.Addr.Type = Offset
  485. op.Addr.Offset = op.Addr.Reference.offset(p.pc, p.nb)
  486. }
  487. }
  488. /* Pass 4: actually encode all the instructions */
  489. for p := self.head; p != nil; p = p.next {
  490. p.encode(&ret)
  491. }
  492. /* all done */
  493. return ret
  494. }
  495. // AssembleAndFree is like Assemble, but it frees the Program after assembling.
  496. func (self *Program) AssembleAndFree(pc uintptr) (ret []byte) {
  497. ret = self.Assemble(pc)
  498. self.Free()
  499. return
  500. }