• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "assembler/elf_assembler.h"
17 
18 namespace assembler {
19 /* These used in ModRM mode when an instruction is encoded. */
20 const uint8 kSubModReg = 5;
21 const uint8 kAndModReg = 4;
22 const uint8 kOrModReg = 1;
23 const uint8 kXorModReg = 6;
24 const uint8 kNotModReg = 2;
25 const uint8 kNegModReg = 3;
26 const uint8 kIdivModReg = 7;
27 const uint8 kDivModReg = 6;
28 const uint8 kShlModReg = 4;
29 const uint8 kSarModReg = 7;
30 const uint8 kShrModReg = 5;
31 const uint8 kJmpModReg = 4;
32 const uint8 kCmpModReg = 7;
33 const uint8 kCallModReg = 2;
34 
35 /* override function in base class */
InitialFileInfo(const std::string & inputFileName)36 void ElfAssembler::InitialFileInfo(const std::string &inputFileName)
37 {
38     /* Initialize some sections that must be used. */
39     DataSection *nullDataSection = new DataSection(" ", SHT_NULL, 0, 0);
40     RegisterSection(*nullDataSection);
41     strTabSection = new StringSection(".strtab", SHT_STRTAB, 0, 1);
42     RegisterSection(*strTabSection);
43     textSection = new DataSection(".text", SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR, k8Bits);
44     RegisterSection(*textSection);
45     symbolTabSection = new SymbolSection(".symtab", SHT_SYMTAB, 0, k8Bits, *strTabSection);
46     RegisterSection(*symbolTabSection);
47 }
48 
EmitVariable(int64 symIdx,uint64 sizeInByte,uint8 alignInByte,SymbolAttr symAttr,SectionKind sectionKind)49 void ElfAssembler::EmitVariable(int64 symIdx, uint64 sizeInByte, uint8 alignInByte, SymbolAttr symAttr,
50                                 SectionKind sectionKind)
51 {
52     switch (sectionKind) {
53         case kSBss:
54         case kSComm:
55         case kSTbss:
56             EmitBssSectionVar(symIdx, sizeInByte, alignInByte, symAttr);
57             break;
58         case kSTdata:
59         case kSData:
60             EmitDataSectionVar(symIdx);
61             break;
62         case kSRodata:
63             if (rodataSection == nullptr) {
64                 rodataSection = new DataSection(".rodata", SHT_PROGBITS, SHF_ALLOC, k8Bits);
65                 RegisterSection(*rodataSection);
66             }
67             UpdateLabel(symIdx, LabelType::kConst, rodataSection->GetDataSize());
68             break;
69         case kSText:
70             UpdateLabel(symIdx);
71             break;
72         case kSDebugInfo:
73         case kSDebugAbbrev:
74         case kSDebugStr:
75         default:
76             assert(false && "unprocessed Section in EmitVariable");
77             break;
78     }
79 }
80 
EmitFloatValue(int64 symIdx,int64 value,size_t valueSize)81 void ElfAssembler::EmitFloatValue(int64 symIdx, int64 value, size_t valueSize)
82 {
83     auto reloffset = codeBuff.size();
84     Encodeb(value, valueSize);
85 
86     if (valueSize == maplebe::k4ByteSize) {
87         UpdateLabel(symIdx, LabelType::kFloatLabel, reloffset);
88     } else if (valueSize == maplebe::k8ByteSize) {
89         UpdateLabel(symIdx, LabelType::kDoubleLabel, reloffset);
90     } else {
91         CHECK_FATAL(false, "--Err: EmitFloatValue only handle float and double value");
92     }
93 }
94 
EmitBssSectionVar(int64 symIdx,uint64 sizeInByte,uint8 alignInByte,SymbolAttr symAttr)95 void ElfAssembler::EmitBssSectionVar(int64 symIdx, uint64 sizeInByte, uint8 alignInByte, SymbolAttr symAttr)
96 {
97     if (bssSection == nullptr) {
98         bssSection = new DataSection(".bss", SHT_NOBITS, SHF_WRITE | SHF_ALLOC, k8Bits);
99         RegisterSection(*bssSection);
100     }
101     uint64 bssCurSize = bssSection->GetSectionSize();
102     bssSection->SetSectionSize(static_cast<Xword>(bssCurSize + sizeInByte));
103     if (symAttr == kSALocal) {
104         const std::string &symbolName = GetNameFromSymMap(symIdx, true);
105         auto nameIndex = strTabSection->AddString(symbolName);
106         AddSymToSymTab({static_cast<Word>(nameIndex), static_cast<uint8>((STB_LOCAL << 4) + (STT_OBJECT & 0xf)), 0,
107                         bssSection->GetIndex(), bssCurSize, sizeInByte},
108                        symIdx);
109         UpdateLabel(symIdx, LabelType::kLocalUninitialized, static_cast<uint32>(bssCurSize));
110     } else {
111         const std::string &symbolName = GetNameFromSymMap(symIdx);
112         auto nameIndex = strTabSection->AddString(symbolName);
113         AddSymToSymTab({static_cast<Word>(nameIndex), static_cast<uint8>((STB_GLOBAL << 4) + (STT_OBJECT & 0xf)), 0,
114                         SHN_COMMON, static_cast<Address>(alignInByte), sizeInByte},
115                        symIdx);
116         UpdateLabel(symIdx, LabelType::kGlobalUninitialized, static_cast<uint32>(bssCurSize));
117     }
118 }
119 
EmitDataSectionVar(int64 symIdx)120 void ElfAssembler::EmitDataSectionVar(int64 symIdx)
121 {
122     if (dataSection == nullptr) {
123         dataSection = new DataSection(".data", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, k8Bits);
124         RegisterSection(*dataSection);
125     }
126     uint32 pos = dataSection->GetDataSize();
127     UpdateLabel(symIdx, LabelType::kStatic, pos);
128 }
129 
EmitFunctionHeader(int64 symIdx,SymbolAttr funcAttr,const std::string * secName)130 void ElfAssembler::EmitFunctionHeader(int64 symIdx, SymbolAttr funcAttr, const std::string *secName)
131 {
132     const auto &emitMemoryManager = maplebe::CGOptions::GetInstance().GetEmitMemoryManager();
133     if (emitMemoryManager.funcAddressSaver != nullptr) {
134         const std::string &funcName = GetNameFromSymMap(symIdx);
135         emitMemoryManager.funcAddressSaver(emitMemoryManager.codeSpace, funcName,
136             static_cast<uint32>(lastModulePC + codeBuff.size()));
137     }
138     UpdateLabel(symIdx, LabelType::kFunc, static_cast<uint32>(codeBuff.size()));
139 }
140 
EmitBBLabel(int64 labelSymIdx,bool genVerboseInfo,uint32 freq,const std::string * mirName)141 void ElfAssembler::EmitBBLabel(int64 labelSymIdx, bool genVerboseInfo, uint32 freq, const std::string *mirName)
142 {
143     UpdateLabel(labelSymIdx, LabelType::kBBLabel, static_cast<uint32>(codeBuff.size()));
144 }
145 
EmitJmpTableElem(int64 jmpLabelIdx,const std::vector<int64> & labelSymIdxs)146 void ElfAssembler::EmitJmpTableElem(int64 jmpLabelIdx, const std::vector<int64> &labelSymIdxs)
147 {
148     UpdateLabel(jmpLabelIdx, LabelType::kJmpLabel, static_cast<uint32>(codeBuff.size()));
149     const size_t kLabelSize = 8;
150     for (auto labelSymIdx : labelSymIdxs) {
151         AppendFixup(labelSymIdx, kAbsolute64, {static_cast<uint32>(codeBuff.size()), kLabelSize}, fixups);
152         uint8 imm = 0;
153         Encodeb(imm, kLabelSize);
154     }
155 }
156 
EmitFunctionFoot(int64 symIdx,SymbolAttr funcAttr)157 void ElfAssembler::EmitFunctionFoot(int64 symIdx, SymbolAttr funcAttr)
158 {
159     uint64 funcSymValue = static_cast<uint64>(GetLabelRelOffset(symIdx));
160     uint64 funcSymSize = static_cast<uint64>(GetLabelSize(symIdx));
161     uint8 funcSymType = STB_GLOBAL;
162     switch (funcAttr) {
163         case kSALocal:
164             funcSymType = STB_LOCAL;
165             break;
166         case kSAGlobal:
167             funcSymType = STB_GLOBAL;
168             break;
169         case kSAWeak:
170             funcSymType = STB_WEAK;
171             break;
172         case kSAStatic:
173         case kSAHidden:
174         default:
175             assert(false && "unkonwn/unsupport SymbolAttr in EmitFunctionFoot");
176             break;
177     }
178     const std::string &symbolName = GetNameFromSymMap(symIdx);
179     auto nameIndex = strTabSection->AddString(symbolName);
180     AddSymToSymTab({static_cast<Word>(nameIndex),
181                     static_cast<uint8>((funcSymType << kLeftShift4Bits) + (STT_FUNC & 0xf)), 0, textSection->GetIndex(),
182                     funcSymValue, funcSymSize},
183                    symIdx);
184 }
185 
EmitDirectString(const std::string & str,bool belongsToDataSec,int64 strSymIdx,bool emitAscii)186 void ElfAssembler::EmitDirectString(const std::string &str, bool belongsToDataSec, int64 strSymIdx, bool emitAscii)
187 {
188     /* Add a terminator to a string. */
189     std::string ustr = str;
190     ustr += '\0';
191     if (strSymIdx != 0) {
192         if (dataSection == nullptr) {
193             dataSection = new DataSection(".data", SHT_PROGBITS, SHF_WRITE | SHF_ALLOC, k8Bits);
194             RegisterSection(*dataSection);
195         }
196         uint32 pos = dataSection->GetDataSize();
197         UpdateLabel(strSymIdx, LabelType::kStrLabel, pos);
198         dataSection->AppendData(ustr.data(), ustr.size());
199         const size_t kStrAlignSize = 8;
200         /* append size, append 0 when align need. */
201         size_t appendSize = kStrAlignSize - ustr.size() % kStrAlignSize;
202         int64 appendData = 0;
203         dataSection->AppendData(appendData, appendSize);
204     } else {
205         if (belongsToDataSec) {
206             dataSection->AppendData(ustr.data(), ustr.size());
207         } else {
208             rodataSection->AppendData(ustr.data(), ustr.size());
209         }
210     }
211 }
212 
EmitIndirectString(int64 strSymIdx,bool belongsToDataSec)213 void ElfAssembler::EmitIndirectString(int64 strSymIdx, bool belongsToDataSec)
214 {
215     const size_t kStrAddrSize = 8;
216     uint32 pos = 0;
217     int64 addr = 0;
218     if (belongsToDataSec) {
219         pos = dataSection->GetDataSize();
220         dataSection->AppendData(addr, kStrAddrSize);
221         AppendFixup(strSymIdx, kAbsolute64, {pos, kStrAddrSize}, dataFixups);
222     } else {
223         pos = rodataSection->GetDataSize();
224         rodataSection->AppendData(addr, kStrAddrSize);
225         AppendFixup(strSymIdx, kAbsolute64, {pos, kStrAddrSize}, rodataFixups);
226     }
227 }
228 
EmitIntValue(int64 value,size_t valueSize,bool belongsToDataSec)229 void ElfAssembler::EmitIntValue(int64 value, size_t valueSize, bool belongsToDataSec)
230 {
231     if (belongsToDataSec) {
232         dataSection->AppendData(value, valueSize);
233     } else {
234         rodataSection->AppendData(value, valueSize);
235     }
236 }
237 
EmitAddrValue(int64 symIdx,int32 symAddrOfs,int32 structFieldOfs,bool belongsToDataSec)238 void ElfAssembler::EmitAddrValue(int64 symIdx, int32 symAddrOfs, int32 structFieldOfs, bool belongsToDataSec)
239 {
240     const size_t kAddrSize = 8;
241     uint32 pos = 0;
242     int64 addr = 0;
243     if (belongsToDataSec) {
244         pos = dataSection->GetDataSize();
245         dataSection->AppendData(addr, kAddrSize);
246         AppendFixup(symIdx, kAbsolute64, {pos, kAddrSize}, dataFixups, symAddrOfs);
247     } else {
248         pos = rodataSection->GetDataSize();
249         rodataSection->AppendData(addr, kAddrSize);
250         AppendFixup(symIdx, kAbsolute64, {pos, kAddrSize}, rodataFixups, symAddrOfs);
251     }
252 }
253 
EmitAddrOfFuncValue(int64 symIdx,bool belongsToDataSec)254 void ElfAssembler::EmitAddrOfFuncValue(int64 symIdx, bool belongsToDataSec)
255 {
256     EmitLabelValue(symIdx, belongsToDataSec);
257 }
258 
EmitLabelValue(int64 symIdx,bool belongsToDataSec)259 void ElfAssembler::EmitLabelValue(int64 symIdx, bool belongsToDataSec)
260 {
261     const size_t kAddrSize = 8;
262     uint32 pos = 0;
263     int64 addr = 0;
264     if (belongsToDataSec) {
265         pos = dataSection->GetDataSize();
266         dataSection->AppendData(addr, kAddrSize);
267         AppendFixup(symIdx, kAbsolute64, {pos, kAddrSize}, dataFixups);
268     } else {
269         pos = rodataSection->GetDataSize();
270         rodataSection->AppendData(addr, kAddrSize);
271         AppendFixup(symIdx, kAbsolute64, {pos, kAddrSize}, rodataFixups);
272     }
273 }
274 
EmitBitFieldValue(uint64 combineBitFieldValue,bool belongsToDataSec)275 void ElfAssembler::EmitBitFieldValue(uint64 combineBitFieldValue, bool belongsToDataSec)
276 {
277     if (belongsToDataSec) {
278         dataSection->AppendData(static_cast<int64>(combineBitFieldValue), 1);
279     } else {
280         rodataSection->AppendData(static_cast<int64>(combineBitFieldValue), 1);
281     }
282 }
283 
EmitNull(uint64 sizeInByte)284 void ElfAssembler::EmitNull(uint64 sizeInByte)
285 {
286     int64 data = 0;
287     dataSection->AppendData(data, static_cast<size_t>(sizeInByte));
288 }
289 
PostEmitVariable(int64 symIdx,SymbolAttr symAttr,uint64 sizeInByte,bool belongsToTextSec)290 void ElfAssembler::PostEmitVariable(int64 symIdx, SymbolAttr symAttr, uint64 sizeInByte, bool belongsToTextSec)
291 {
292     Label *label = labelManager.at(symIdx);
293     uint64 pos = static_cast<uint64>(label->GetRelOffset());
294     auto secIdx = belongsToTextSec ? textSection->GetIndex() : dataSection->GetIndex();
295     if (symAttr == kSALocal) {
296         const std::string &symbolName = GetNameFromSymMap(symIdx, true);
297         auto index = strTabSection->AddString(symbolName);
298         AddSymToSymTab({static_cast<Word>(index), static_cast<uint8>((STB_LOCAL << 4) + (STT_OBJECT & 0xf)), 0, secIdx,
299             pos, sizeInByte}, symIdx);
300     } else {
301         const std::string &symbolName = GetNameFromSymMap(symIdx);
302         auto index = strTabSection->AddString(symbolName);
303         uint8 symInfo = symAttr == kSAGlobal ? STB_GLOBAL : STB_WEAK;
304         AddSymToSymTab({static_cast<Word>(index), static_cast<uint8>((symInfo << 4) + (STT_OBJECT & 0xf)), 0, secIdx,
305             pos, sizeInByte}, symIdx);
306     }
307 }
308 
FinalizeFileInfo()309 void ElfAssembler::FinalizeFileInfo()
310 {
311     AppendGlobalSymsToSymTabSec();
312     HandleTextSectionFixup();
313     HandleDataSectionFixup();
314     HandleRodataSectionFixup();
315     HandleDebugInfoSectionFixup();
316     WriteElfFile();
317 }
318 
319 /* encode function */
OpReg(Reg reg,uint8 opCode1,uint8 opCode2,uint8 modReg)320 void ElfAssembler::OpReg(Reg reg, uint8 opCode1, uint8 opCode2, uint8 modReg)
321 {
322     if (HasOpndSizePrefix(reg)) {
323         Encodeb(0x66);
324     }
325     uint8 rex = GetRex(reg);
326     if (rex != 0) {
327         Encodeb(rex);
328     }
329     Encodeb(opCode1 | (GetRegSize(reg) == k8Bits ? 0 : 1));
330     if (opCode2 != 0) {
331         Encodeb(opCode2);
332     }
333     uint8 modrm = GetRegCodeId(reg);
334     SetModRM(GetMod(reg), modReg, modrm);
335 }
336 
OpMem(const Mem & mem,uint8 opCode1,uint8 opCode2,uint8 modReg)337 void ElfAssembler::OpMem(const Mem &mem, uint8 opCode1, uint8 opCode2, uint8 modReg)
338 {
339     if (HasOpndSizePrefix(mem)) {
340         Encodeb(0x66);
341     }
342 
343     if (HasAddrSizePrefix(mem)) {
344         Encodeb(0x67);
345     }
346 
347     uint8 rex = GetRex(mem);
348     if (rex != 0) {
349         Encodeb(rex);
350     }
351     Encodeb(opCode1 | (mem.size == k8Bits ? 0 : 1));
352     if (opCode2 != 0) {
353         Encodeb(opCode2);
354     }
355     uint8 modrm = 0;
356     if (!HasSIB(mem)) {
357         modrm = GetRegCodeId(mem.base);
358     } else {
359         modrm = 0b100; /* r/m=b100, use SIB */
360     }
361     SetModRM(GetMod(mem), modReg, modrm);
362     if (HasSIB(mem)) {
363         Encodeb(GetSIB(mem));
364     }
365     OpDisp(mem);
366 }
367 
OpDisp(const Mem & mem)368 void ElfAssembler::OpDisp(const Mem &mem)
369 {
370     int64 symIdx = mem.disp.first;
371     uint64 offset = static_cast<uint64>(mem.disp.second);
372     if (symIdx != 0) {
373         if (!CanEncodeLabel(symIdx)) {
374             size_t offsetSize = 4;
375             UpdateLabel(symIdx);
376             AppendFixup(symIdx, kRelative, {static_cast<uint32>(codeBuff.size()), offsetSize}, fixups, mem.disp.second);
377             uint8 imm = 0;
378             Encodeb(imm, offsetSize);
379         }
380     } else if (offset == 0) {
381         if (mem.memType == kOnlyBase && (mem.base == RBP || mem.base == R13)) {
382             Encodeb(offset);
383         } else if (mem.base == RIP) {
384             Encoded(offset);
385         } else {
386             return;
387         }
388     } else {
389         if (mem.base != RIP && Is8Bits(offset)) {
390             Encodeb(offset); /* 8-bit displacement */
391         } else {
392             Encoded(offset); /* 32-bit displacement */
393         }
394     }
395 }
396 
OpRR(Reg reg1,Reg reg2,uint8 opCode1,uint8 opCode2,bool extInsn)397 void ElfAssembler::OpRR(Reg reg1, Reg reg2, uint8 opCode1, uint8 opCode2, bool extInsn)
398 {
399     if (!extInsn && (HasOpndSizePrefix(reg1) || HasOpndSizePrefix(reg2))) {
400         Encodeb(0x66);
401     }
402     uint8 rex = extInsn ? GetRex(reg2, reg1) : GetRex(reg1, reg2);
403     if (rex != 0) {
404         Encodeb(rex);
405     }
406     Encodeb(opCode1 | (GetRegSize(reg1) == k8Bits ? 0 : 1));
407     if (opCode2 != 0) {
408         Encodeb(opCode2);
409     }
410     uint8 modrm = extInsn ? GetModRM(reg2, reg1) : GetModRM(reg1, reg2);
411     if (modrm != 0) {
412         Encodeb(modrm);
413     }
414 }
415 
OpRM(Reg reg,const Mem & mem,uint8 opCode1,uint8 opCode2,bool extInsn)416 void ElfAssembler::OpRM(Reg reg, const Mem &mem, uint8 opCode1, uint8 opCode2, bool extInsn)
417 {
418     if (!extInsn && HasOpndSizePrefix(reg)) {
419         Encodeb(0x66);
420     }
421     if (!extInsn && HasAddrSizePrefix(mem)) {
422         Encodeb(0x67);
423     }
424     uint8 rex = GetRex(mem, reg);
425     if (rex != 0) {
426         Encodeb(rex);
427     }
428     Encodeb(opCode1 | (GetRegSize(reg) == k8Bits ? 0 : 1));
429     if (opCode2 != 0) {
430         Encodeb(opCode2);
431     }
432     uint8 modrm = GetModRM(reg, mem);
433     Encodeb(modrm);
434     if (HasSIB(mem)) {
435         Encodeb(GetSIB(mem));
436     }
437     OpDisp(mem);
438 }
439 
OpImmAndReg(const ImmOpnd & immOpnd,Reg reg,uint8 opCode,uint8 modReg)440 void ElfAssembler::OpImmAndReg(const ImmOpnd &immOpnd, Reg reg, uint8 opCode, uint8 modReg)
441 {
442     bool isSymbol = immOpnd.second;
443     uint32 imm = static_cast<uint32>(immOpnd.first); /* When isSymbol is true, this is index. */
444     uint8 immBit = Is8Bits(imm) ? k8Bits : (Is16Bits(imm) ? k16Bits : k32Bits);
445     uint8 regSize = GetRegSize(reg);
446     if (regSize == k8Bits) {
447         immBit = k8Bits;
448     }
449     if (immBit == k16Bits && (regSize == k64Bits || regSize == k32Bits)) {
450         immBit = k32Bits; /* if 32/64bit mode, imm val can not use 16-bit. */
451     }
452     immBit = isSymbol ? k32Bits : immBit;
453     if (GetRegId(reg) == 0 && (regSize == immBit || (regSize == k64Bits && immBit == k32Bits))) {
454         if (HasOpndSizePrefix(reg)) {
455             Encodeb(0x66);
456         }
457         if (GetRex(reg)) {
458             Encodeb(GetRex(reg));
459         }
460         Encodeb(opCode | 0x4 | (immBit == k8Bits ? 0 : 1));
461     } else {
462         uint8 tmp = immBit < std::min(static_cast<uint32>(regSize), 32U) ? 2 : 0;
463         OpReg(reg, 0x80 | tmp, 0, modReg);
464     }
465     if (isSymbol) {
466         if (!CanEncodeLabel(immOpnd.first)) {
467             UpdateLabel(immOpnd.first);
468             AppendFixup(immOpnd.first, kRelative, {static_cast<uint32>(codeBuff.size()), immBit / k8Bits}, fixups);
469             imm = 0;
470             Encodeb(imm, immBit / k8Bits);
471         }
472     } else {
473         Encodeb(imm, immBit / k8Bits);
474     }
475 }
476 
OpImmAndMem(const ImmOpnd & immOpnd,const Mem & mem,uint8 modReg)477 void ElfAssembler::OpImmAndMem(const ImmOpnd &immOpnd, const Mem &mem, uint8 modReg)
478 {
479     bool isSymbol = immOpnd.second;
480     uint32 imm = static_cast<uint32>(immOpnd.first); /* When isSymbol is true, this is index. */
481     if (isSymbol) {
482         if (!CanEncodeLabel(immOpnd.first)) {
483             size_t offsetSize = 4;
484             UpdateLabel(immOpnd.first);
485             AppendFixup(immOpnd.first, kRelative, {static_cast<uint32>(codeBuff.size()), offsetSize}, fixups);
486             imm = 0;
487             OpMem(mem, 0x80, 0, modReg);
488             Encodeb(imm, offsetSize);
489         }
490     } else {
491         uint8 immBit = Is8Bits(imm) ? k8Bits : (Is16Bits(imm) ? k16Bits : k32Bits);
492         if (mem.size == k8Bits) {
493             immBit = k8Bits;
494         }
495         if (immBit == k16Bits && (mem.size == k64Bits || mem.size == k32Bits)) {
496             immBit = k32Bits; /* if 32/64bit mode, imm val can not use 16-bit. */
497         }
498         uint8 tmp = immBit < std::min(static_cast<uint32>(mem.size), 32U) ? 2 : 0;
499         OpMem(mem, 0x80 | tmp, 0, modReg);
500         Encodeb(imm, immBit / k8Bits);
501     }
502 }
503 
MovRegAndDisp(Reg reg,const Mem & mem,uint8 opCode)504 void ElfAssembler::MovRegAndDisp(Reg reg, const Mem &mem, uint8 opCode)
505 {
506     if (HasOpndSizePrefix(reg)) {
507         Encodeb(0x66);
508     }
509     if (HasAddrSizePrefix(mem)) {
510         Encodeb(0x67);
511     }
512     uint8 rex = GetRex(mem, reg);
513     if (rex != 0) {
514         Encodeb(rex);
515     }
516     Encodeb(opCode | (GetRegSize(reg) == k8Bits ? 0 : 1));
517     int64 symIdx = mem.disp.first;
518     uint64 offset = static_cast<uint64>(mem.disp.second);
519     if (symIdx != 0) {
520         size_t offsetSize = k8Bits;
521         Encodeb(static_cast<uint8>(0), offsetSize);
522         UpdateLabel(symIdx);
523         AppendFixup(symIdx, kAbsolute64, {static_cast<uint32>(codeBuff.size()), offsetSize}, fixups);
524     }
525     if (Is64Bits(offset)) {
526         Encodeq(offset);
527     } else {
528         Encoded(offset);
529     }
530 }
531 
OpPushPop(Reg reg,uint8 code)532 void ElfAssembler::OpPushPop(Reg reg, uint8 code)
533 {
534     if (HasOpndSizePrefix(reg)) {
535         Encodeb(0x66);
536     }
537     if (IsRegExt(reg)) {
538         Encodeb(0x41); /* Rex prefix */
539     }
540     Encodeb(code | GetRegCodeId(reg));
541 }
542 
JmpToLabel(int64 labelIdx,uint8 opCode1,uint8 opCode2,size_t offsetSize)543 void ElfAssembler::JmpToLabel(int64 labelIdx, uint8 opCode1, uint8 opCode2, size_t offsetSize)
544 {
545     Encodeb(opCode1);
546     if (opCode2 != 0) {
547         Encodeb(opCode2);
548     }
549     if (!CanEncodeLabel(labelIdx)) {
550         UpdateLabel(labelIdx);
551         AppendFixup(labelIdx, kRelative, {static_cast<uint32>(codeBuff.size()), offsetSize}, fixups);
552         uint8 imm = 0;
553         Encodeb(imm, offsetSize);
554     }
555 }
556 
OpCmovcc(Reg srcReg,Reg dstReg,uint8 opCode1,uint8 opCode2)557 void ElfAssembler::OpCmovcc(Reg srcReg, Reg dstReg, uint8 opCode1, uint8 opCode2)
558 {
559     if (HasOpndSizePrefix(srcReg) || HasOpndSizePrefix(dstReg)) {
560         Encodeb(0x66);
561     }
562     uint8 rex = GetRex(dstReg, srcReg);
563     if (rex != 0) {
564         Encodeb(rex);
565     }
566     Encodeb(opCode1);
567     Encodeb(opCode2);
568     uint8 modrm = GetModRM(dstReg, srcReg);
569     if (modrm != 0) {
570         Encodeb(modrm);
571     }
572 }
573 
UpdateLabel(int64 labelIdx,LabelType type,uint32 relOffset)574 void ElfAssembler::UpdateLabel(int64 labelIdx, LabelType type, uint32 relOffset)
575 {
576     if (labelManager.count(labelIdx) == 0) {
577         Label *label = new Label(labelIdx, relOffset, type);
578         (void)labelManager.emplace(labelIdx, label);
579     } else {
580         Label *label = labelManager.at(labelIdx);
581         if (type != LabelType::kLNone) {
582             label->SetLabelType(type);
583         }
584         if (relOffset != 0xFFFFFFFFU) {
585             label->SetRelOffset(relOffset);
586         }
587     }
588 }
589 
CanEncodeLabel(int64 labelIdx)590 bool ElfAssembler::CanEncodeLabel(int64 labelIdx)
591 {
592     if (labelManager.count(labelIdx) != 0) {
593         Label *label = labelManager.at(labelIdx);
594         uint32 relOffset = label->GetRelOffset();
595         LabelType labelType = label->GetLabelType();
596         bool canEncode = (labelType == LabelType::kBBLabel || labelType == LabelType::kFunc ||
597                           labelType == LabelType::kDoubleLabel || labelType == LabelType::kFloatLabel);
598         if (canEncode && relOffset != 0xFFFFFFFFU) {
599             size_t offsetSize = 4;
600             uint64 offset = static_cast<uint64>((relOffset - codeBuff.size()) - offsetSize);
601             Encodeb(offset, offsetSize);
602             return true;
603         }
604     }
605     return false;
606 }
607 
GetLabelSize(int64 labelIdx) const608 uint32 ElfAssembler::GetLabelSize(int64 labelIdx) const
609 {
610     return static_cast<uint32>(codeBuff.size()) - GetLabelRelOffset(labelIdx);
611 }
612 
GetLabelRelOffset(int64 labelIdx) const613 uint32 ElfAssembler::GetLabelRelOffset(int64 labelIdx) const
614 {
615     if (labelManager.count(labelIdx) != 0) {
616         Label *label = labelManager.at(labelIdx);
617         assert(label->GetRelOffset() != 0xFFFFFFFFU && "label's relOffset doesn't exist");
618         return label->GetRelOffset();
619     }
620     return 0;
621 }
622 
AppendFixup(int64 labelIdx,FixupKind kind,const std::pair<uint32,size_t> & offsetPair,std::vector<Fixup * > & tmpFixups,int64 disp)623 void ElfAssembler::AppendFixup(int64 labelIdx, FixupKind kind, const std::pair<uint32, size_t> &offsetPair,
624                                std::vector<Fixup *> &tmpFixups, int64 disp)
625 {
626     tmpFixups.push_back(new Fixup(labelIdx, kind, offsetPair, disp));
627 }
628 
629 /* elf file */
InitElfHeader()630 void ElfAssembler::InitElfHeader()
631 {
632     header.e_ident[EI_MAG0] = ELFMAG0;
633     header.e_ident[EI_MAG1] = ELFMAG1;
634     header.e_ident[EI_MAG2] = ELFMAG2;
635     header.e_ident[EI_MAG3] = ELFMAG3;
636     header.e_ident[EI_CLASS] = ELFCLASS64;
637     header.e_ident[EI_DATA] = ELFDATA2LSB;
638     header.e_ident[EI_VERSION] = EV_CURRENT;
639     header.e_ident[EI_OSABI] = ELFOSABI_NONE; /* ELFOSABI_NONE represents UNIX System V */
640     header.e_ident[EI_ABIVERSION] = 0;
641     (void)std::fill_n(&header.e_ident[EI_PAD], EI_NIDENT - EI_PAD, 0);
642     header.e_type = ET_REL;
643     header.e_machine = EM_X86_64;
644     header.e_version = EV_CURRENT;
645     header.e_entry = 0;
646     header.e_phoff = 0;
647     header.e_shoff = 0; /* later get */
648     header.e_flags = 0; /* The Intel architecture defines no flags; so this member contains zero. */
649     header.e_ehsize = sizeof(FileHeader);
650     header.e_phentsize = 0;
651     header.e_phnum = 0;
652     header.e_shentsize = sizeof(SectionHeader);
653     header.e_shnum = static_cast<uint16>(sections.size());
654     header.e_shstrndx = strTabSection->GetIndex();
655 }
656 
RegisterSection(Section & section)657 void ElfAssembler::RegisterSection(Section &section)
658 {
659     sections.push_back(&section);
660     DEBUG_ASSERT(sections.size() > 0, "must not be zero");
661     section.SetIndex(static_cast<SectionIndex>(sections.size() - 1));
662 }
663 
LayoutSections()664 void ElfAssembler::LayoutSections()
665 {
666     globalOffset = sizeof(FileHeader);
667     globalOffset = Alignment::Align<Offset>(globalOffset, k8Bits);
668 
669     for (auto *section : sections) {
670         section->SetSectionHeaderNameIndex(static_cast<Word>(strTabSection->AddString(section->GetName())));
671     }
672 
673     for (auto *section : sections) {
674         globalOffset = Alignment::Align<Offset>(globalOffset, section->GetAlign());
675         /* lay out section */
676         UpdateSectionOffset(*section);
677         if (section->GetType() != SHT_NOBITS) {
678             section->GenerateData();
679         }
680         UpdateGlobalOffset(*section);
681     }
682 
683     globalOffset = Alignment::Align<Offset>(globalOffset, 16U);
684     header.e_shoff = globalOffset;
685     header.e_shnum = static_cast<uint16>(sections.size());
686 }
687 
UpdateSectionOffset(Section & section)688 void ElfAssembler::UpdateSectionOffset(Section &section)
689 {
690     if (section.GetType() != SHT_NOBITS) {
691         section.SetOffset(globalOffset);
692     } else {
693         section.SetOffset(0);
694     }
695 }
696 
UpdateGlobalOffset(Section & section)697 void ElfAssembler::UpdateGlobalOffset(Section &section)
698 {
699     if (section.GetType() != SHT_NOBITS) {
700         globalOffset += section.GetSectionSize();
701     }
702 }
703 
SetFileOffset(uint64 offset)704 void ElfAssembler::SetFileOffset(uint64 offset)
705 {
706     (void)outStream.seekp(offset);
707 }
708 
709 /* symIdx is the key used to get symbol's index in .symtab */
AddSymToSymTab(const Symbol & symbol,int64 symIdx)710 void ElfAssembler::AddSymToSymTab(const Symbol &symbol, int64 symIdx)
711 {
712     const int kGetHigh4Bits = 4;
713     if ((symbol.st_info >> kGetHigh4Bits) == STB_LOCAL) {
714         localSymTab.push_back(std::make_pair(symbol, symIdx));
715     } else {
716         symTab.push_back(std::make_pair(symbol, symIdx));
717     }
718 }
719 
AppendRela(const Label & label,const std::pair<uint32,size_t> & offsetPair,uint64 type,Sxword addend)720 void ElfAssembler::AppendRela(const Label &label, const std::pair<uint32, size_t> &offsetPair, uint64 type,
721                               Sxword addend)
722 {
723     LabelType labelType = label.GetLabelType();
724     int64 relOffset = static_cast<int64>(label.GetRelOffset());
725     uint64 offset = static_cast<uint64>(offsetPair.first);
726     int64 offsetSize = static_cast<int64>(offsetPair.second);
727     if (labelType == LabelType::kConst) {
728         int64 rodataSecSymIdx = ~rodataSection->GetIndex() + 1;
729         relaSection->AppendRela(
730             {offset,
731              static_cast<Xword>((symbolTabSection->GetIdxInSymbols(rodataSecSymIdx) << kLeftShift32Bits) +
732                                 (type & 0xffffffff)),
733              relOffset});
734     } else if (labelType == LabelType::kGlobal) {
735         addend -= offsetSize;
736         relaSection->AppendRela(
737             {offset,
738              static_cast<Xword>((symbolTabSection->GetIdxInSymbols(label.GetlabelIdx()) << kLeftShift32Bits) +
739                                 (type & 0xffffffff)),
740              addend});
741     } else if (labelType == LabelType::kStatic) {
742         addend += relOffset - offsetSize;
743         int64 dataSecSymIdx = ~dataSection->GetIndex() + 1;
744         relaSection->AppendRela(
745             {offset,
746              static_cast<Xword>((symbolTabSection->GetIdxInSymbols(dataSecSymIdx) << kLeftShift32Bits) +
747                                 (type & 0xffffffff)),
748              addend});
749     } else if (labelType == LabelType::kLocalUninitialized) {
750         addend = addend + relOffset - offsetSize;
751         int64 bssSecSymIdx = ~bssSection->GetIndex() + 1;
752         relaSection->AppendRela(
753             {offset,
754              static_cast<Xword>((symbolTabSection->GetIdxInSymbols(bssSecSymIdx) << kLeftShift32Bits) +
755                                 (type & 0xffffffff)),
756              addend});
757     } else if (labelType == LabelType::kGlobalUninitialized) {
758         addend = addend - offsetSize;
759         relaSection->AppendRela(
760             {offset,
761              static_cast<Xword>((symbolTabSection->GetIdxInSymbols(label.GetlabelIdx()) << kLeftShift32Bits) +
762                                 (type & 0xffffffff)),
763              addend});
764     } else if (labelType == LabelType::kJmpLabel) {
765         type = R_X86_64_32;
766         addend = relOffset;
767         int64 textSecSymIdx = ~textSection->GetIndex() + 1;
768         relaSection->AppendRela(
769             {offset,
770              static_cast<Xword>((symbolTabSection->GetIdxInSymbols(textSecSymIdx) << kLeftShift32Bits) +
771                                 (type & 0xffffffff)),
772              addend});
773     } else if (labelType == LabelType::kBBLabel) {
774         addend = relOffset;
775         int64 textSecSymIdx = ~textSection->GetIndex() + 1;
776         relaSection->AppendRela(
777             {offset,
778              static_cast<Xword>((symbolTabSection->GetIdxInSymbols(textSecSymIdx) << kLeftShift32Bits) +
779                                 (type & 0xffffffff)),
780              addend});
781     } else if (labelType == LabelType::kFunc ||
782                (label.GetRelOffset() == 0xFFFFFFFFU && labelType == LabelType::kLNone)) {
783         int64 labelIdx = label.GetlabelIdx();
784         if (!symbolTabSection->ExistSymInSymbols(labelIdx)) {
785             symbolTabSection->AppendIdxInSymbols(labelIdx);
786         }
787         relaSection->AppendRela({offsetPair.first,
788                                  static_cast<Xword>((symbolTabSection->GetIdxInSymbols(labelIdx) << kLeftShift32Bits) +
789                                                     (type & 0xffffffff)),
790                                  addend});
791     } else {
792         assert(false && "unsupported label type in func AddRela");
793     }
794 }
795 
GetRelaType(FixupKind kind) const796 uint64 ElfAssembler::GetRelaType(FixupKind kind) const
797 {
798     switch (kind) {
799         case kRelative:
800             return R_X86_64_PC32;
801         case kRelative64:
802             return R_X86_64_PC64;
803         case kAbsolute:
804             return R_X86_64_32;
805         case kAbsolute64:
806             return R_X86_64_64;
807         case kPLT:
808             return R_X86_64_PLT32;
809         case kFNone:
810             return R_X86_64_NONE;
811     }
812 }
813 
HandleTextSectionFixup()814 void ElfAssembler::HandleTextSectionFixup()
815 {
816     if (!fixups.empty()) {
817         relaSection =
818             new RelaSection(".rela.text", SHT_RELA, SHF_INFO_LINK, textSection->GetIndex(), k8Bits, *symbolTabSection);
819         RegisterSection(*relaSection);
820     }
821 
822     for (auto fixup : fixups) {
823         int64 labelIdx = fixup->GetlabelIdx();
824         if (labelManager.count(labelIdx) == 0) {
825             continue;
826         }
827 
828         const std::pair<uint32, size_t> &offsetPair = fixup->GetOffset();
829         Label *label = labelManager.at(labelIdx);
830         uint32 relOffset = label->GetRelOffset();
831         LabelType labelType = label->GetLabelType();
832 
833         FixupKind fixupKind = fixup->GetFixupKind();
834         if ((fixupKind == kRelative || fixupKind == kRelative64) &&
835             (labelType == LabelType::kBBLabel || labelType == LabelType::kFunc)) {
836             FixupEncode(offsetPair.first, relOffset, offsetPair.second);
837             fixup->SetFixupKind(kFNone);
838         }
839 
840         if (relOffset != 0xFFFFFFFFU && fixupKind == kPLT) {
841             FixupEncode(offsetPair.first, relOffset, offsetPair.second);
842             fixup->SetFixupKind(kFNone);
843         }
844 
845         fixupKind = fixup->GetFixupKind();
846         uint64 type = GetRelaType(fixupKind);
847         int64 addend = (fixupKind == kAbsolute || fixupKind == kAbsolute64) ? 0 : -0x4;
848         if (fixupKind != kFNone) {
849             addend = labelType == LabelType::kGlobalUninitialized || labelType == LabelType::kLocalUninitialized ||
850                              labelType == LabelType::kGlobal || labelType == LabelType::kStatic
851                          ? fixup->GetDisp()
852                          : addend;
853             AppendRela(*label, offsetPair, type, addend);
854         }
855     }
856     textSection->AppendData(codeBuff.data(), codeBuff.size());
857 }
858 
HandleDataSectionFixup()859 void ElfAssembler::HandleDataSectionFixup()
860 {
861     if (!dataFixups.empty()) {
862         relaDataSection =
863             new RelaSection(".rela.data", SHT_RELA, SHF_INFO_LINK, dataSection->GetIndex(), k8Bits, *symbolTabSection);
864         RegisterSection(*relaDataSection);
865     }
866     for (auto fixup : dataFixups) {
867         int64 labelIdx = fixup->GetlabelIdx();
868         std::pair<uint32, size_t> offset = fixup->GetOffset();
869         const uint32 relocType = R_X86_64_64;
870         if (labelManager.count(labelIdx) == 0) {
871             continue;
872         }
873         Label *label = labelManager.at(labelIdx);
874         LabelType labelType = label->GetLabelType();
875         int64 addend = 0;
876         int64 relOffset = static_cast<int64>(label->GetRelOffset());
877         if (labelType == LabelType::kGlobalUninitialized) {
878             addend = fixup->GetDisp();
879             uint64 pos = symbolTabSection->GetIdxInSymbols(labelIdx);
880             relaDataSection->AppendRela(
881                 {offset.first, static_cast<Xword>((pos << kLeftShift32Bits) + (relocType & 0xffffffff)), addend});
882         } else if (labelType == LabelType::kLocalUninitialized) {
883             addend = fixup->GetDisp();
884             int64 bssSecSymIdx = ~bssSection->GetIndex() + 1;
885             relaDataSection->AppendRela(
886                 {offset.first,
887                  static_cast<Xword>((symbolTabSection->GetIdxInSymbols(bssSecSymIdx) << kLeftShift32Bits) +
888                                     (relocType & 0xffffffff)),
889                  addend});
890         } else if (labelType == LabelType::kFunc) {
891             uint64 pos = symbolTabSection->GetIdxInSymbols(labelIdx);
892             relaDataSection->AppendRela(
893                 {offset.first, static_cast<Xword>((pos << kLeftShift32Bits) + (relocType & 0xffffffff)), addend});
894         } else if (labelType == LabelType::kStrLabel || labelType == LabelType::kGlobal ||
895                    labelType == LabelType::kStatic) {
896             uint64 pos = symbolTabSection->GetIdxInSymbols(~dataSection->GetIndex() + 1);
897             addend = (labelType == LabelType::kGlobal || labelType == LabelType::kStatic) ? fixup->GetDisp() + relOffset
898                                                                                           : relOffset;
899             relaDataSection->AppendRela(
900                 {offset.first, static_cast<Xword>((pos << kLeftShift32Bits) + (relocType & 0xffffffff)), addend});
901         } else {
902             addend = relOffset;
903             int64 textSecSymIdx = ~textSection->GetIndex() + 1;
904             relaDataSection->AppendRela(
905                 {offset.first,
906                  static_cast<Xword>((symbolTabSection->GetIdxInSymbols(textSecSymIdx) << kLeftShift32Bits) +
907                                     (relocType & 0xffffffff)),
908                  addend});
909         }
910     }
911 }
912 
HandleRodataSectionFixup()913 void ElfAssembler::HandleRodataSectionFixup()
914 {
915     if (!rodataFixups.empty()) {
916         relaRodataSection = new RelaSection(".rela.rodata", SHT_RELA, SHF_INFO_LINK, rodataSection->GetIndex(), k8Bits,
917                                             *symbolTabSection);
918         RegisterSection(*relaRodataSection);
919     }
920     for (auto fixup : rodataFixups) {
921         int64 labelIdx = fixup->GetlabelIdx();
922         std::pair<uint32, size_t> offset = fixup->GetOffset();
923         const uint32 relocType = R_X86_64_64;
924         if (labelManager.count(labelIdx) == 0) {
925             continue;
926         }
927         Label *label = labelManager.at(labelIdx);
928         LabelType labelType = label->GetLabelType();
929         int64 addend = 0;
930         int64 relOffset = static_cast<int64>(label->GetRelOffset());
931         if (labelType == LabelType::kGlobalUninitialized || labelType == LabelType::kLocalUninitialized) {
932             addend = relOffset;
933             uint64 pos = symbolTabSection->GetIdxInSymbols(~textSection->GetIndex() + 1);
934             relaRodataSection->AppendRela(
935                 {offset.first, static_cast<Xword>((pos << kLeftShift32Bits) + (relocType & 0xffffffff)), addend});
936         }
937     }
938 }
939 
WriteElfFile()940 void ElfAssembler::WriteElfFile()
941 {
942     /* Init elf file header */
943     InitElfHeader();
944 
945     LayoutSections();
946 
947     const auto &emitMemoryManager = maplebe::CGOptions::GetInstance().GetEmitMemoryManager();
948     if (emitMemoryManager.codeSpace != nullptr) {
949         DEBUG_ASSERT(textSection != nullptr, "textSection has not been initialized");
950         uint8 *codeSpace = emitMemoryManager.allocateDataSection(emitMemoryManager.codeSpace,
951             textSection->GetSectionSize(), textSection->GetAlign(), textSection->GetName());
952         auto ret = memcpy_s(
953             codeSpace, textSection->GetSectionSize(), textSection->GetData().data(), textSection->GetDataSize());
954         CHECK_FATAL(ret == EOK, "memcpy failed");
955         if (CGOptions::addFuncSymbol()) {
956             uint8 *symtabSpace = emitMemoryManager.allocateDataSection(emitMemoryManager.codeSpace,
957                 symbolTabSection->GetDataSize(), symbolTabSection->GetAlign(), symbolTabSection->GetName().c_str());
958             ret = memcpy_s(symtabSpace,
959                 symbolTabSection->GetDataSize(),
960                 symbolTabSection->GetAddr(),
961                 symbolTabSection->GetDataSize());
962             CHECK_FATAL(ret == EOK, "memcpy failed");
963             uint8 *stringTabSpace = emitMemoryManager.allocateDataSection(emitMemoryManager.codeSpace,
964                 strTabSection->GetDataSize(),
965                 strTabSection->GetAlign(),
966                 strTabSection->GetName().c_str());
967             ret = memcpy_s(stringTabSpace,
968                 strTabSection->GetDataSize(),
969                 strTabSection->GetData().data(),
970                 strTabSection->GetDataSize());
971             CHECK_FATAL(ret == EOK, "memcpy failed");
972         }
973         return;
974     }
975 
976     /* write header */
977     Emit(&header, sizeof(header));
978 
979     /* write sections */
980     for (auto *section : sections) {
981         if (section->GetType() == SHT_NOBITS) {
982             continue;
983         }
984         SetFileOffset(section->GetOffset());
985         section->WriteSection(outFStream);
986     }
987 
988     /* write section table */
989     SetFileOffset(header.e_shoff);
990     for (auto *section : sections) {
991         Emit(&section->GetSectionHeader(), sizeof(section->GetSectionHeader()));
992     }
993 }
994 
995 /* Append the symbol of non-empty and necessary section to symbol table section. */
AppendSecSymsToSymTabSec()996 void ElfAssembler::AppendSecSymsToSymTabSec()
997 {
998     for (Section *section : sections) {
999         if (section->GetType() != SHT_PROGBITS && section->GetType() != SHT_NOBITS) {
1000             continue;
1001         }
1002         DataSection *dataSec = static_cast<DataSection *>(section);
1003         if (section->GetFlags() == (SHF_ALLOC | SHF_EXECINSTR) || section->GetSectionSize() != 0 ||
1004             (dataSec != nullptr && dataSec->GetDataSize() != 0)) {
1005             auto nameIndex = strTabSection->AddString(section->GetName());
1006             symbolTabSection->AppendSymbol({static_cast<Word>(nameIndex),
1007                                             static_cast<uint8>((STB_LOCAL << kLeftShift4Bits) + (STT_SECTION & 0xf)), 0,
1008                                             section->GetIndex(), 0, 0});
1009             /* Indexed by the inverse of the section index. */
1010             int64 secSymIdx = ~section->GetIndex() + 1;
1011             symbolTabSection->AppendIdxInSymbols(secSymIdx);
1012         }
1013     }
1014 }
1015 
AppendGlobalSymsToSymTabSec()1016 void ElfAssembler::AppendGlobalSymsToSymTabSec()
1017 {
1018     for (auto elem : symTab) {
1019         const Symbol &symbol = elem.first;
1020         int64 symIdx = elem.second;
1021         symbolTabSection->AppendSymbol(symbol);
1022         symbolTabSection->AppendIdxInSymbols(symIdx);
1023     }
1024 }
1025 
AppendSymsToSymTabSec()1026 void ElfAssembler::AppendSymsToSymTabSec()
1027 {
1028     /* emit local symbol */
1029     for (auto elem : localSymTab) {
1030         Symbol symbol = elem.first;
1031         int64 symIdx = elem.second;
1032         symbolTabSection->AppendSymbol(symbol);
1033         symbolTabSection->AppendIdxInSymbols(symIdx);
1034     }
1035 
1036     /* Append section symbol that may be used in relocation item, section is local. */
1037     AppendSecSymsToSymTabSec();
1038 
1039     /* set .symtab's info : index of the first non-local symbol */
1040     symbolTabSection->SetInfo(symbolTabSection->GetSymbolsSize());
1041 
1042     /* emit global and other symbol */
1043     for (auto elem : symTab) {
1044         const Symbol &symbol = elem.first;
1045         int64 symIdx = elem.second;
1046         symbolTabSection->AppendSymbol(symbol);
1047         symbolTabSection->AppendIdxInSymbols(symIdx);
1048     }
1049 }
1050 
1051 /* emit debug info */
EmitDIDebugInfoSectionHeader(uint64 debugInfoLength)1052 void ElfAssembler::EmitDIDebugInfoSectionHeader(uint64 debugInfoLength)
1053 {
1054     debugInfoSection = new DataSection(".debug_info", SHT_PROGBITS, 0, 1);
1055     RegisterSection(*debugInfoSection);
1056     /* length of .debug_info section, 4 bytes */
1057     size_t debugInfoLenSize = 4;
1058     debugInfoSection->AppendData(static_cast<int64>(debugInfoLength), debugInfoLenSize);
1059     size_t dwarfVersionSize = 2;
1060     /* DWARF version, 2 bytes */
1061     debugInfoSection->AppendData(static_cast<int64>(kDwarfVersion), dwarfVersionSize);
1062     /* debug_abbrev_offset. 4 bytes for dwarf32, 8 bytes for dwarf64 */
1063     int64 debugAbbrevOffset = 0;
1064     size_t debugAbbrevOffsetSize = 4;
1065     /* If labelSymIdx equals LLONG_MAX, there is not a real label bound to the fixup. */
1066     AppendFixup(LLONG_MAX, kAbsolute, {debugInfoSection->GetDataSize(), debugAbbrevOffsetSize}, debugInfoFixups);
1067     debugInfoSection->AppendData(debugAbbrevOffset, debugAbbrevOffsetSize);
1068     /* address size. 1 byte */
1069     size_t byteOfkSizeOfPTR = 1;
1070     debugInfoSection->AppendData(kSizeOfPTR, byteOfkSizeOfPTR);
1071 }
1072 
EmitDIDebugInfoSectionAbbrevId(bool verbose,uint32 abbrevId,const std::string & dieTagName,uint32 offset,uint32 size)1073 void ElfAssembler::EmitDIDebugInfoSectionAbbrevId(bool verbose, uint32 abbrevId, const std::string &dieTagName,
1074                                                   uint32 offset, uint32 size)
1075 {
1076     auto abbrevIdUleb128 = EncodeULEB128(abbrevId);
1077     debugInfoSection->AppendData(&abbrevIdUleb128, abbrevIdUleb128.size());
1078 }
1079 
1080 /* EmitDIAttrValue */
EmitDwFormString(const std::string & name)1081 void ElfAssembler::EmitDwFormString(const std::string &name)
1082 {
1083     debugInfoSection->AppendData(&name, name.size());
1084 }
1085 
EmitDwFormStrp(uint32 strLabelId,size_t strTableSize)1086 void ElfAssembler::EmitDwFormStrp(uint32 strLabelId, size_t strTableSize)
1087 {
1088     int64 labelSymIdx = CalculateStrLabelSymIdx(static_cast<int64>(strLabelId), static_cast<int64>(strTableSize));
1089     UpdateLabel(labelSymIdx, LabelType::kDebugStrLabel);
1090     int64 strLabelOffset = 0;
1091     size_t strLabelOffsetSize = 4;
1092     AppendFixup(labelSymIdx, kAbsolute, {debugInfoSection->GetDataSize(), strLabelOffsetSize}, debugInfoFixups);
1093     debugInfoSection->AppendData(strLabelOffset, strLabelOffsetSize);
1094 }
1095 
EmitDwFormData(int32 attrValue,uint8 sizeInByte)1096 void ElfAssembler::EmitDwFormData(int32 attrValue, uint8 sizeInByte)
1097 {
1098     debugInfoSection->AppendData(attrValue, sizeInByte);
1099 }
1100 
EmitDwFormData8()1101 void ElfAssembler::EmitDwFormData8()
1102 {
1103     int64 addr = 0;
1104     size_t addrSizeInByte = 8;
1105     debugInfoSection->AppendData(addr, addrSizeInByte);
1106 }
1107 
EmitDwFormData8(uint32 endLabelFuncPuIdx,uint32 startLabelFuncPuIdx,uint32 endLabelIdx,uint32 startLabelIdx)1108 void ElfAssembler::EmitDwFormData8(uint32 endLabelFuncPuIdx, uint32 startLabelFuncPuIdx, uint32 endLabelIdx,
1109                                    uint32 startLabelIdx)
1110 {
1111     int64 addr = 0;
1112     size_t addrSizeInByte = 8;
1113     debugInfoSection->AppendData(addr, addrSizeInByte);
1114 }
1115 
EmitLabel(uint32 funcPuIdx,uint32 labIdx)1116 void ElfAssembler::EmitLabel(uint32 funcPuIdx, uint32 labIdx)
1117 {
1118     int64 labSymIdx = CalculateLabelSymIdx(funcPuIdx, labIdx);
1119     UpdateLabel(labIdx);
1120     int64 addr = 0;
1121     size_t addrSizeInByte = 8;
1122     AppendFixup(labSymIdx, kAbsolute64, {debugInfoSection->GetDataSize(), addrSizeInByte}, debugInfoFixups);
1123     debugInfoSection->AppendData(addr, addrSizeInByte);
1124 }
1125 
EmitDwFormSecOffset()1126 void ElfAssembler::EmitDwFormSecOffset()
1127 {
1128     int64 lineLabelOffset = 0;
1129     size_t lineLabelOffsetSize = 4;
1130     /* If labelSymIdx equals  - 2, there is not a real label bound to the fixup. */
1131     AppendFixup(LLONG_MAX - 2, kAbsolute, {debugInfoSection->GetDataSize(), lineLabelOffsetSize}, debugInfoFixups);
1132     debugInfoSection->AppendData(lineLabelOffset, lineLabelOffsetSize);
1133 }
1134 
EmitDwFormAddr(bool emitTextBegin)1135 void ElfAssembler::EmitDwFormAddr(bool emitTextBegin)
1136 {
1137     if (emitTextBegin) {
1138         int64 addr = 0;
1139         size_t addrSizeInByte = 8;
1140         /* If labelSymIdx equals LLONG_MAX - 1, there is not a real label bound to the fixup. */
1141         AppendFixup(LLONG_MAX - 1, kAbsolute64, {debugInfoSection->GetDataSize(), addrSizeInByte}, debugInfoFixups);
1142         debugInfoSection->AppendData(addr, addrSizeInByte);
1143     }
1144 }
1145 
EmitDwFormRef4(uint64 offsetOrValue,bool unknownType,bool emitOffset)1146 void ElfAssembler::EmitDwFormRef4(uint64 offsetOrValue, bool unknownType, bool emitOffset)
1147 {
1148     size_t offsetOrValueSize = 4;
1149     debugInfoSection->AppendData(static_cast<int64>(offsetOrValue), offsetOrValueSize);
1150 }
1151 
EmitDwFormExprlocCfa(uint32 dwOp)1152 void ElfAssembler::EmitDwFormExprlocCfa(uint32 dwOp)
1153 {
1154     debugInfoSection->AppendData(1, 1);
1155     debugInfoSection->AppendData(static_cast<int64>(dwOp), 1);
1156 }
1157 
EmitDwFormExprlocAddr(uint32 dwOp,const std::string & addrStr)1158 void ElfAssembler::EmitDwFormExprlocAddr(uint32 dwOp, const std::string &addrStr)
1159 {
1160     debugInfoSection->AppendData(static_cast<int64>(k9ByteSize), 1);
1161     debugInfoSection->AppendData(static_cast<int64>(dwOp), 1);
1162     size_t addStrSize = 8;
1163     debugInfoSection->AppendData(&addrStr, addStrSize);
1164 }
1165 
EmitDwFormExprlocFbreg(uint32 dwOp,int fboffset,size_t sleb128Size)1166 void ElfAssembler::EmitDwFormExprlocFbreg(uint32 dwOp, int fboffset, size_t sleb128Size)
1167 {
1168     auto sleb128SizeEncode = EncodeSLEB128(1 + static_cast<int64>(sleb128Size));
1169     debugInfoSection->AppendData(&sleb128SizeEncode, sleb128SizeEncode.size());
1170     debugInfoSection->AppendData(static_cast<int64>(dwOp), 1);
1171     auto fboffsetSleb128 = EncodeSLEB128(fboffset);
1172     debugInfoSection->AppendData(&fboffsetSleb128, fboffsetSleb128.size());
1173 }
1174 
EmitDwFormExprlocBregn(uint32 dwOp,const std::string & dwOpName)1175 void ElfAssembler::EmitDwFormExprlocBregn(uint32 dwOp, const std::string &dwOpName)
1176 {
1177     debugInfoSection->AppendData(static_cast<int64>(k2Bytes), 1);
1178     debugInfoSection->AppendData(static_cast<int64>(dwOp), 1);
1179     debugInfoSection->AppendData(&dwOpName, dwOpName.size());
1180     int64 offset = 0;
1181     debugInfoSection->AppendData(offset, 1);
1182 }
1183 
EmitDwFormExprloc(uintptr elp)1184 void ElfAssembler::EmitDwFormExprloc(uintptr elp)
1185 {
1186     auto elpUleb128 = EncodeULEB128(elp);
1187     debugInfoSection->AppendData(&elpUleb128, elpUleb128.size());
1188 }
1189 
EmitDIDebugAbbrevDiae(bool verbose,uint32 abbrevId,uint32 tag,const std::string & dwTagName,bool withChildren)1190 void ElfAssembler::EmitDIDebugAbbrevDiae(bool verbose, uint32 abbrevId, uint32 tag, const std::string &dwTagName,
1191                                          bool withChildren)
1192 {
1193     debugAbbrevSection = new DataSection(".debug_abbrev", SHT_PROGBITS, 0, 1);
1194     RegisterSection(*debugAbbrevSection);
1195     /* Abbrev Entry ID */
1196     auto abbrevIdUleb128 = EncodeULEB128(abbrevId);
1197     debugAbbrevSection->AppendData(&abbrevIdUleb128, abbrevIdUleb128.size());
1198     /* TAG */
1199     auto tagUleb128 = EncodeULEB128(tag);
1200     debugAbbrevSection->AppendData(&tagUleb128, tagUleb128.size());
1201     /* children */
1202     auto childrenValue = withChildren ? 1 : 0;
1203     debugAbbrevSection->AppendData(childrenValue, 1);
1204 }
1205 
EmitDIDebugAbbrevDiaePairItem(bool verbose,uint32 aplAt,uint32 aplFrom,const std::string & dwAtName,const std::string & dwFromName)1206 void ElfAssembler::EmitDIDebugAbbrevDiaePairItem(bool verbose, uint32 aplAt, uint32 aplFrom,
1207                                                  const std::string &dwAtName, const std::string &dwFromName)
1208 {
1209     /* odd entry -- DW_AT_*, even entry -- DW_FORM_* */
1210     auto aplAtUleb128 = EncodeULEB128(aplAt);
1211     debugAbbrevSection->AppendData(&aplAtUleb128, aplAtUleb128.size());
1212     auto aplFromUleb128 = EncodeULEB128(aplFrom);
1213     debugAbbrevSection->AppendData(&aplFromUleb128, aplFromUleb128.size());
1214 }
1215 
EmitDIDebugSectionEnd(SectionKind secKind)1216 void ElfAssembler::EmitDIDebugSectionEnd(SectionKind secKind)
1217 {
1218     int64 value = 0;
1219     size_t valueSizeInByte = 1;
1220     switch (secKind) {
1221         case kSDebugInfo:
1222             debugInfoSection->AppendData(value, valueSizeInByte);
1223             break;
1224         case kSDebugAbbrev:
1225             debugAbbrevSection->AppendData(value, valueSizeInByte);
1226             break;
1227         case kSBss:
1228         case kSComm:
1229         case kSData:
1230         case kSRodata:
1231         case kSTbss:
1232         case kSTdata:
1233         case kSText:
1234         case kSDebugStr:
1235         default:
1236             assert(false && "unsupport SectionKind in EmitDIDebugSectionEnd");
1237             break;
1238     }
1239 }
1240 
EmitDIDebugStrSection(const std::vector<uint32> & strps,const std::vector<std::string> & debugStrs,uint64 size,size_t strTableSize)1241 void ElfAssembler::EmitDIDebugStrSection(const std::vector<uint32> &strps, const std::vector<std::string> &debugStrs,
1242                                          uint64 size, size_t strTableSize)
1243 {
1244     debugStrSection = new DataSection(".debug_str", SHT_PROGBITS, SHF_MASKPROC, 1);
1245     RegisterSection(*debugStrSection);
1246     for (int i = 0; i < static_cast<int>(debugStrs.size()); i++) {
1247         int64 strLabSymIdx = CalculateStrLabelSymIdx(size, strps[i], strTableSize);
1248         UpdateLabel(strLabSymIdx, LabelType::kDebugStrLabel, debugStrSection->GetDataSize());
1249         debugStrSection->AppendData(&debugStrs[i], debugStrs[i].size());
1250         EmitDIDebugSectionEnd(kSDebugStr);
1251     }
1252 }
1253 
HandleDebugInfoSectionFixup()1254 void ElfAssembler::HandleDebugInfoSectionFixup()
1255 {
1256     if (!debugInfoFixups.empty()) {
1257         relaDebugInfoSection = new RelaSection(".rela.debug_info", SHT_RELA, SHF_INFO_LINK,
1258                                                debugInfoSection->GetIndex(), k8Bits, *symbolTabSection);
1259         RegisterSection(*relaDebugInfoSection);
1260     }
1261     for (auto fixup : debugInfoFixups) {
1262         int64 labelIdx = fixup->GetlabelIdx();
1263         const std::pair<uint32, size_t> &offsetPair = fixup->GetOffset();
1264         FixupKind fixupKind = fixup->GetFixupKind();
1265         uint64 relocType = GetRelaType(fixupKind);
1266         int64 addend = fixup->GetDisp();
1267         int64 textSecSymIdx = ~textSection->GetIndex() + 1;
1268         int64 debugLineSecSymIdx = ~debugLineSection->GetIndex() + 1;
1269         int64 abbrevSecSymIdx = ~debugAbbrevSection->GetIndex() + 1;
1270         uint64 pos = labelIdx == LLONG_MAX
1271                          ? symbolTabSection->GetIdxInSymbols(debugLineSecSymIdx)
1272                          : (labelIdx == LLONG_MAX - 1 ? symbolTabSection->GetIdxInSymbols(textSecSymIdx)
1273                                                       : symbolTabSection->GetIdxInSymbols(abbrevSecSymIdx));
1274         if (!labelManager.count(labelIdx)) {
1275             relaDebugInfoSection->AppendRela(
1276                 {offsetPair.first, static_cast<Xword>((pos << kLeftShift32Bits) + (relocType & 0xffffffff)), addend});
1277             continue;
1278         }
1279         Label *label = labelManager.at(labelIdx);
1280         LabelType labelType = label->GetLabelType();
1281         addend = label->GetRelOffset();
1282         if (labelType == LabelType::kBBLabel) {
1283             pos = symbolTabSection->GetIdxInSymbols(textSecSymIdx);
1284         } else if (labelType == LabelType::kDebugStrLabel) {
1285             pos = symbolTabSection->GetIdxInSymbols(~debugStrSection->GetIndex() + 1);
1286         } else {
1287             assert(false && "unsupport label type in HandleDebugInfoSectionFixup!");
1288         }
1289         relaDebugInfoSection->AppendRela(
1290             {offsetPair.first, static_cast<Xword>((pos << kLeftShift32Bits) + (relocType & 0xffffffff)), addend});
1291     }
1292 }
1293 
1294 /* start of X64 instructions */
1295 /* mov */
Mov(InsnSize insnSize,Reg srcReg,Reg destReg)1296 void ElfAssembler::Mov(InsnSize insnSize, Reg srcReg, Reg destReg)
1297 {
1298     OpRR(srcReg, destReg, 0x88, 0);
1299 }
1300 
Mov(InsnSize insnSize,const ImmOpnd & immOpnd,Reg reg)1301 void ElfAssembler::Mov(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg)
1302 {
1303     bool isSymbol = immOpnd.second;
1304     uint64 imm = static_cast<uint64>(immOpnd.first); /* When isSymbol is true, this is index. */
1305     uint8 regSize = GetRegSize(reg);
1306     uint8 regId = GetRegCodeId(reg);
1307     uint8 code = 0xB0 | ((regSize == k8Bits ? 0 : 1) << kLeftShift3Bits);
1308     if (HasOpndSizePrefix(reg)) {
1309         Encodeb(0x66);
1310     }
1311     if (GetRex(reg) != 0) {
1312         Encodeb(GetRex(reg));
1313     }
1314     if (regSize == k64Bits && (isSymbol || Is32Bits(imm))) {
1315         Encodeb(0xC7);
1316         code = 0xC0;
1317         regSize = k32Bits;
1318     }
1319     size_t offsetSize = isSymbol ? k64Bits : regSize / k8Bits;
1320     Encodeb(code | regId);
1321     if (isSymbol) {
1322         UpdateLabel(immOpnd.first);
1323         AppendFixup(immOpnd.first, kAbsolute64, {static_cast<uint32>(codeBuff.size()), offsetSize}, fixups);
1324         imm = 0;
1325     }
1326     Encodeb(imm, offsetSize);
1327 }
1328 
Mov(InsnSize insnSize,const Mem & mem,Reg reg)1329 void ElfAssembler::Mov(InsnSize insnSize, const Mem &mem, Reg reg)
1330 {
1331     if (GetRegId(reg) == 0 && mem.memType == kOnlyDisp) {
1332         MovRegAndDisp(reg, mem, 0xA0);
1333     } else {
1334         OpRM(reg, mem, 0x8A, 0);
1335     }
1336 }
1337 
Mov(InsnSize insnSize,Reg reg,const Mem & mem)1338 void ElfAssembler::Mov(InsnSize insnSize, Reg reg, const Mem &mem)
1339 {
1340     if (GetRegId(reg) == 0 && mem.memType == kOnlyDisp) {
1341         MovRegAndDisp(reg, mem, 0xA2);
1342     } else {
1343         OpRM(reg, mem, 0x88, 0);
1344     }
1345 }
1346 
Mov(InsnSize insnSize,const ImmOpnd & immOpnd,const Mem & mem)1347 void ElfAssembler::Mov(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem)
1348 {
1349     bool isSymbol = immOpnd.second;
1350     uint32 imm = static_cast<uint32>(immOpnd.first); /* When isSymbol is true, this is index. */
1351     uint8 immBit = Is8Bits(imm) ? k8Bits : (Is16Bits(imm) ? k16Bits : k32Bits);
1352     if (mem.size == k8Bits) {
1353         immBit = k8Bits;
1354     }
1355     if (immBit == k16Bits && (mem.size == k64Bits || mem.size == k32Bits)) {
1356         immBit = k32Bits; /* if 32/64bit mode, imm val can not use 16-bit. */
1357     }
1358     immBit = isSymbol ? k64Bits : immBit;
1359     size_t immSize = immBit / k8Bits;
1360     OpMem(mem, 0xC6, 0, 0);
1361     if (isSymbol) {
1362         UpdateLabel(immOpnd.first);
1363         AppendFixup(immOpnd.first, kAbsolute64, {static_cast<uint32>(codeBuff.size()), immSize}, fixups);
1364         imm = 0;
1365     }
1366     Encodeb(imm, immSize);
1367 }
1368 
1369 /* floating point mov */
Mov(Reg srcReg,Reg destReg,bool isMovD)1370 void ElfAssembler::Mov(Reg srcReg, Reg destReg, bool isMovD)
1371 {
1372     uint8 srcRegSize = GetRegSize(srcReg);
1373     uint8 destRegSize = GetRegSize(destReg);
1374     if (srcRegSize == k128Bits || destRegSize == k128Bits) {
1375         Encodeb(0x66);
1376     }
1377     if (srcRegSize == k128Bits) {
1378         OpRR(srcReg, destReg, 0x0F, 0x7E);
1379     } else if (destRegSize == k128Bits) {
1380         OpRR(destReg, srcReg, 0x0F, 0x6E);
1381     }
1382 }
1383 
MovF(const Mem & mem,Reg reg,bool isSingle)1384 void ElfAssembler::MovF(const Mem &mem, Reg reg, bool isSingle)
1385 {
1386     if (isSingle) {
1387         Encodeb(0xF3);
1388     } else {
1389         Encodeb(0xF2);
1390     }
1391     OpRM(reg, mem, 0x0F, 0x10);
1392 }
1393 
MovF(Reg reg,const Mem & mem,bool isSingle)1394 void ElfAssembler::MovF(Reg reg, const Mem &mem, bool isSingle)
1395 {
1396     if (isSingle) {
1397         Encodeb(0xF3);
1398     } else {
1399         Encodeb(0xF2);
1400     }
1401     OpRM(reg, mem, 0x0F, 0x11);
1402 }
1403 
1404 /* movabs */
Movabs(const ImmOpnd & immOpnd,Reg reg)1405 void ElfAssembler::Movabs(const ImmOpnd &immOpnd, Reg reg)
1406 {
1407     bool isSymbol = immOpnd.second;
1408     uint64 imm = static_cast<uint64>(immOpnd.first); /* When isSymbol is true, this is index. */
1409     if (GetRex(reg) != 0) {
1410         Encodeb(GetRex(reg));
1411     }
1412     Encodeb(0xB8 | GetRegCodeId(reg));
1413     size_t offsetSize = 8;
1414     if (isSymbol) {
1415         UpdateLabel(immOpnd.first);
1416         AppendFixup(immOpnd.first, kAbsolute64, {static_cast<uint32>(codeBuff.size()), offsetSize}, fixups);
1417         imm = 0;
1418     }
1419     Encodeb(imm, offsetSize);
1420 }
1421 
Movabs(int64 symIdx,Reg reg)1422 void ElfAssembler::Movabs(int64 symIdx, Reg reg)
1423 {
1424     if (GetRex(reg) != 0) {
1425         Encodeb(GetRex(reg));
1426     }
1427     Encodeb(0xB8 | GetRegCodeId(reg));
1428     size_t offsetSize = 8;
1429     size_t offset = codeBuff.size() - offsetSize;
1430     UpdateLabel(symIdx);
1431     AppendFixup(symIdx, kAbsolute64, {offset, offsetSize}, fixups);
1432     uint8 imm = 0;
1433     Encodeb(imm, offsetSize);
1434 }
1435 
1436 /* push */
Push(InsnSize insnSize,Reg reg)1437 void ElfAssembler::Push(InsnSize insnSize, Reg reg)
1438 {
1439     OpPushPop(reg, 0x50);
1440 }
1441 
1442 /* pop */
Pop(InsnSize insnSize,Reg reg)1443 void ElfAssembler::Pop(InsnSize insnSize, Reg reg)
1444 {
1445     OpPushPop(reg, 0x58);
1446 }
1447 
1448 /* lea */
Lea(InsnSize insnSize,const Mem & mem,Reg reg)1449 void ElfAssembler::Lea(InsnSize insnSize, const Mem &mem, Reg reg)
1450 {
1451     OpRM(reg, mem, 0x8C);
1452 }
1453 
1454 /* movzx */
MovZx(InsnSize sSize,InsnSize dSize,Reg srcReg,Reg destReg)1455 void ElfAssembler::MovZx(InsnSize sSize, InsnSize dSize, Reg srcReg, Reg destReg)
1456 {
1457     OpRR(srcReg, destReg, 0x0F, 0xB6 | (GetRegSize(srcReg) == k8Bits ? 0 : 1), true);
1458 }
1459 
MovZx(InsnSize sSize,InsnSize dSize,const Mem & mem,Reg reg)1460 void ElfAssembler::MovZx(InsnSize sSize, InsnSize dSize, const Mem &mem, Reg reg)
1461 {
1462     OpRM(reg, mem, 0x0F, 0xB6 | (mem.size == k8Bits ? 0 : 1), true);
1463 }
1464 
1465 /* movsx */
MovSx(InsnSize sSize,InsnSize dSize,Reg srcReg,Reg destReg)1466 void ElfAssembler::MovSx(InsnSize sSize, InsnSize dSize, Reg srcReg, Reg destReg)
1467 {
1468     uint8 code1 = 0x0F;
1469     uint8 code2 = 0xBE | (GetRegSize(srcReg) == k8Bits ? 0 : 1);
1470     if (GetRegSize(srcReg) == k32Bits && GetRegSize(destReg) == k64Bits) {
1471         code1 = 0x63;
1472         code2 = 0;
1473     }
1474     OpRR(srcReg, destReg, code1, code2, true);
1475 }
1476 
MovSx(InsnSize sSize,InsnSize dSize,const Mem & mem,Reg reg)1477 void ElfAssembler::MovSx(InsnSize sSize, InsnSize dSize, const Mem &mem, Reg reg)
1478 {
1479     uint8 code1 = 0x0F;
1480     uint8 code2 = 0xBE | (mem.size == k8Bits ? 0 : 1);
1481     if (mem.size == k32Bits && GetRegSize(reg) == k64Bits) {
1482         code1 = 0x63;
1483         code2 = 0;
1484     }
1485     OpRM(reg, mem, code1, code2, true);
1486 }
1487 
1488 /* add */
Add(InsnSize insnSize,Reg srcReg,Reg destReg)1489 void ElfAssembler::Add(InsnSize insnSize, Reg srcReg, Reg destReg)
1490 {
1491     OpRR(srcReg, destReg, 0x00);
1492 }
1493 
Add(InsnSize insnSize,const ImmOpnd & immOpnd,Reg reg)1494 void ElfAssembler::Add(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg)
1495 {
1496     OpImmAndReg(immOpnd, reg, 0x00, 0);
1497 }
1498 
Add(InsnSize insnSize,const Mem & mem,Reg reg)1499 void ElfAssembler::Add(InsnSize insnSize, const Mem &mem, Reg reg)
1500 {
1501     OpRM(reg, mem, 0x02);
1502 }
1503 
Add(InsnSize insnSize,Reg reg,const Mem & mem)1504 void ElfAssembler::Add(InsnSize insnSize, Reg reg, const Mem &mem)
1505 {
1506     OpRM(reg, mem, 0x00);
1507 }
1508 
Add(InsnSize insnSize,const ImmOpnd & immOpnd,const Mem & mem)1509 void ElfAssembler::Add(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem)
1510 {
1511     OpImmAndMem(immOpnd, mem, 0);
1512 }
1513 
1514 /* add floating point */
Add(Reg srcReg,Reg destReg,bool isSingle)1515 void ElfAssembler::Add(Reg srcReg, Reg destReg, bool isSingle)
1516 {
1517     if (isSingle) {
1518         Encodeb(0xF3);
1519     } else {
1520         Encodeb(0xF2);
1521     }
1522     OpRR(destReg, srcReg, 0x0F, 0x58);
1523 }
1524 
Add(const Mem & mem,Reg reg,bool isSingle)1525 void ElfAssembler::Add(const Mem &mem, Reg reg, bool isSingle)
1526 {
1527     if (isSingle) {
1528         Encodeb(0xF3);
1529     } else {
1530         Encodeb(0xF2);
1531     }
1532     OpRM(reg, mem, 0x0F, 0x58);
1533 }
1534 
1535 /* sub */
Sub(InsnSize insnSize,Reg srcReg,Reg destReg)1536 void ElfAssembler::Sub(InsnSize insnSize, Reg srcReg, Reg destReg)
1537 {
1538     OpRR(srcReg, destReg, 0x28);
1539 }
1540 
Sub(InsnSize insnSize,const ImmOpnd & immOpnd,Reg reg)1541 void ElfAssembler::Sub(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg)
1542 {
1543     OpImmAndReg(immOpnd, reg, 0x28, kSubModReg);
1544 }
1545 
Sub(InsnSize insnSize,const Mem & mem,Reg reg)1546 void ElfAssembler::Sub(InsnSize insnSize, const Mem &mem, Reg reg)
1547 {
1548     OpRM(reg, mem, 0x2A);
1549 }
1550 
Sub(InsnSize insnSize,Reg reg,const Mem & mem)1551 void ElfAssembler::Sub(InsnSize insnSize, Reg reg, const Mem &mem)
1552 {
1553     OpRM(reg, mem, 0x28);
1554 }
1555 
Sub(InsnSize insnSize,const ImmOpnd & immOpnd,const Mem & mem)1556 void ElfAssembler::Sub(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem)
1557 {
1558     OpImmAndMem(immOpnd, mem, kSubModReg);
1559 }
1560 
1561 /* sub floating point */
Sub(Reg srcReg,Reg destReg,bool isSingle)1562 void ElfAssembler::Sub(Reg srcReg, Reg destReg, bool isSingle)
1563 {
1564     if (isSingle) {
1565         Encodeb(0xF3);
1566     } else {
1567         Encodeb(0xF2);
1568     }
1569     OpRR(destReg, srcReg, 0x0F, 0x5c);
1570 }
1571 
Sub(const Mem & mem,Reg reg,bool isSingle)1572 void ElfAssembler::Sub(const Mem &mem, Reg reg, bool isSingle)
1573 {
1574     if (isSingle) {
1575         Encodeb(0xF3);
1576     } else {
1577         Encodeb(0xF2);
1578     }
1579     OpRM(reg, mem, 0x0F, 0x5c);
1580 }
1581 
1582 /* and */
And(InsnSize insnSize,Reg srcReg,Reg destReg)1583 void ElfAssembler::And(InsnSize insnSize, Reg srcReg, Reg destReg)
1584 {
1585     OpRR(srcReg, destReg, 0x20);
1586 }
1587 
And(InsnSize insnSize,const Mem & mem,Reg reg)1588 void ElfAssembler::And(InsnSize insnSize, const Mem &mem, Reg reg)
1589 {
1590     OpRM(reg, mem, 0x21);
1591 }
1592 
And(InsnSize insnSize,const ImmOpnd & immOpnd,Reg reg)1593 void ElfAssembler::And(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg)
1594 {
1595     OpImmAndReg(immOpnd, reg, 0x20, kAndModReg);
1596 }
1597 
And(InsnSize insnSize,Reg reg,const Mem & mem)1598 void ElfAssembler::And(InsnSize insnSize, Reg reg, const Mem &mem)
1599 {
1600     OpRM(reg, mem, 0x20);
1601 }
1602 
And(InsnSize insnSize,const ImmOpnd & immOpnd,const Mem & mem)1603 void ElfAssembler::And(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem)
1604 {
1605     OpImmAndMem(immOpnd, mem, kAndModReg);
1606 }
1607 
1608 /* or */
Or(InsnSize insnSize,Reg srcReg,Reg destReg)1609 void ElfAssembler::Or(InsnSize insnSize, Reg srcReg, Reg destReg)
1610 {
1611     OpRR(srcReg, destReg, 0x08);
1612 }
1613 
Or(InsnSize insnSize,const Mem & mem,Reg reg)1614 void ElfAssembler::Or(InsnSize insnSize, const Mem &mem, Reg reg)
1615 {
1616     OpRM(reg, mem, 0x0A);
1617 }
1618 
Or(InsnSize insnSize,const ImmOpnd & immOpnd,Reg reg)1619 void ElfAssembler::Or(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg)
1620 {
1621     OpImmAndReg(immOpnd, reg, 0x08, kOrModReg);
1622 }
1623 
Or(InsnSize insnSize,Reg reg,const Mem & mem)1624 void ElfAssembler::Or(InsnSize insnSize, Reg reg, const Mem &mem)
1625 {
1626     OpRM(reg, mem, 0x08);
1627 }
1628 
Or(InsnSize insnSize,const ImmOpnd & immOpnd,const Mem & mem)1629 void ElfAssembler::Or(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem)
1630 {
1631     OpImmAndMem(immOpnd, mem, kOrModReg);
1632 }
1633 
1634 /* xor */
Xor(InsnSize insnSize,Reg srcReg,Reg destReg)1635 void ElfAssembler::Xor(InsnSize insnSize, Reg srcReg, Reg destReg)
1636 {
1637     OpRR(srcReg, destReg, 0x30);
1638 }
1639 
Xor(InsnSize insnSize,const ImmOpnd & immOpnd,Reg reg)1640 void ElfAssembler::Xor(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg)
1641 {
1642     OpImmAndReg(immOpnd, reg, 0x30, kXorModReg);
1643 }
1644 
Xor(InsnSize insnSize,const Mem & mem,Reg reg)1645 void ElfAssembler::Xor(InsnSize insnSize, const Mem &mem, Reg reg)
1646 {
1647     OpRM(reg, mem, 0x32);
1648 }
1649 
Xor(InsnSize insnSize,Reg reg,const Mem & mem)1650 void ElfAssembler::Xor(InsnSize insnSize, Reg reg, const Mem &mem)
1651 {
1652     OpRM(reg, mem, 0x30);
1653 }
1654 
Xor(InsnSize insnSize,const ImmOpnd & immOpnd,const Mem & mem)1655 void ElfAssembler::Xor(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem)
1656 {
1657     OpImmAndMem(immOpnd, mem, kXorModReg);
1658 }
1659 
1660 /* bsr */
Bsr(InsnSize insnSize,Reg srcReg,Reg destReg)1661 void ElfAssembler::Bsr(InsnSize insnSize, Reg srcReg, Reg destReg)
1662 {
1663     OpRR(srcReg, destReg, 0x0f, 0xbd);
1664 }
1665 
1666 /* not */
Not(InsnSize insnSize,Reg reg)1667 void ElfAssembler::Not(InsnSize insnSize, Reg reg)
1668 {
1669     OpReg(reg, 0xF6, 0, kNotModReg);
1670 }
1671 
Not(InsnSize insnSize,const Mem & mem)1672 void ElfAssembler::Not(InsnSize insnSize, const Mem &mem)
1673 {
1674     OpMem(mem, 0xF6, 0, kNotModReg);
1675 }
1676 
1677 /* neg */
Neg(InsnSize insnSize,Reg reg)1678 void ElfAssembler::Neg(InsnSize insnSize, Reg reg)
1679 {
1680     OpReg(reg, 0xF6, 0, kNegModReg);
1681 }
1682 
Neg(InsnSize insnSize,const Mem & mem)1683 void ElfAssembler::Neg(InsnSize insnSize, const Mem &mem)
1684 {
1685     OpMem(mem, 0xF6, 0, kNegModReg);
1686 }
1687 
1688 /* div & cwd, cdq, cqo */
Idiv(InsnSize insnSize,Reg reg)1689 void ElfAssembler::Idiv(InsnSize insnSize, Reg reg)
1690 {
1691     OpReg(reg, 0xF6, 0, kIdivModReg);
1692 }
1693 
Idiv(InsnSize insnSize,const Mem & mem)1694 void ElfAssembler::Idiv(InsnSize insnSize, const Mem &mem)
1695 {
1696     OpMem(mem, 0xF6, 0, kIdivModReg);
1697 }
1698 
Div(InsnSize insnSize,Reg reg)1699 void ElfAssembler::Div(InsnSize insnSize, Reg reg)
1700 {
1701     OpReg(reg, 0xF6, 0, kDivModReg);
1702 }
1703 
Div(InsnSize insnSize,const Mem & mem)1704 void ElfAssembler::Div(InsnSize insnSize, const Mem &mem)
1705 {
1706     OpMem(mem, 0xF6, 0, kDivModReg);
1707 }
1708 
Cwd()1709 void ElfAssembler::Cwd()
1710 {
1711     Encodeb(0x66);
1712     Encodeb(0x99);
1713 }
1714 
Cdq()1715 void ElfAssembler::Cdq()
1716 {
1717     Encodeb(0x99);
1718 }
1719 
Cqo()1720 void ElfAssembler::Cqo()
1721 {
1722     Encodeb(0x48);
1723     Encodeb(0x99);
1724 }
1725 
1726 /* shl */
Shl(InsnSize insnSize,Reg srcReg,Reg destReg)1727 void ElfAssembler::Shl(InsnSize insnSize, Reg srcReg, Reg destReg)
1728 {
1729     OpReg(destReg, 0xD2, 0, kShlModReg);
1730 }
1731 
Shl(InsnSize insnSize,const ImmOpnd & immOpnd,Reg reg)1732 void ElfAssembler::Shl(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg)
1733 {
1734     OpReg(reg, 0xC0, 0, kShlModReg);
1735     Encodeb(static_cast<uint64>(immOpnd.first));
1736 }
1737 
Shl(InsnSize insnSize,Reg reg,const Mem & mem)1738 void ElfAssembler::Shl(InsnSize insnSize, Reg reg, const Mem &mem)
1739 {
1740     OpMem(mem, 0xD2, 0, kShlModReg);
1741 }
1742 
Shl(InsnSize insnSize,const ImmOpnd & immOpnd,const Mem & mem)1743 void ElfAssembler::Shl(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem)
1744 {
1745     OpMem(mem, 0xC0, 0, kShlModReg);
1746     Encodeb(static_cast<uint64>(immOpnd.first));
1747 }
1748 
1749 /* sar */
Sar(InsnSize insnSize,Reg srcReg,Reg destReg)1750 void ElfAssembler::Sar(InsnSize insnSize, Reg srcReg, Reg destReg)
1751 {
1752     OpReg(destReg, 0xD2, 0, kSarModReg);
1753 }
1754 
Sar(InsnSize insnSize,const ImmOpnd & immOpnd,Reg reg)1755 void ElfAssembler::Sar(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg)
1756 {
1757     OpReg(reg, 0xC0, 0, kSarModReg);
1758     Encodeb(static_cast<uint64>(immOpnd.first));
1759 }
1760 
Sar(InsnSize insnSize,Reg reg,const Mem & mem)1761 void ElfAssembler::Sar(InsnSize insnSize, Reg reg, const Mem &mem)
1762 {
1763     OpMem(mem, 0xD2, 0, kSarModReg);
1764 }
1765 
Sar(InsnSize insnSize,const ImmOpnd & immOpnd,const Mem & mem)1766 void ElfAssembler::Sar(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem)
1767 {
1768     OpMem(mem, 0xC0, 0, kSarModReg);
1769     Encodeb(static_cast<uint64>(immOpnd.first));
1770 }
1771 
1772 /* shr */
Shr(InsnSize insnSize,Reg srcReg,Reg destReg)1773 void ElfAssembler::Shr(InsnSize insnSize, Reg srcReg, Reg destReg)
1774 {
1775     OpReg(destReg, 0xD2, 0, kShrModReg);
1776 }
1777 
Shr(InsnSize insnSize,const ImmOpnd & immOpnd,Reg reg)1778 void ElfAssembler::Shr(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg)
1779 {
1780     OpReg(reg, 0xC0, 0, kShrModReg);
1781     Encodeb(static_cast<uint64>(immOpnd.first));
1782 }
1783 
Shr(InsnSize insnSize,Reg reg,const Mem & mem)1784 void ElfAssembler::Shr(InsnSize insnSize, Reg reg, const Mem &mem)
1785 {
1786     OpMem(mem, 0xD2, 0, kShrModReg);
1787 }
1788 
Shr(InsnSize insnSize,const ImmOpnd & immOpnd,const Mem & mem)1789 void ElfAssembler::Shr(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem)
1790 {
1791     OpMem(mem, 0xC0, 0, kShrModReg);
1792     Encodeb(static_cast<uint64>(immOpnd.first));
1793 }
1794 
1795 /* jmp */
Jmp(Reg reg)1796 void ElfAssembler::Jmp(Reg reg)
1797 {
1798     OpReg(reg, 0xFF, 0, kJmpModReg);
1799 }
1800 
Jmp(const Mem & mem)1801 void ElfAssembler::Jmp(const Mem &mem)
1802 {
1803     OpMem(mem, 0xFF, 0, kJmpModReg);
1804 }
1805 
Jmp(int64 symIdx)1806 void ElfAssembler::Jmp(int64 symIdx)
1807 {
1808     JmpToLabel(symIdx, 0xE9);
1809 }
1810 
1811 /* jump condition */
Je(int64 symIdx)1812 void ElfAssembler::Je(int64 symIdx)
1813 {
1814     JmpToLabel(symIdx, 0x0F, 0x84);
1815 }
1816 
Ja(int64 symIdx)1817 void ElfAssembler::Ja(int64 symIdx)
1818 {
1819     JmpToLabel(symIdx, 0x0F, 0x87);
1820 }
1821 
Jae(int64 symIdx)1822 void ElfAssembler::Jae(int64 symIdx)
1823 {
1824     JmpToLabel(symIdx, 0x0F, 0x83);
1825 }
1826 
Jne(int64 symIdx)1827 void ElfAssembler::Jne(int64 symIdx)
1828 {
1829     JmpToLabel(symIdx, 0x0F, 0x85);
1830 }
1831 
Jb(int64 symIdx)1832 void ElfAssembler::Jb(int64 symIdx)
1833 {
1834     JmpToLabel(symIdx, 0x0F, 0x82);
1835 }
1836 
Jbe(int64 symIdx)1837 void ElfAssembler::Jbe(int64 symIdx)
1838 {
1839     JmpToLabel(symIdx, 0x0F, 0x86);
1840 }
1841 
Jg(int64 symIdx)1842 void ElfAssembler::Jg(int64 symIdx)
1843 {
1844     JmpToLabel(symIdx, 0x0F, 0x8F);
1845 }
1846 
Jge(int64 symIdx)1847 void ElfAssembler::Jge(int64 symIdx)
1848 {
1849     JmpToLabel(symIdx, 0x0F, 0x8D);
1850 }
1851 
Jl(int64 symIdx)1852 void ElfAssembler::Jl(int64 symIdx)
1853 {
1854     JmpToLabel(symIdx, 0x0F, 0x8C);
1855 }
1856 
Jle(int64 symIdx)1857 void ElfAssembler::Jle(int64 symIdx)
1858 {
1859     JmpToLabel(symIdx, 0x0F, 0x8E);
1860 }
1861 
1862 /* cmp */
Cmp(InsnSize insnSize,Reg srcReg,Reg destReg)1863 void ElfAssembler::Cmp(InsnSize insnSize, Reg srcReg, Reg destReg)
1864 {
1865     OpRR(srcReg, destReg, 0x38);
1866 }
1867 
Cmp(InsnSize insnSize,const Mem & mem,Reg reg)1868 void ElfAssembler::Cmp(InsnSize insnSize, const Mem &mem, Reg reg)
1869 {
1870     OpRM(reg, mem, 0x3A);
1871 }
1872 
Cmp(InsnSize insnSize,Reg reg,const Mem & mem)1873 void ElfAssembler::Cmp(InsnSize insnSize, Reg reg, const Mem &mem)
1874 {
1875     OpRM(reg, mem, 0x38);
1876 }
1877 
Cmp(InsnSize insnSize,const ImmOpnd & immOpnd,Reg reg)1878 void ElfAssembler::Cmp(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg)
1879 {
1880     OpImmAndReg(immOpnd, reg, 0x38, kCmpModReg);
1881 }
1882 
Cmp(InsnSize insnSize,const ImmOpnd & immOpnd,const Mem & mem)1883 void ElfAssembler::Cmp(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem)
1884 {
1885     OpImmAndMem(immOpnd, mem, kCmpModReg);
1886 }
1887 
1888 /* test */
Test(InsnSize insnSize,Reg srcReg,Reg destReg)1889 void ElfAssembler::Test(InsnSize insnSize, Reg srcReg, Reg destReg)
1890 {
1891     OpRR(srcReg, destReg, 0x84);
1892 }
1893 
1894 /* setcc */
Setbe(Reg reg)1895 void ElfAssembler::Setbe(Reg reg)
1896 {
1897     OpReg(reg, 0x0F, 0x96, 0);
1898 }
1899 
Setbe(const Mem & mem)1900 void ElfAssembler::Setbe(const Mem &mem)
1901 {
1902     OpMem(mem, 0x0F, 0x96, 0);
1903 }
1904 
Setle(Reg reg)1905 void ElfAssembler::Setle(Reg reg)
1906 {
1907     OpReg(reg, 0x0F, 0x9E, 0);
1908 }
1909 
Setle(const Mem & mem)1910 void ElfAssembler::Setle(const Mem &mem)
1911 {
1912     OpMem(mem, 0x0F, 0x9E, 0);
1913 }
1914 
Setae(Reg reg)1915 void ElfAssembler::Setae(Reg reg)
1916 {
1917     OpReg(reg, 0x0F, 0x93, 0);
1918 }
1919 
Setae(const Mem & mem)1920 void ElfAssembler::Setae(const Mem &mem)
1921 {
1922     OpMem(mem, 0x0F, 0x93, 0);
1923 }
1924 
Setge(Reg reg)1925 void ElfAssembler::Setge(Reg reg)
1926 {
1927     OpReg(reg, 0x0F, 0x9D, 0);
1928 }
Setge(const Mem & mem)1929 void ElfAssembler::Setge(const Mem &mem)
1930 {
1931     OpMem(mem, 0x0F, 0x9D, 0);
1932 }
1933 
Setne(Reg reg)1934 void ElfAssembler::Setne(Reg reg)
1935 {
1936     OpReg(reg, 0x0F, 0x95, 0);
1937 }
1938 
Setne(const Mem & mem)1939 void ElfAssembler::Setne(const Mem &mem)
1940 {
1941     OpMem(mem, 0x0F, 0x95, 0);
1942 }
1943 
Setb(Reg reg)1944 void ElfAssembler::Setb(Reg reg)
1945 {
1946     OpReg(reg, 0x0F, 0x92, 0);
1947 }
1948 
Setb(const Mem & mem)1949 void ElfAssembler::Setb(const Mem &mem)
1950 {
1951     OpMem(mem, 0x0F, 0x92, 0);
1952 }
1953 
Setl(Reg reg)1954 void ElfAssembler::Setl(Reg reg)
1955 {
1956     OpReg(reg, 0x0F, 0x9C, 0);
1957 }
1958 
Setl(const Mem & mem)1959 void ElfAssembler::Setl(const Mem &mem)
1960 {
1961     OpMem(mem, 0x0F, 0x9C, 0);
1962 }
1963 
Seta(Reg reg)1964 void ElfAssembler::Seta(Reg reg)
1965 {
1966     OpReg(reg, 0x0F, 0x97, 0);
1967 }
1968 
Seta(const Mem & mem)1969 void ElfAssembler::Seta(const Mem &mem)
1970 {
1971     OpMem(mem, 0x0F, 0x97, 0);
1972 }
1973 
Setg(Reg reg)1974 void ElfAssembler::Setg(Reg reg)
1975 {
1976     OpReg(reg, 0x0F, 0x9F, 0);
1977 }
1978 
Setg(const Mem & mem)1979 void ElfAssembler::Setg(const Mem &mem)
1980 {
1981     OpMem(mem, 0x0F, 0x9F, 0);
1982 }
1983 
Sete(Reg reg)1984 void ElfAssembler::Sete(Reg reg)
1985 {
1986     OpReg(reg, 0x0F, 0x94, 0);
1987 }
1988 
Sete(const Mem & mem)1989 void ElfAssembler::Sete(const Mem &mem)
1990 {
1991     OpMem(mem, 0x0F, 0x94, 0);
1992 }
1993 
Seto(Reg reg)1994 void ElfAssembler::Seto(Reg reg)
1995 {
1996     OpReg(reg, 0x0F, 0x90, 0);
1997 }
1998 
Seto(const Mem & mem)1999 void ElfAssembler::Seto(const Mem &mem)
2000 {
2001     OpMem(mem, 0x0F, 0x90, 0);
2002 }
2003 
2004 /* cmov */
Cmova(InsnSize insnSize,Reg srcReg,Reg destReg)2005 void ElfAssembler::Cmova(InsnSize insnSize, Reg srcReg, Reg destReg)
2006 {
2007     OpCmovcc(srcReg, destReg, 0x0F, 0x47);
2008 }
2009 
Cmova(InsnSize insnSize,const Mem & mem,Reg reg)2010 void ElfAssembler::Cmova(InsnSize insnSize, const Mem &mem, Reg reg)
2011 {
2012     OpRM(reg, mem, 0x0E, 0x47);
2013 }
Cmovae(InsnSize insnSize,Reg srcReg,Reg destReg)2014 void ElfAssembler::Cmovae(InsnSize insnSize, Reg srcReg, Reg destReg)
2015 {
2016     OpCmovcc(srcReg, destReg, 0x0F, 0x43);
2017 }
2018 
Cmovae(InsnSize insnSize,const Mem & mem,Reg reg)2019 void ElfAssembler::Cmovae(InsnSize insnSize, const Mem &mem, Reg reg)
2020 {
2021     OpRM(reg, mem, 0x0E, 0x43);
2022 }
2023 
Cmovb(InsnSize insnSize,Reg srcReg,Reg destReg)2024 void ElfAssembler::Cmovb(InsnSize insnSize, Reg srcReg, Reg destReg)
2025 {
2026     OpCmovcc(srcReg, destReg, 0x0F, 0x42);
2027 }
2028 
Cmovb(InsnSize insnSize,const Mem & mem,Reg reg)2029 void ElfAssembler::Cmovb(InsnSize insnSize, const Mem &mem, Reg reg)
2030 {
2031     OpRM(reg, mem, 0x0E, 0x42);
2032 }
2033 
Cmovbe(InsnSize insnSize,Reg srcReg,Reg destReg)2034 void ElfAssembler::Cmovbe(InsnSize insnSize, Reg srcReg, Reg destReg)
2035 {
2036     OpCmovcc(srcReg, destReg, 0x0F, 0x46);
2037 }
2038 
Cmovbe(InsnSize insnSize,const Mem & mem,Reg reg)2039 void ElfAssembler::Cmovbe(InsnSize insnSize, const Mem &mem, Reg reg)
2040 {
2041     OpRM(reg, mem, 0x0E, 0x46);
2042 }
2043 
Cmove(InsnSize insnSize,Reg srcReg,Reg destReg)2044 void ElfAssembler::Cmove(InsnSize insnSize, Reg srcReg, Reg destReg)
2045 {
2046     OpCmovcc(srcReg, destReg, 0x0F, 0x44);
2047 }
2048 
Cmove(InsnSize insnSize,const Mem & mem,Reg reg)2049 void ElfAssembler::Cmove(InsnSize insnSize, const Mem &mem, Reg reg)
2050 {
2051     OpRM(reg, mem, 0x0E, 0x44);
2052 }
2053 
Cmovg(InsnSize insnSize,Reg srcReg,Reg destReg)2054 void ElfAssembler::Cmovg(InsnSize insnSize, Reg srcReg, Reg destReg)
2055 {
2056     OpCmovcc(srcReg, destReg, 0x0F, 0x4F);
2057 }
2058 
Cmovg(InsnSize insnSize,const Mem & mem,Reg reg)2059 void ElfAssembler::Cmovg(InsnSize insnSize, const Mem &mem, Reg reg)
2060 {
2061     OpRM(reg, mem, 0x0E, 0x4F);
2062 }
2063 
Cmovge(InsnSize insnSize,Reg srcReg,Reg destReg)2064 void ElfAssembler::Cmovge(InsnSize insnSize, Reg srcReg, Reg destReg)
2065 {
2066     OpCmovcc(srcReg, destReg, 0x0F, 0x4D);
2067 }
2068 
Cmovge(InsnSize insnSize,const Mem & mem,Reg reg)2069 void ElfAssembler::Cmovge(InsnSize insnSize, const Mem &mem, Reg reg)
2070 {
2071     OpRM(reg, mem, 0x0E, 0x4D);
2072 }
2073 
Cmovl(InsnSize insnSize,Reg srcReg,Reg destReg)2074 void ElfAssembler::Cmovl(InsnSize insnSize, Reg srcReg, Reg destReg)
2075 {
2076     OpCmovcc(srcReg, destReg, 0x0F, 0x4C);
2077 }
2078 
Cmovl(InsnSize insnSize,const Mem & mem,Reg reg)2079 void ElfAssembler::Cmovl(InsnSize insnSize, const Mem &mem, Reg reg)
2080 {
2081     OpRM(reg, mem, 0x0E, 0x4C);
2082 }
2083 
Cmovle(InsnSize insnSize,Reg srcReg,Reg destReg)2084 void ElfAssembler::Cmovle(InsnSize insnSize, Reg srcReg, Reg destReg)
2085 {
2086     OpCmovcc(srcReg, destReg, 0x0F, 0x4E);
2087 }
2088 
Cmovle(InsnSize insnSize,const Mem & mem,Reg reg)2089 void ElfAssembler::Cmovle(InsnSize insnSize, const Mem &mem, Reg reg)
2090 {
2091     OpRM(reg, mem, 0x0E, 0x4E);
2092 }
2093 
Cmovo(InsnSize insnSize,Reg srcReg,Reg destReg)2094 void ElfAssembler::Cmovo(InsnSize insnSize, Reg srcReg, Reg destReg)
2095 {
2096     OpCmovcc(srcReg, destReg, 0x0F, 0x40);
2097 }
2098 
Cmovne(InsnSize insnSize,Reg srcReg,Reg destReg)2099 void ElfAssembler::Cmovne(InsnSize insnSize, Reg srcReg, Reg destReg)
2100 {
2101     OpCmovcc(srcReg, destReg, 0x0F, 0x45);
2102 }
2103 
Cmovne(InsnSize insnSize,const Mem & mem,Reg reg)2104 void ElfAssembler::Cmovne(InsnSize insnSize, const Mem &mem, Reg reg)
2105 {
2106     OpRM(reg, mem, 0x0E, 0x45);
2107 }
2108 
2109 /* call */
Call(InsnSize insnSize,Reg reg)2110 void ElfAssembler::Call(InsnSize insnSize, Reg reg)
2111 {
2112     // Save to disignate memory
2113     OpReg(reg, 0xFF, 0, kCallModReg);
2114 }
2115 
Call(InsnSize insnSize,const Mem & mem)2116 void ElfAssembler::Call(InsnSize insnSize, const Mem &mem)
2117 {
2118     OpMem(mem, 0xFF, 0, kCallModReg);
2119 }
2120 
Call(InsnSize insnSize,int64 symIdx)2121 void ElfAssembler::Call(InsnSize insnSize, int64 symIdx)
2122 {
2123     Encodeb(0xE8);
2124     if (!CanEncodeLabel(symIdx)) {
2125         size_t offsetSize = 4;
2126         UpdateLabel(symIdx, LabelType::kFunc);
2127         AppendFixup(symIdx, kPLT, {static_cast<uint32>(codeBuff.size()), offsetSize}, fixups);
2128         uint8 imm = 0;
2129         Encodeb(imm, offsetSize);
2130     }
2131 }
2132 
2133 /* ret */
Ret()2134 void ElfAssembler::Ret()
2135 {
2136     Encodeb(0xC3);
2137 }
2138 
2139 /* leave */
Leave()2140 void ElfAssembler::Leave()
2141 {
2142     Encodeb(0xC9);
2143 }
2144 
2145 /* imul */
Imul(InsnSize insnSize,Reg srcReg,Reg destReg)2146 void ElfAssembler::Imul(InsnSize insnSize, Reg srcReg, Reg destReg)
2147 {
2148     OpRR(destReg, srcReg, 0x0F, 0xAF);
2149 }
2150 
2151 /* mul float */
Mul(Reg srcReg,Reg destReg,bool isSingle)2152 void ElfAssembler::Mul(Reg srcReg, Reg destReg, bool isSingle)
2153 {
2154     if (isSingle) {
2155         Encodeb(0xF3);
2156     } else {
2157         Encodeb(0xF2);
2158     }
2159     OpRR(destReg, srcReg, 0x0F, 0x59);
2160 }
2161 
Mul(const Mem & mem,Reg reg,bool isSingle)2162 void ElfAssembler::Mul(const Mem &mem, Reg reg, bool isSingle)
2163 {
2164     if (isSingle) {
2165         Encodeb(0xF3);
2166     } else {
2167         Encodeb(0xF2);
2168     }
2169     OpRM(reg, mem, 0x0F, 0x59);
2170 }
2171 
2172 /* nop */
Nop(InsnSize insnSize,const Mem & mem)2173 void ElfAssembler::Nop(InsnSize insnSize, const Mem &mem)
2174 {
2175     OpMem(mem, 0x0E, 0x1F, 0);
2176 }
2177 
Nop()2178 void ElfAssembler::Nop()
2179 {
2180     Encodeb(0x90);
2181 }
2182 
2183 /* byte swap */
Bswap(InsnSize insnSize,Reg reg)2184 void ElfAssembler::Bswap(InsnSize insnSize, Reg reg)
2185 {
2186     uint8 rex = GetRex(reg);
2187     if (rex != 0) {
2188         Encodeb(rex);
2189     }
2190     Encodeb(0x0F);
2191     Encodeb(0xC8 | GetRegCodeId(reg));
2192 }
2193 
Xchg(InsnSize insnSize,Reg srcReg,Reg destReg)2194 void ElfAssembler::Xchg(InsnSize insnSize, Reg srcReg, Reg destReg)
2195 {
2196     /* if the reg is ax, eax or rax */
2197     if ((GetRegId(srcReg) == 0 || GetRegId(destReg) == 0) && GetRegSize(srcReg) != k8Bits) {
2198         uint8 rex = GetRex(srcReg, destReg);
2199         if (rex != 0) {
2200             Encodeb(rex);
2201         } else if (GetRegSize(srcReg) == k16Bits) {
2202             Encodeb(0x66);
2203         }
2204         uint8 regCodeId = GetRegId(srcReg) == 0 ? GetRegCodeId(destReg) : GetRegCodeId(srcReg);
2205         Encodeb(0x90 | regCodeId);
2206     } else {
2207         OpRR(srcReg, destReg, 0x86);
2208     }
2209 }
2210 
2211 /* floating point */
MovF(Reg srcReg,Reg destReg,bool isSingle)2212 void ElfAssembler::MovF(Reg srcReg, Reg destReg, bool isSingle)
2213 {
2214     bool isXMM = GetRegSize(srcReg) == k128Bits || GetRegSize(destReg) == k128Bits;
2215     if (isSingle) {
2216         if (isXMM) {
2217             Encodeb(0xF3);
2218         }
2219         OpRR(destReg, srcReg, 0x0F, 0x10);
2220     } else {
2221         if (isXMM) {
2222             Encodeb(0xF2);
2223         }
2224         OpRR(destReg, srcReg, 0x0F, 0x10);
2225     }
2226 }
2227 
2228 /* floating point and */
And(Reg srcReg,Reg destReg,bool isSingle)2229 void ElfAssembler::And(Reg srcReg, Reg destReg, bool isSingle)
2230 {
2231     if (isSingle) {
2232         Encodeb(0x100);
2233     } else {
2234         Encodeb(0x66);
2235     }
2236     OpRR(destReg, srcReg, 0x0F, 0x54);
2237 }
2238 
And(const Mem & mem,Reg reg,bool isSingle)2239 void ElfAssembler::And(const Mem &mem, Reg reg, bool isSingle)
2240 {
2241     if (isSingle) {
2242         Encodeb(0x100);
2243     } else {
2244         Encodeb(0x66);
2245     }
2246     OpRM(reg, mem, 0x0F, 0x54);
2247 }
2248 
2249 /* floating div */
Divsd(Reg srcReg,Reg destReg)2250 void ElfAssembler::Divsd(Reg srcReg, Reg destReg)
2251 {
2252     Encodeb(0xF2);
2253     OpRR(destReg, srcReg, 0x0F, 0x5E);
2254 }
2255 
Divsd(const Mem & mem,Reg reg)2256 void ElfAssembler::Divsd(const Mem &mem, Reg reg)
2257 {
2258     Encodeb(0xF2);
2259     OpRM(reg, mem, 0x0F, 0x5E);
2260 }
2261 
2262 /* convert int2float */
Cvtsi2ss(InsnSize insnSize,Reg srcReg,Reg destReg)2263 void ElfAssembler::Cvtsi2ss(InsnSize insnSize, Reg srcReg, Reg destReg)
2264 {
2265     Encodeb(0xF3);
2266     OpRR(destReg, srcReg, 0x0F, 0x2A);
2267 }
2268 
Cvtsi2sd(InsnSize insnSize,Reg srcReg,Reg destReg)2269 void ElfAssembler::Cvtsi2sd(InsnSize insnSize, Reg srcReg, Reg destReg)
2270 {
2271     Encodeb(0xF2);
2272     OpRR(destReg, srcReg, 0x0F, 0x2A);
2273 }
2274 
2275 /*convert float2int */
Cvttsd2si(InsnSize insnSize,Reg srcReg,Reg destReg)2276 void ElfAssembler::Cvttsd2si(InsnSize insnSize, Reg srcReg, Reg destReg)
2277 {
2278     Encodeb(0xF2);
2279     OpRR(destReg, srcReg, 0x0F, 0x2C);
2280 }
2281 
Cvttss2si(InsnSize insnSize,Reg srcReg,Reg destReg)2282 void ElfAssembler::Cvttss2si(InsnSize insnSize, Reg srcReg, Reg destReg)
2283 {
2284     Encodeb(0xF3);
2285     OpRR(destReg, srcReg, 0x0F, 0x2C);
2286 }
2287 
2288 /* convert float2float */
Cvtss2sd(Reg srcReg,Reg destReg)2289 void ElfAssembler::Cvtss2sd(Reg srcReg, Reg destReg)
2290 {
2291     Encodeb(0xF3);
2292     OpRR(destReg, srcReg, 0x0F, 0x5A);
2293 }
2294 
Cvtsd2ss(Reg srcReg,Reg destReg)2295 void ElfAssembler::Cvtsd2ss(Reg srcReg, Reg destReg)
2296 {
2297     Encodeb(0xF2);
2298     OpRR(destReg, srcReg, 0x0F, 0x5A);
2299 }
2300 
2301 /* unordered compare */
Ucomisd(Reg srcReg,Reg destReg)2302 void ElfAssembler::Ucomisd(Reg srcReg, Reg destReg)
2303 {
2304     Encodeb(0x66);
2305     OpRR(destReg, srcReg, 0x0F, 0x2E);
2306 }
2307 
Ucomiss(Reg srcReg,Reg destReg)2308 void ElfAssembler::Ucomiss(Reg srcReg, Reg destReg)
2309 {
2310     Encodeb(0x100);
2311     OpRR(destReg, srcReg, 0x0F, 0x2E);
2312 }
2313 
Cmpsd(Reg srcReg,Reg destReg,uint8 imm)2314 void ElfAssembler::Cmpsd(Reg srcReg, Reg destReg, uint8 imm)
2315 {
2316     Encodeb(0xF2);
2317     OpRR(destReg, srcReg, 0x0F, 0xC2);
2318     Encodeb(imm);
2319 }
2320 
Cmpeqsd(Reg srcReg,Reg destReg)2321 void ElfAssembler::Cmpeqsd(Reg srcReg, Reg destReg)
2322 {
2323     Cmpsd(srcReg, destReg, 0);
2324 }
2325 
2326 /* float sqrt*/
Sqrtss_r(Reg srcReg,Reg destReg)2327 void ElfAssembler::Sqrtss_r(Reg srcReg, Reg destReg)
2328 {
2329     Encodeb(0xF3);
2330     OpRR(destReg, srcReg, 0x0F, 0x51);
2331 }
2332 
Sqrtsd_r(Reg srcReg,Reg destReg)2333 void ElfAssembler::Sqrtsd_r(Reg srcReg, Reg destReg)
2334 {
2335     Encodeb(0xF2);
2336     OpRR(destReg, srcReg, 0x0F, 0x51);
2337 }
2338 /* end of X64 instructions */
2339 
2340 /* process stackmap */
RecordStackmap(const std::vector<uint8> & referenceMap,const std::vector<uint8> & deoptVreg2LocationInfo)2341 void ElfAssembler::RecordStackmap(const std::vector<uint8> &referenceMap,
2342                                   const std::vector<uint8> &deoptVreg2LocationInfo)
2343 {
2344     const auto &emitMemoryManager = maplebe::CGOptions::GetInstance().GetEmitMemoryManager();
2345     if (emitMemoryManager.codeSpace == nullptr) {
2346         return;
2347     }
2348     emitMemoryManager.pc2CallSiteInfoSaver(emitMemoryManager.codeSpace, lastModulePC + codeBuff.size(), referenceMap);
2349     emitMemoryManager.pc2DeoptInfoSaver(emitMemoryManager.codeSpace, lastModulePC + codeBuff.size(),
2350                                         deoptVreg2LocationInfo);
2351 }
2352 
GetCurModulePC()2353 uint32 ElfAssembler::GetCurModulePC()
2354 {
2355     return static_cast<uint32>(lastModulePC + codeBuff.size());
2356 }
2357 
SetLastModulePC(uint32 pc)2358 void ElfAssembler::SetLastModulePC(uint32 pc)
2359 {
2360     lastModulePC = pc;
2361 }
2362 } /* namespace assembler */