• 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 #ifndef ELF_ASSEMBLER_H
17 #define ELF_ASSEMBLER_H
18 
19 #include "assembler.h"
20 #include "elf_file.h"
21 #include "cg_option.h"
22 
23 namespace assembler {
24 const uint8 kLeftShift6Bits = 6;
25 const uint8 kLeftShift3Bits = 3;
26 const uint8 kGetLow3Bits = 0b111;
27 const uint8 kLeftShift32Bits = 32;
28 const uint8 kLeftShift4Bits = 4;
29 
30 class ElfAssembler : public Assembler {
31 public:
ElfAssembler(const std::string & outputFileName)32     ElfAssembler(const std::string &outputFileName) : Assembler()
33     {
34         const auto &emitMemoryManager = maplebe::CGOptions::GetInstance().GetEmitMemoryManager();
35         if (emitMemoryManager.codeSpace == nullptr) {
36             outFStream.open(outputFileName, std::ios::trunc | std::ios::binary);
37         }
38     }
39 
40     ~ElfAssembler() = default;
41 
42     /* override function in base class */
43     void InitialFileInfo(const std::string &inputFileName) override;
44     void EmitVariable(int64 symIdx, uint64 sizeInByte, uint8 alignInByte, SymbolAttr symAttr,
45                       SectionKind sectionKind) override;
46     void EmitFunctionHeader(int64 symIdx, SymbolAttr funcAttr, const std::string *secName) override;
47     void EmitBBLabel(int64 labelSymIdx, bool genVerboseInfo, uint32 freq, const std::string *mirName) override;
48     void EmitJmpTableElem(int64 jmpLabelIdx, const std::vector<int64> &labelSymIdxs) override;
49     void EmitFunctionFoot(int64 symIdx, SymbolAttr funcAttr) override;
50     void EmitDirectString(const std::string &ustr, bool belongsToDataSec, int64 strSymIdx, bool emitAscii) override;
51     void EmitIndirectString(int64 strSymIdx, bool belongsToDataSec) override;
52     void EmitIntValue(int64 value, size_t valueSize, bool belongsToDataSec) override;
53     void EmitFloatValue(int64 symIdx, int64 value, size_t valueSize) override;
54     void EmitAddrValue(int64 symIdx, int32 symAddrOfs, int32 structFieldOfs, bool belongsToDataSec) override;
55     void EmitAddrOfFuncValue(int64 symIdx, bool belongsToDataSec) override;
56     void EmitLabelValue(int64 symIdx, bool belongsToDataSec) override;
57     void EmitBitFieldValue(uint64 combineBitFieldValue, bool belongsToDataSec) override;
58     void EmitNull(uint64 sizeInByte) override;
59     void PostEmitVariable(int64 symIdx, SymbolAttr symAttr, uint64 sizeInByte, bool belongsToTextSec) override;
60     void FinalizeFileInfo() override;
61     void EmitBssSectionVar(int64 symIdx, uint64 sizeInByte, uint8 alignInByte, SymbolAttr symAttr);
62     void EmitDataSectionVar(int64 symIdx);
63 
64     /* emit debug info */
EmitDIHeader()65     void EmitDIHeader() override {};
EmitDIFooter()66     void EmitDIFooter() override {};
EmitDIHeaderFileInfo()67     void EmitDIHeaderFileInfo() override {};
68     void EmitDIDebugInfoSectionHeader(uint64 debugInfoLength) override;
69     void EmitDIDebugInfoSectionAbbrevId(bool verbose, uint32 abbrevId, const std::string &dieTagName, uint32 offset,
70                                         uint32 size) override;
71     /* nothing to do in ElfAssembler. */
EmitDIFormSpecification(unsigned int dwform)72     void EmitDIFormSpecification(unsigned int dwform) override {};
EmitDebugComment(const char * comment)73     void EmitDebugComment(const char* comment) override {};
74 
75     /* EmitDIAttrValue */
76     void EmitDwFormString(const std::string &name) override;
77     void EmitDwFormStrp(uint32 strLabelId, size_t strTableSize) override;
78     void EmitDwFormData(int32 attrValue, uint8 sizeInByte) override;
79     void EmitDwFormData8() override;
80     void EmitDwFormData8(uint32 endLabelFuncPuIdx, uint32 startLabelFuncPuIdx, uint32 endLabelIdx,
81                          uint32 startLabelIdx) override;
82     void EmitLabel(uint32 funcPuIdx, uint32 labIdx) override;
83     void EmitDwFormSecOffset() override;
84     void EmitDwFormAddr(bool emitTextBegin) override;
85     void EmitDwFormRef4(uint64 offsetOrValue, bool unknownType, bool emitOffset) override;
86     void EmitDwFormExprlocCfa(uint32 dwOp) override;
87     void EmitDwFormExprlocAddr(uint32 dwOp, const std::string &addrStr) override;
88     void EmitDwFormExprlocFbreg(uint32 dwOp, int fboffset, size_t sleb128Size) override;
89     void EmitDwFormExprlocBregn(uint32 dwOp, const std::string &dwOpName) override; /* n=0~7 */
90     void EmitDwFormExprloc(uintptr elp) override;
91 
EmitDIDwName(const std::string & dwAtName,const std::string & dwForName)92     void EmitDIDwName(const std::string &dwAtName, const std::string &dwForName) override {};
EmitDIDWFormStr(const std::string & formStr)93     void EmitDIDWFormStr(const std::string &formStr) override {};
EmitDIDWDataMemberLocaltion(unsigned int lableIdx,uintptr_t attr)94     void EmitDIDWDataMemberLocaltion(unsigned int lableIdx, uintptr_t attr) override {};
EmitDIDebugAbbrevSectionHeader()95     void EmitDIDebugAbbrevSectionHeader() override {};
96     void EmitDIDebugAbbrevDiae(bool verbose, uint32 abbrevId, uint32 tag, const std::string &dwTagName,
97                                bool withChildren) override;
98     void EmitDIDebugAbbrevDiaePairItem(bool verbose, uint32 aplAt, uint32 aplFrom, const std::string &dwAtName,
99                                        const std::string &dwFromName) override;
100     void EmitDIDebugSectionEnd(SectionKind secKind) override;
EmitDIDebugARangesSection()101     void EmitDIDebugARangesSection() override
102     {
103         debugARangesSection = new DataSection(".debug_aranges", SHT_PROGBITS, 0, 1);
104         RegisterSection(*debugARangesSection);
105     }
106 
EmitDIDebugRangesSection()107     void EmitDIDebugRangesSection() override
108     {
109         debugRangesSection = new DataSection(".debug_ranges", SHT_PROGBITS, 0, 1);
110         RegisterSection(*debugRangesSection);
111     }
112 
EmitDIDebugLineSection()113     void EmitDIDebugLineSection() override {};
114     void EmitDIDebugStrSection(const std::vector<uint32> &strps, const std::vector<std::string> &debugStrs, uint64 size,
115                                size_t strTableSize) override;
EmitLine()116     void EmitLine() override {};
117     void HandleDebugInfoSectionFixup();
118 
EncodeULEB128(uint64 value)119     const std::vector<uint8> &EncodeULEB128(uint64 value)
120     {
121         static std::vector<uint8> uleb128Value;
122         if (value == 0) {
123             uleb128Value.push_back(0);
124         }
125         int rightShift7Bits = 7;
126         while (value != 0) {
127             uint8 byte = value & 0x7F;
128             value >>= rightShift7Bits;
129             byte = value != 0 ? byte |= 0x80 : byte;
130             uleb128Value.push_back(byte);
131         }
132         return uleb128Value;
133     }
134 
EncodeSLEB128(int64 value)135     const std::vector<uint8> &EncodeSLEB128(int64 value)
136     {
137         static std::vector<uint8> sleb128Value;
138         int more = 1;
139         int rightShift7Bits = 7;
140         while (more != 0) {
141             uint8 byte = static_cast<uint8>(static_cast<uint64>(value) & 0x7F);
142             uint8 sign = static_cast<uint8>(static_cast<uint64>(value) & 0x40);
143             value = static_cast<uint64>(value) >> rightShift7Bits;
144             if ((value == 0 && sign == 0) || (value == -1 && sign != 0)) {
145                 more = 0;
146             } else {
147                 byte |= 0x80;
148             }
149             sleb128Value.push_back(byte);
150         }
151         return sleb128Value;
152     }
153 
154     /* start of X64 instructions */
155     /* mov */
156     void Mov(InsnSize insnSize, Reg srcReg, Reg destReg) override;
157     void Mov(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) override;
158     void Mov(InsnSize insnSize, const Mem &mem, Reg reg) override;
159     void Mov(InsnSize insnSize, Reg reg, const Mem &mem) override;
160     void Mov(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) override;
161     /* floating point mov */
162     void Mov(Reg srcReg, Reg destReg, bool isMovD) override;
163     void MovF(const Mem &mem, Reg reg, bool isSingle) override;
164     void MovF(Reg reg, const Mem &mem, bool isSingle) override;
165     /* movabs */
166     void Movabs(const ImmOpnd &immOpnd, Reg reg) override;
167     void Movabs(int64 symIdx, Reg reg) override;
168     /* push */
169     void Push(InsnSize insnSize, Reg reg) override;
170     /* pop */
171     void Pop(InsnSize insnSize, Reg reg) override;
172     /* lea */
173     void Lea(InsnSize insnSize, const Mem &mem, Reg reg) override;
174     /* movzx */
175     void MovZx(InsnSize sSize, InsnSize dSize, Reg srcReg, Reg destReg) override;
176     void MovZx(InsnSize sSize, InsnSize dSize, const Mem &mem, Reg reg) override;
177     /* movsx */
178     void MovSx(InsnSize sSize, InsnSize dSize, Reg srcReg, Reg destReg) override;
179     void MovSx(InsnSize sSize, InsnSize dSize, const Mem &mem, Reg reg) override;
180     /* add */
181     void Add(InsnSize insnSize, Reg srcReg, Reg destReg) override;
182     void Add(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) override;
183     void Add(InsnSize insnSize, const Mem &mem, Reg reg) override;
184     void Add(InsnSize insnSize, Reg reg, const Mem &mem) override;
185     void Add(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) override;
186     /* add floating point */
187     void Add(Reg srcReg, Reg destReg, bool isSingle) override;
188     void Add(const Mem &mem, Reg reg, bool isSingle) override;
189     /* sub */
190     void Sub(InsnSize insnSize, Reg srcReg, Reg destReg) override;
191     void Sub(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) override;
192     void Sub(InsnSize insnSize, const Mem &mem, Reg reg) override;
193     void Sub(InsnSize insnSize, Reg reg, const Mem &mem) override;
194     void Sub(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) override;
195     /* sub floating point */
196     void Sub(Reg srcReg, Reg destReg, bool isSingle) override;
197     void Sub(const Mem &mem, Reg reg, bool isSingle) override;
198     /* and */
199     void And(InsnSize insnSize, Reg srcReg, Reg destReg) override;
200     void And(InsnSize insnSize, const Mem &mem, Reg reg) override;
201     void And(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) override;
202     void And(InsnSize insnSize, Reg reg, const Mem &mem) override;
203     void And(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) override;
204     /* or */
205     void Or(InsnSize insnSize, Reg srcReg, Reg destReg) override;
206     void Or(InsnSize insnSize, const Mem &mem, Reg reg) override;
207     void Or(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) override;
208     void Or(InsnSize insnSize, Reg reg, const Mem &mem) override;
209     void Or(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) override;
210     /* xor */
211     void Xor(InsnSize insnSize, Reg srcReg, Reg destReg) override;
212     void Xor(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) override;
213     void Xor(InsnSize insnSize, const Mem &mem, Reg reg) override;
214     void Xor(InsnSize insnSize, Reg reg, const Mem &mem) override;
215     void Xor(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) override;
216     /* bsr */
217     void Bsr(InsnSize insnSize, Reg srcReg, Reg destReg) override;
218     /* not */
219     void Not(InsnSize insnSize, Reg reg) override;
220     void Not(InsnSize insnSize, const Mem &mem) override;
221     /* neg */
222     void Neg(InsnSize insnSize, Reg reg) override;
223     void Neg(InsnSize insnSize, const Mem &mem) override;
224     /* div & cwd, cdq, cqo */
225     void Idiv(InsnSize insnSize, Reg reg) override;
226     void Idiv(InsnSize insnSize, const Mem &mem) override;
227     void Div(InsnSize insnSize, Reg reg) override;
228     void Div(InsnSize insnSize, const Mem &mem) override;
229     void Cwd() override;
230     void Cdq() override;
231     void Cqo() override;
232     /* shl */
233     void Shl(InsnSize insnSize, Reg srcReg, Reg destReg) override;
234     void Shl(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) override;
235     void Shl(InsnSize insnSize, Reg reg, const Mem &mem) override;
236     void Shl(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) override;
237     /* sar */
238     void Sar(InsnSize insnSize, Reg srcReg, Reg destReg) override;
239     void Sar(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) override;
240     void Sar(InsnSize insnSize, Reg reg, const Mem &mem) override;
241     void Sar(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) override;
242     /* shr */
243     void Shr(InsnSize insnSize, Reg srcReg, Reg destReg) override;
244     void Shr(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) override;
245     void Shr(InsnSize insnSize, Reg reg, const Mem &mem) override;
246     void Shr(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) override;
247     /* jmp */
248     void Jmp(Reg reg) override;
249     void Jmp(const Mem &mem) override;
250     void Jmp(int64 symIdx) override;
251     /* jump condition */
252     void Je(int64 symIdx) override;
253     void Ja(int64 symIdx) override;
254     void Jae(int64 symIdx) override;
255     void Jne(int64 symIdx) override;
256     void Jb(int64 symIdx) override;
257     void Jbe(int64 symIdx) override;
258     void Jg(int64 symIdx) override;
259     void Jge(int64 symIdx) override;
260     void Jl(int64 symIdx) override;
261     void Jle(int64 symIdx) override;
262     /* cmp */
263     void Cmp(InsnSize insnSize, Reg srcReg, Reg destReg) override;
264     void Cmp(InsnSize insnSize, const Mem &mem, Reg reg) override;
265     void Cmp(InsnSize insnSize, Reg reg, const Mem &mem) override;
266     void Cmp(InsnSize insnSize, const ImmOpnd &immOpnd, Reg reg) override;
267     void Cmp(InsnSize insnSize, const ImmOpnd &immOpnd, const Mem &mem) override;
268     /* test */
269     void Test(InsnSize insnSize, Reg srcReg, Reg destReg) override;
270     /* set */
271     void Setbe(Reg reg) override;
272     void Setbe(const Mem &mem) override;
273     void Setle(Reg reg) override;
274     void Setle(const Mem &mem) override;
275     void Setae(Reg reg) override;
276     void Setae(const Mem &mem) override;
277     void Setge(Reg reg) override;
278     void Setge(const Mem &mem) override;
279     void Setne(Reg reg) override;
280     void Setne(const Mem &mem) override;
281     void Setb(Reg reg) override;
282     void Setb(const Mem &mem) override;
283     void Setl(Reg reg) override;
284     void Setl(const Mem &mem) override;
285     void Seta(Reg reg) override;
286     void Seta(const Mem &mem) override;
287     void Setg(Reg reg) override;
288     void Setg(const Mem &mem) override;
289     void Sete(Reg reg) override;
290     void Sete(const Mem &mem) override;
291     void Seto(Reg reg) override;
292     void Seto(const Mem &mem) override;
293     /* cmov */
294     void Cmova(InsnSize insnSize, Reg srcReg, Reg destReg) override;
295     void Cmova(InsnSize insnSize, const Mem &mem, Reg reg) override;
296     void Cmovae(InsnSize insnSize, Reg srcReg, Reg destReg) override;
297     void Cmovae(InsnSize insnSize, const Mem &mem, Reg reg) override;
298     void Cmovb(InsnSize insnSize, Reg srcReg, Reg destReg) override;
299     void Cmovb(InsnSize insnSize, const Mem &mem, Reg reg) override;
300     void Cmovbe(InsnSize insnSize, Reg srcReg, Reg destReg) override;
301     void Cmovbe(InsnSize insnSize, const Mem &mem, Reg reg) override;
302     void Cmove(InsnSize insnSize, Reg srcReg, Reg destReg) override;
303     void Cmove(InsnSize insnSize, const Mem &mem, Reg reg) override;
304     void Cmovg(InsnSize insnSize, Reg srcReg, Reg destReg) override;
305     void Cmovg(InsnSize insnSize, const Mem &mem, Reg reg) override;
306     void Cmovge(InsnSize insnSize, Reg srcReg, Reg destReg) override;
307     void Cmovge(InsnSize insnSize, const Mem &mem, Reg reg) override;
308     void Cmovl(InsnSize insnSize, Reg srcReg, Reg destReg) override;
309     void Cmovl(InsnSize insnSize, const Mem &mem, Reg reg) override;
310     void Cmovle(InsnSize insnSize, Reg srcReg, Reg destReg) override;
311     void Cmovle(InsnSize insnSize, const Mem &mem, Reg reg) override;
312     void Cmovne(InsnSize insnSize, Reg srcReg, Reg destReg) override;
313     void Cmovne(InsnSize insnSize, const Mem &mem, Reg reg) override;
314     void Cmovo(InsnSize insnSize, Reg srcReg, Reg destReg) override;
315     /* call */
316     void Call(InsnSize insnSize, Reg reg) override;
317     void Call(InsnSize insnSize, const Mem &mem) override;
318     void Call(InsnSize insnSize, int64 symIdx) override;
319     /* ret */
320     void Ret() override;
321     /* leave */
322     void Leave() override;
323     /* imul */
324     void Imul(InsnSize insnSize, Reg srcReg, Reg destReg) override;
325     /* mul float */
326     void Mul(Reg srcReg, Reg destReg, bool isSingle) override;
327     void Mul(const Mem &mem, Reg reg, bool isSingle) override;
328     /* nop */
329     void Nop(InsnSize insnSize, const Mem &mem) override;
330     void Nop() override;
331     /* byte swap */
332     void Bswap(InsnSize insnSize, Reg reg) override;
333     void Xchg(InsnSize insnSize, Reg srcReg, Reg destReg) override;
334     /* pseudo insn */
DealWithPseudoInst(const std::string & insn)335     void DealWithPseudoInst(const std::string &insn) override {}
336     /* floating point */
337     void MovF(Reg srcReg, Reg destReg, bool isSingle) override;
338     /* floating point and */
339     void And(Reg srcReg, Reg destReg, bool isSingle) override;
340     void And(const Mem &mem, Reg reg, bool isSingle) override;
341     /* floating div */
342     void Divsd(Reg srcReg, Reg destReg) override;
343     void Divsd(const Mem &mem, Reg reg) override;
344     /* convert int2float */
345     void Cvtsi2ss(InsnSize insnSize, Reg srcReg, Reg destReg) override;
346     void Cvtsi2sd(InsnSize insnSize, Reg srcReg, Reg destReg) override;
347     /*convert float2int */
348     void Cvttsd2si(InsnSize insnSize, Reg srcReg, Reg destReg) override;
349     void Cvttss2si(InsnSize insnSize, Reg srcReg, Reg destReg) override;
350     /* convert float2float */
351     void Cvtss2sd(Reg srcReg, Reg destReg) override;
352     void Cvtsd2ss(Reg srcReg, Reg destReg) override;
353     /* unordered compare */
354     void Ucomisd(Reg srcReg, Reg destReg) override;
355     void Ucomiss(Reg srcReg, Reg destReg) override;
356     void Cmpsd(Reg srcReg, Reg destReg, uint8 imm);
357     void Cmpeqsd(Reg srcReg, Reg destReg) override;
358     /* float sqrt*/
359     void Sqrtss_r(Reg srcReg, Reg destReg) override;
360     void Sqrtsd_r(Reg srcReg, Reg destReg) override;
361     /* end of X64 instructions */
362     /* process stackmap */
363     void RecordStackmap(const std::vector<uint8> &referenceMap,
364                         const std::vector<uint8> &deoptVreg2LocationInfo) override;
365     uint32 GetCurModulePC() override;
366     void SetLastModulePC(uint32 pc) override;
367 
368 private:
369     /* insn encode function */
Encodeb(uint64 code)370     void Encodeb(uint64 code)
371     {
372         codeBuff.push_back(static_cast<uint8>(code));
373     }
374 
Encodeb(const uint8 * code,size_t codeSize)375     void Encodeb(const uint8 *code, size_t codeSize)
376     {
377         for (size_t i = 0; i < codeSize; i++) {
378             Encodeb(code[i]);
379         }
380     }
381 
Encodeb(uint64 code,size_t codeSize)382     void Encodeb(uint64 code, size_t codeSize)
383     {
384         for (size_t i = 0; i < codeSize; i++) {
385             /* Use little endian for immediate value or displacement. */
386             Encodeb(static_cast<uint8>(code >> (i * k8Bits)));
387         }
388     }
389 
Encodew(uint64 code)390     void Encodew(uint64 code)
391     {
392         Encodeb(code, k16Bits / k8Bits); /* 2bytes, 16bits */
393     }
394 
Encoded(uint64 code)395     void Encoded(uint64 code)
396     {
397         Encodeb(code, k32Bits / k8Bits); /* 4bytes, 32bits */
398     }
399 
Encodeq(uint64 code)400     void Encodeq(uint64 code)
401     {
402         Encodeb(code, k64Bits / k8Bits); /* 8bytes, 64bits */
403     }
404 
FixupEncode(size_t position,uint32 relOffset,size_t codeSize)405     void FixupEncode(size_t position, uint32 relOffset, size_t codeSize)
406     {
407         uint64 code = static_cast<uint64>(relOffset - position - codeSize);
408         for (size_t i = 0; i < codeSize; i++) {
409             codeBuff[position + i] = static_cast<uint8>(code >> (i * k8Bits));
410         }
411     }
412 
GetRegSize(Reg reg)413     uint8 GetRegSize(Reg reg) const
414     {
415         const uint8 kRegSizeBits = 8; /* The high 8 bits is register's size. */
416         return reg >> kRegSizeBits;
417     }
418 
GetRegId(Reg reg)419     uint8 GetRegId(Reg reg) const
420     {
421         return static_cast<uint8_t>(reg & 0xF);
422     }
423 
IsRegExt(Reg reg)424     bool IsRegExt(Reg reg) const
425     {
426         /* 0xF is 4 bits, the lower 4 bits represent the id of the register. */
427         uint8 regId = reg & 0xF;
428         const uint8 kStartExtId = 8;
429         return (regId & kStartExtId) == kStartExtId;
430     }
431 
GetRegCodeId(Reg reg)432     uint8 GetRegCodeId(Reg reg) const
433     {
434         /* The lower 3 bits are used to store the encoding id of the register. */
435         return reg & kGetLow3Bits;
436     }
437 
Need8BitRegPrefix(Reg reg)438     bool Need8BitRegPrefix(Reg reg) const
439     {
440         if (reg == ERR || GetRegSize(reg) != k8Bits) {
441             return false;
442         }
443         uint8 regCodeId = GetRegCodeId(reg);
444         /* From right to left, the eighth bit in reg equals 1 represents the lower 8-bit register. */
445         const int kEighthBit = 8;
446         bool isLow8BitReg = ((((reg & 0xFF) >> (kEighthBit - 1)) & 1) == 1);
447         const uint8 kMinHigh8BitRegId = 4;
448         const uint8 kMaxHigh8BitRegId = 7;
449         return isLow8BitReg && (regCodeId >= kMinHigh8BitRegId && regCodeId <= kMaxHigh8BitRegId);
450     }
451 
HasOpndSizePrefix(Reg reg)452     bool HasOpndSizePrefix(Reg reg) const
453     {
454         return GetRegSize(reg) == k16Bits ? true : false;
455     }
456 
HasOpndSizePrefix(const Mem & mem)457     bool HasOpndSizePrefix(const Mem &mem) const
458     {
459         return mem.size == k16Bits ? true : false;
460     }
461 
HasAddrSizePrefix(const Mem & mem)462     bool HasAddrSizePrefix(const Mem &mem) const
463     {
464         Reg reg = mem.base != ERR ? mem.base : (mem.index != ERR ? mem.index : ERR);
465         uint8 regSize = reg == ERR ? k64Bits : GetRegSize(reg);
466         return regSize == k32Bits ? true : false;
467     }
468 
GetRex(Reg reg)469     uint8 GetRex(Reg reg) const
470     {
471         uint8 rexW = GetRegSize(reg) == k64Bits ? 8 : 0;
472         uint8 rexB = IsRegExt(reg) ? 1 : 0;
473         uint8 rex = rexW | rexB;
474         if (rex || Need8BitRegPrefix(reg)) {
475             rex |= 0x40; /* 0x40 is rex fixed prefix. */
476         }
477         return rex;
478     }
479 
GetRex(Reg reg1,Reg reg2)480     uint8 GetRex(Reg reg1, Reg reg2) const
481     {
482         uint8 rexW = GetRegSize(reg1) == k64Bits || GetRegSize(reg2) == k64Bits ? 8 : 0;
483         uint8 rexR = IsRegExt(reg1) ? 4 : 0;
484         uint8 rexB = IsRegExt(reg2) ? 1 : 0;
485         uint8 rex = rexW | rexR | rexB;
486         if (rex || Need8BitRegPrefix(reg1) || Need8BitRegPrefix(reg2)) {
487             rex |= 0x40; /* 0x40 is rex fixed prefix. */
488         }
489         return rex;
490     }
491 
492     uint8 GetRex(const Mem &mem, Reg reg = ERR) const
493     {
494         uint8 rexW = (reg != ERR && GetRegSize(reg) == k64Bits) ? 8 : 0;
495         uint8 rexR = reg != ERR && IsRegExt(reg) ? 4 : 0;
496         uint8 rexX = mem.index != ERR && IsRegExt(mem.index) ? 2 : 0;
497         uint8 rexB = mem.base != ERR && IsRegExt(mem.base) ? 1 : 0;
498         uint8 rex = rexW | rexR | rexX | rexB;
499         if (rex || Need8BitRegPrefix(reg)) {
500             rex |= 0x40; /* 0x40 is rex fixed prefix. */
501         }
502         return rex;
503     }
504 
GetMod(Reg reg)505     uint8 GetMod(Reg reg) const
506     {
507         return 0b11;
508     } /* mod=b11, register direct addressing. */
509 
GetMod(const Mem & mem)510     uint8 GetMod(const Mem &mem) const
511     {
512         int64 symIdx = mem.disp.first;
513         int64 offset = mem.disp.second;
514         if ((symIdx == 0 && offset != 0 && Is8Bits(offset) && mem.base != RIP) ||
515             (mem.memType == kOnlyBase && (mem.base == RBP || mem.base == R13))) {
516             return 0b01; /* mod=b01, ModRM=b01 Reg r/m */
517         } else if (symIdx != 0 || (offset != 0 && Is32Bits(offset))) {
518             if (mem.base == ERR || mem.base == RIP) {
519                 return 0b00; /* mod=b00, ModRM=b00 Reg r/m */
520             } else {
521                 return 0b10; /* mod=b10, ModRM=b01 Reg r/m */
522             }
523         }
524         return 0b00; /* mod=b00, ModRM=b00 Reg r/m */
525     }
526 
GetModRM(Reg reg1,Reg reg2)527     uint8 GetModRM(Reg reg1, Reg reg2) const
528     {
529         uint8 modReg = GetRegCodeId(reg1);
530         uint8 mod = GetMod(reg1);
531         uint8 modrm = GetRegCodeId(reg2);
532         return ((mod << kLeftShift6Bits) | (modReg << kLeftShift3Bits) | (modrm & kGetLow3Bits));
533     }
534 
GetModRM(Reg reg,const Mem & mem)535     uint8 GetModRM(Reg reg, const Mem &mem) const
536     {
537         uint8 modReg = GetRegCodeId(reg);
538         uint8 mod = GetMod(mem);
539         uint8 modrm = !HasSIB(mem) ? GetRegCodeId(mem.base) : 0b100; /* r/m=b100, use SIB */
540         return ((mod << kLeftShift6Bits) | (modReg << kLeftShift3Bits) | (modrm & kGetLow3Bits));
541     }
542 
SetModRM(uint8 mod,uint8 modReg,uint8 modrm)543     void SetModRM(uint8 mod, uint8 modReg, uint8 modrm)
544     {
545         uint8 modRM = (mod << kLeftShift6Bits) | (modReg << kLeftShift3Bits) | (modrm & kGetLow3Bits);
546         Encodeb(modRM);
547     }
548 
HasSIB(const Mem & mem)549     bool HasSIB(const Mem &mem) const
550     {
551         if (mem.memType == kBaseAndDisp || mem.memType == kOnlyBase) {
552             return GetRegCodeId(mem.base) == 0b100;
553         }
554         return mem.memType != kBaseAndDisp && mem.memType != kOnlyBase && mem.memType != kNone;
555     }
556 
GetSIB(const Mem & mem)557     uint8 GetSIB(const Mem &mem) const
558     {
559         std::unordered_map<uint8, uint8> log2Map = {{1, 0}, {2, 1}, {4, 2}, {8, 3}};
560         uint8 scale = log2Map[mem.s];
561         uint8 index = mem.index != ERR ? GetRegCodeId(mem.index) : 0b100;
562         uint8 base = mem.base != ERR ? GetRegCodeId(mem.base) : 0b101;
563         return ((scale << kLeftShift6Bits) | ((index & kGetLow3Bits) << kLeftShift3Bits) | (base & kGetLow3Bits));
564     }
565 
566     void OpReg(Reg reg, uint8 opCode1, uint8 opCode2, uint8 modReg);
567     void OpMem(const Mem &mem, uint8 opCode1, uint8 opCode2, uint8 modReg);
568     void OpDisp(const Mem &mem);
569     void OpRR(Reg reg1, Reg reg2, uint8 opCode1, uint8 opCode2 = 0, bool extInsn = false);
570     void OpRM(Reg reg, const Mem &mem, uint8 opCode1, uint8 opCode2 = 0, bool extInsn = false);
571     void OpImmAndReg(const ImmOpnd &immOpnd, Reg reg, uint8 opCode, uint8 modReg);
572     void OpImmAndMem(const ImmOpnd &immOpnd, const Mem &mem, uint8 modReg);
573     void MovRegAndDisp(Reg reg, const Mem &mem, uint8 opCode);
574     void OpPushPop(Reg reg, uint8 opCode);
575     void JmpToLabel(int64 labelIdx, uint8 opCode1, uint8 opCode2 = 0, size_t offsetSize = 4);
576     void OpCmovcc(Reg srcReg, Reg dstReg, uint8 opCode1, uint8 opCode2);
577     void UpdateLabel(int64 labelIdx, LabelType type = LabelType::kLNone, uint32 relOffset = 0xFFFFFFFFU);
578     bool CanEncodeLabel(int64 labelIdx);
579     uint32 GetLabelSize(int64 labelIdx) const;
580     uint32 GetLabelRelOffset(int64 labelIdx) const;
581     void AppendFixup(int64 labelIdx, FixupKind kind, const std::pair<uint32, size_t> &offsetPair,
582                      std::vector<Fixup *> &tmpFixups, int64 disp = 0);
583     /* elf file */
584     void InitElfHeader();
585     void RegisterSection(Section &section);
586     void LayoutSections();
587     void UpdateSectionOffset(Section &section);
588     void UpdateGlobalOffset(Section &section);
589     void SetFileOffset(uint64 offset);
590     /* symIdx is the key used to get symbol's index in .symtab */
591     void AddSymToSymTab(const Symbol &symbol, int64 symIdx);
592     void AppendRela(const Label &label, const std::pair<uint32, size_t> &offsetPair, uint64 type, Sxword addend);
593     uint64 GetRelaType(FixupKind kind) const;
594     void HandleTextSectionFixup();
595     void HandleDataSectionFixup();
596     void HandleRodataSectionFixup();
597     void WriteElfFile();
598     void AppendSecSymsToSymTabSec();
599     void AppendSymsToSymTabSec();
600     void AppendGlobalSymsToSymTabSec();
601 
602 private:
603     std::vector<uint8> codeBuff;
604     std::unordered_map<int64, Label *> labelManager;
605     std::vector<std::pair<Symbol, int64>> localSymTab;
606     std::vector<std::pair<Symbol, int64>> symTab;
607     std::vector<Fixup *> fixups;
608     std::vector<Fixup *> dataFixups;
609     std::vector<Fixup *> rodataFixups;
610     std::vector<Fixup *> debugInfoFixups;
611     std::vector<Section *> sections;
612     Offset globalOffset = 0; /* global offset of the elf file */
613     FileHeader header {};
614     DataSection *textSection = nullptr;
615     DataSection *rodataSection = nullptr;
616     DataSection *dataSection = nullptr;
617     DataSection *bssSection = nullptr;
618     RelaSection *relaSection = nullptr;
619     RelaSection *relaDataSection = nullptr;
620     RelaSection *relaRodataSection = nullptr;
621     StringSection *strTabSection = nullptr;
622     SymbolSection *symbolTabSection = nullptr;
623     /* debug section */
624     DataSection *debugInfoSection = nullptr;
625     RelaSection *relaDebugInfoSection = nullptr;
626     DataSection *debugAbbrevSection = nullptr;
627     DataSection *debugStrSection = nullptr;
628     DataSection *debugARangesSection = nullptr;
629     DataSection *debugRangesSection = nullptr;
630     DataSection *debugLineSection = nullptr;
631     uint64_t lastModulePC;
632 }; /* class ElfAssembler */
633 } /* namespace assembler */
634 
635 #endif /* ELF_ASSEMBLER_H */