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