• 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 MAPLEBE_INCLUDE_CG_OBJ_EMIT_H
17 #define MAPLEBE_INCLUDE_CG_OBJ_EMIT_H
18 
19 #include "emit.h"
20 #include "ifile.h"
21 #include "string_utils.h"
22 #ifdef JIT_ENABLE_CODE_SIGN
23 #include "jit_buffer_integrity.h"
24 #include "jit_signcode.h"
25 #endif
26 
27 namespace maplebe {
28 #ifdef JIT_ENABLE_CODE_SIGN
29 using namespace OHOS::Security::CodeSign;
30 using namespace panda::ecmascript::kungfu;
31 #endif
32 enum FixupKind : uint32 {
33     kFKNone,
34     kExceptFixup,
35     kEhTypeDefFixup,
36     kEhTypeUndefFixup,
37     kLSDAFixup,
38     kFirstTargetFixupKind = 64, /* the kind in subclass start from 64 */
39 };
40 
41 class Fixup {
42 public:
Fixup(const std::string & label,uint32 relOffsetVal,uint32 offsetVal,FixupKind fixupKind)43     Fixup(const std::string &label, uint32 relOffsetVal, uint32 offsetVal, FixupKind fixupKind)
44         : labelName(label), relOffset(relOffsetVal), offset(offsetVal), kind(fixupKind)
45     {
46     }
47 
48     ~Fixup() = default;
49 
GetLabel()50     const std::string &GetLabel() const
51     {
52         return labelName;
53     }
54 
GetRelOffset()55     uint32 GetRelOffset() const
56     {
57         return relOffset;
58     }
59 
SetOffset(uint32 value)60     void SetOffset(uint32 value)
61     {
62         offset = value;
63     }
64 
GetOffset()65     uint32 GetOffset() const
66     {
67         return offset;
68     }
69 
GetFixupKind()70     FixupKind GetFixupKind() const
71     {
72         return kind;
73     }
74 
75 private:
76     std::string labelName; /* target label name */
77     uint32 relOffset;      /* offset to target label */
78     uint32 offset;         /* record where to fix up */
79     FixupKind kind;        /* record how to fix up */
80 };
81 
82 class LocalFixup {
83 public:
LocalFixup(uint32 label,uint32 offsetVal,FixupKind fixupkind)84     LocalFixup(uint32 label, uint32 offsetVal, FixupKind fixupkind)
85         : labelIndex(label), offset(offsetVal), kind(fixupkind)
86     {
87     }
88 
89     ~LocalFixup() = default;
90 
GetLabelIndex()91     uint32 GetLabelIndex() const
92     {
93         return labelIndex;
94     }
95 
GetOffset()96     uint32 GetOffset() const
97     {
98         return offset;
99     }
100 
GetFixupKind()101     FixupKind GetFixupKind() const
102     {
103         return kind;
104     }
105 
106 private:
107     uint32 labelIndex; /* target label index */
108     uint32 offset;     /* record where to fix up */
109     FixupKind kind;    /* record how to fix up */
110 };
111 
112 enum SymbolKind : uint32 {
113     kStFunc,
114     kStNone,
115 };
116 
117 class ObjSymbol {
118 public:
ObjSymbol(const std::string & name,SymbolKind kind,uint32 pos)119     ObjSymbol(const std::string &name, SymbolKind kind, uint32 pos) : symbolName(name), symbolKind(kind), offset(pos) {}
120     ~ObjSymbol() = default;
121 
GetSymbolName()122     std::string GetSymbolName() const
123     {
124         return symbolName;
125     }
126 
GetSymbolKind()127     SymbolKind GetSymbolKind() const
128     {
129         return symbolKind;
130     }
131 
GetOffset()132     uint32 GetOffset() const
133     {
134         return offset;
135     }
136 
137 private:
138     std::string symbolName;
139     SymbolKind symbolKind;
140     uint32 offset;
141 };
142 
143 class ObjFuncEmitInfo : public FuncEmitInfo {
144 public:
ObjFuncEmitInfo(CGFunc & func,MemPool & inputMemPool)145     ObjFuncEmitInfo(CGFunc &func, MemPool &inputMemPool)
146         : FuncEmitInfo(func),
147           memPool(inputMemPool),
148           alloc(&memPool),
149           localFixups(alloc.Adapter()),
150           globalFixups(alloc.Adapter()),
151           relocations(alloc.Adapter()),
152           textData(alloc.Adapter()),
153           label2Order(alloc.Adapter()),
154           switchTableOffset(alloc.Adapter()),
155           offset2StackMapInfo(alloc.Adapter()),
156           funcName(&memPool)
157     {
158     }
159 
160     virtual ~ObjFuncEmitInfo() = default;
161 
162     struct StackMapInfo {
163         const std::vector<uint8> referenceMap;
164         const std::vector<uint8> deoptInfo;
165     };
166 
GetEndOffset()167     uint32 GetEndOffset() const
168     {
169         return endOffset;
170     }
171 
SetEndOffset(uint32 offset)172     void SetEndOffset(uint32 offset)
173     {
174         endOffset = offset;
175     }
176 
GetStartOffset()177     uint32 GetStartOffset() const
178     {
179         return startOffset;
180     }
181 
SetStartOffset(uint32 offset)182     void SetStartOffset(uint32 offset)
183     {
184         startOffset = offset;
185     }
186 
GetExceptStartOffset()187     uint32 GetExceptStartOffset() const
188     {
189         return exceptStartOffset;
190     }
191 
SetExceptStartOffset(uint32 offset)192     void SetExceptStartOffset(uint32 offset)
193     {
194         exceptStartOffset = offset;
195     }
196 
AppendLocalFixups(LocalFixup & fixup)197     ALWAYS_INLINE void AppendLocalFixups(LocalFixup &fixup)
198     {
199         localFixups.push_back(&fixup);
200 #ifdef JIT_ENABLE_CODE_SIGN
201         if (CGOptions::UseJitCodeSign()) {
202             WillFixUp(JitSignCode::GetInstance()->GetCodeSigner());
203         }
204 #endif
205     }
206 
AppendGlobalFixups(Fixup & fixup)207     ALWAYS_INLINE void AppendGlobalFixups(Fixup &fixup)
208     {
209         globalFixups.push_back(&fixup);
210 #ifdef JIT_ENABLE_CODE_SIGN
211         if (CGOptions::UseJitCodeSign()) {
212             WillFixUp(JitSignCode::GetInstance()->GetCodeSigner());
213         }
214 #endif
215     }
216 
AppendRelocations(Fixup & fixup)217     void AppendRelocations(Fixup &fixup)
218     {
219         relocations.push_back(&fixup);
220     }
221 
GetGlobalFixups()222     const MapleVector<Fixup *> &GetGlobalFixups() const
223     {
224         return globalFixups;
225     }
226 
AppendContents(uint64 binInsn,uint32 byteSize)227     virtual void AppendContents(uint64 binInsn, uint32 byteSize)
228     {
229         (void)binInsn;
230         (void)byteSize;
231         CHECK_FATAL(false, "this function should be implemented in subclass");
232     }
233 
HandleLocalBranchFixup(const std::vector<uint32> & label2Offset,const std::vector<uint32> & symbol2Offset)234     virtual void HandleLocalBranchFixup(const std::vector<uint32> &label2Offset,
235                                         const std::vector<uint32> &symbol2Offset)
236     {
237         (void)label2Offset;
238         CHECK_FATAL(false, "this fucntion should be implemented in subclass");
239     }
240 
GetFuncName()241     const MapleString &GetFuncName() const
242     {
243         return funcName;
244     }
245 
SetFuncName(const std::string & name)246     void SetFuncName(const std::string &name)
247     {
248         funcName = name;
249     }
250 
GetTextData()251     MapleVector<uint8> GetTextData() const
252     {
253         return textData;
254     }
255 
GetTextDataSize()256     size_t GetTextDataSize() const
257     {
258         return textData.size();
259     }
260 
AppendTextData(const void * data,uint32 byteSize)261     ALWAYS_INLINE void AppendTextData(const void *data, uint32 byteSize)
262     {
263         auto pdata = reinterpret_cast<const uint8 *>(data);  // data:0xa9be7c1d pdata:1d 7c be a9
264         (void)textData.insert(textData.end(), pdata, pdata + byteSize);
265 #ifdef JIT_ENABLE_CODE_SIGN
266         if (CGOptions::UseJitCodeSign()) {
267             JitSignCode *singleton = JitSignCode::GetInstance();
268             RegisterTmpBuffer(singleton->GetCodeSigner(), textData.data());
269             AppendData(singleton->GetCodeSigner(), pdata, byteSize);
270             singleton->signTableSize_ += 1;
271         }
272 #endif
273     }
274 
AppendTextData(uint64 data,uint32 byteSize)275     ALWAYS_INLINE void AppendTextData(uint64 data, uint32 byteSize)
276     {
277         for (size_t i = 0; i < byteSize; i++) {
278             textData.push_back(static_cast<uint8>(data >> (i << k8BitShift)));
279         }
280 #ifdef JIT_ENABLE_CODE_SIGN
281         if (CGOptions::UseJitCodeSign()) {
282             JitSignCode *singleton = JitSignCode::GetInstance();
283             RegisterTmpBuffer(singleton->GetCodeSigner(), textData.data());
284             AppendData(singleton->GetCodeSigner(), &data, byteSize);
285             singleton->signTableSize_ += 1;
286         }
287 #endif
288     }
289 
GetTextDataElem32(size_t index)290     uint32 GetTextDataElem32(size_t index)
291     {
292         uint32 value = 0;
293         errno_t res = memcpy_s(&value, sizeof(uint32), textData.data() + index, sizeof(uint32));
294         CHECK_FATAL(res == EOK, "call memcpy_s failed");
295         return value;
296     }
297 
GetTextDataElem64(size_t index)298     uint64 GetTextDataElem64(size_t index)
299     {
300         uint64 value = 0;
301         errno_t res = memcpy_s(&value, sizeof(uint64), textData.data() + index, sizeof(uint64));
302         CHECK_FATAL(res == EOK, "call memcpy_s failed");
303         return value;
304     }
305 
SwapTextData(const void * value,size_t index,size_t byteSize)306     ALWAYS_INLINE void SwapTextData(const void *value, size_t index, size_t byteSize)
307     {
308         errno_t res = memcpy_s(textData.data() + index, byteSize, value, byteSize);
309         CHECK_FATAL(res == EOK, "call memcpy_s failed");
310 #ifdef JIT_ENABLE_CODE_SIGN
311         if (CGOptions::UseJitCodeSign()) {
312             JitSignCode *singleton = JitSignCode::GetInstance();
313             RegisterTmpBuffer(singleton->GetCodeSigner(), textData.data());
314             res = PatchData(singleton->GetCodeSigner(), index, textData.data() + index, byteSize);
315         }
316 #endif
317     }
318 
FillTextDataPadding(uint32 padding)319     void FillTextDataPadding(uint32 padding)
320     {
321         for (uint32 i = 0; i < padding; ++i) {
322             textData.push_back(0);
323         }
324     }
325 
FillTextDataNop(uint32 padding)326     void FillTextDataNop(uint32 padding)
327     {
328         DEBUG_ASSERT(padding % k4ByteSize == 0, "padding is not a multiple of 4!\n");
329         uint32 nopNum = padding >> k2BitSize;
330         for (uint32 i = 0; i < nopNum; i++) {
331             AppendTextData(0xd503201f, k4ByteSize);
332         }
333     }
334 
SetSwitchTableOffset(const std::string & name,uint32 offset)335     void SetSwitchTableOffset(const std::string &name, uint32 offset)
336     {
337         MapleString switchTableName(name, &memPool);
338         switchTableOffset[switchTableName] = offset;
339     }
340 
GetSwitchTableOffset()341     const MapleMap<MapleString, uint32> &GetSwitchTableOffset() const
342     {
343         return switchTableOffset;
344     }
345 
GetMethodHeader()346     const MethodHeader &GetMethodHeader() const
347     {
348         return methodHeader;
349     }
350 
UpdateMethodCodeSize()351     void UpdateMethodCodeSize()
352     {
353         methodHeader.codeSize = static_cast<uint32>(GetTextDataSize());
354     }
355 
AppendLabel2Order(uint32 label)356     void AppendLabel2Order(uint32 label)
357     {
358         (void)label2Order.insert(std::make_pair(label, order));
359         order++;
360     }
361 
GetLabelOrder(uint32 label)362     uint32 GetLabelOrder(uint32 label) const
363     {
364         auto itr = label2Order.find(label);
365         CHECK_FATAL(itr != label2Order.end(), "not found label");
366         return itr->second;
367     }
368 
RecordOffset2StackMapInfo(size_t offset,const std::vector<uint8> & referenceMap,const std::vector<uint8> deoptInfo)369     void RecordOffset2StackMapInfo(size_t offset, const std::vector<uint8> &referenceMap,
370                                    const std::vector<uint8> deoptInfo)
371     {
372         offset2StackMapInfo.insert(std::pair<size_t, StackMapInfo>(offset, {referenceMap, deoptInfo}));
373     }
374 
GetOffset2StackMapInfo()375     MapleUnorderedMap<size_t, StackMapInfo> &GetOffset2StackMapInfo()
376     {
377         return offset2StackMapInfo;
378     }
379 
380 protected:
381     MemPool &memPool;
382     MapleAllocator alloc;
383     MapleVector<LocalFixup *> localFixups;
384     MapleVector<Fixup *> globalFixups;
385     MapleVector<Fixup *> relocations;
386     MapleVector<uint8> textData;
387     MapleMap<uint32, uint32> label2Order; /* this is used to sort callsite */
388     MapleMap<MapleString, uint32> switchTableOffset;
389     MapleUnorderedMap<size_t, StackMapInfo> offset2StackMapInfo;
390     uint32 endOffset = 0;
391     uint32 startOffset = 0;
392     uint32 exceptStartOffset = 0;
393     MapleString funcName;
394     MethodHeader methodHeader;
395     uint32 order = 0;
396 };
397 
398 class ObjEmitter : public Emitter {
399 public:
ObjEmitter(CG & cg,const std::string & objFileName)400     ObjEmitter(CG &cg, const std::string &objFileName)
401         : Emitter(cg, objFileName), alloc(memPool), sections(alloc.Adapter()), contents(alloc.Adapter())
402     {
403         const auto &emitMemoryManager = maplebe::CGOptions::GetInstance().GetEmitMemoryManager();
404         if (emitMemoryManager.codeSpace == nullptr) {
405             fileStream.open(objFileName, std::ios::trunc | std::ios::binary);
406         }
407 
408         uint32 funcNum = 0;
409         for (auto func : cg.GetMIRModule()->GetFunctionList()) {
410             if (func->GetBody() != nullptr) {
411                 funcNum++;
412             }
413         }
414         contents.resize(funcNum);
415     }
416 
417     virtual ~ObjEmitter() = default;
418 
419     void EmitFuncBinaryCode(ObjFuncEmitInfo &objFuncEmitInfo);
420     void EmitInstructions(ObjFuncEmitInfo &objFuncEmitInfo, std::vector<uint32> &label2Offset);
421     void EmitLocalFloatValue(ObjFuncEmitInfo &objFuncEmitInfo);
422     void EmitFullLSDA(ObjFuncEmitInfo &objFuncEmitInfo, const std::vector<uint32> &label2Offset);
423     void EmitFastLSDA(ObjFuncEmitInfo &objFuncEmitInfo, const std::vector<uint32> &label2Offset);
424     void EmitSwitchTable(ObjFuncEmitInfo &objFuncEmitInfo, const std::vector<uint32> &symbol2Offset);
425     void WriteObjFile();
426 
HandleGlobalFixup()427     void HandleGlobalFixup()
428     {
429         for (auto *section : sections) {
430             section->HandleGlobalFixup(globalLabel2Offset);
431         }
432     }
433 
434     void Run(FuncEmitInfo &funcEmitInfo);
435     void EmitFuncBuffer(CGFunc &cgFunc);
436 
CreateFuncEmitInfo(CGFunc & cgFunc)437     FuncEmitInfo &CreateFuncEmitInfo(CGFunc &cgFunc)
438     {
439         CHECK_FATAL(false, "this function should be implemented in subclass");
440         MemPool *memPool = cgFunc.GetCG()->GetMIRModule()->GetMemPool();
441         return *memPool->New<ObjFuncEmitInfo>(cgFunc, *memPool);
442     }
443 
444     void InitELFHeader();
445     void AddSymbol(const std::string &name, Word size, const Section &section, Address value);
446     void AddFuncSymbol(const MapleString &name, Word size, Address value);
447     void ClearData();
448     void HandleExceptFixup();
449 
UpdateSectionOffsetAddr(Section * section)450     void UpdateSectionOffsetAddr(Section *section)
451     {
452         if (section->GetType() != SHT_NOBITS) {
453             section->SetOffset(globalOffset);
454         } else {
455             section->SetOffset(0);
456         }
457     }
458 
UpdateGlobalOffsetAddr(Section * section)459     void UpdateGlobalOffsetAddr(Section *section)
460     {
461         if ((section->GetFlags() & SHF_ALLOC) != 0) {
462             globalAddr += section->GetDataSize();
463         }
464         if (section->GetType() != SHT_NOBITS) {
465             globalOffset += section->GetDataSize();
466         }
467     }
468 
RegisterSection(Section * section)469     void RegisterSection(Section *section)
470     {
471         sections.push_back(section);
472         DEBUG_ASSERT(sections.size() > 0, "sections not empty");
473         section->SetIndex(sections.size() - 1);
474     }
475 
RegisterGlobalLabel(const std::string labelName,ObjLabel label)476     void RegisterGlobalLabel(const std::string labelName, ObjLabel label)
477     {
478         (void)globalLabel2Offset.insert(std::make_pair(labelName, label));
479     }
480 
AddSectionName(const std::string & name)481     size_t AddSectionName(const std::string &name)
482     {
483         return name.empty() ? 0 : shStrSection->AddString(name);
484     }
485 
Finish()486     void Finish() override
487     {
488         InitSections();
489         AppendGlobalLabel();
490         AppendSymsToSymTabSec();
491         HandleTextSectionGlobalFixup();
492         AppendTextSectionData();
493         LayoutSections();
494         WriteObjFile();
495         ClearData();
496     }
497 
CloseOutput()498     void CloseOutput() override
499     {
500         if (fileStream.is_open()) {
501             fileStream << outStream.str();
502             fileStream.close();
503         }
504     }
505 
506     virtual void EncodeInstruction(const Insn &insn, const std::vector<uint32> &label2Offset,
507                                    ObjFuncEmitInfo &objFuncEmitInfo) = 0;
508     virtual uint32 GetInsnSize(const Insn &insn) const = 0;
509     virtual void HandleTextSectionGlobalFixup() = 0;
510     virtual void AppendTextSectionData() = 0;
511     virtual void AppendGlobalLabel() = 0;
512     virtual void AppendSymsToSymTabSec() = 0;
513     virtual void InitSections() = 0;
514     virtual void LayoutSections() = 0;
515     virtual void UpdateMachineAndFlags(FileHeader &header) = 0;
516 
GetContents()517     MapleVector<ObjFuncEmitInfo *> &GetContents()
518     {
519         return contents;
520     }
521 
GetBeforeTextDataSize(ObjFuncEmitInfo & objFuncEmitInfo)522     size_t GetBeforeTextDataSize(ObjFuncEmitInfo &objFuncEmitInfo) const
523     {
524         size_t textDataSize = 0;
525         for (auto *content : contents) {
526             if (content == nullptr) {
527                 continue;
528             }
529             textDataSize += content->GetTextDataSize();
530             if (content->GetFuncName() == objFuncEmitInfo.GetFuncName()) {
531                 break;
532             }
533         }
534         return textDataSize;
535     }
536 
537     void EmitMIRIntConst(EmitInfo &emitInfo);
538     void EmitMIRAddrofConst(EmitInfo &emitInfo);
539     void EmitMIRAddrofConstOffset(EmitInfo &emitInfo);
540     void EmitMIRAddrofConstCommon(EmitInfo &emitInfo, uint64 specialOffset);
541     void EmitFunctionSymbolTable(ObjFuncEmitInfo &objFuncEmitInfo, std::vector<uint32> &symbol2Offset);
542     void EmitStr16Const(ObjFuncEmitInfo &objFuncEmitInfo, const MIRSymbol &str16Symbol);
543     void EmitStrConst(ObjFuncEmitInfo &objFuncEmitInfo, const MIRSymbol &strSymbol);
544 
545 protected:
546     virtual void InsertNopInsn(ObjFuncEmitInfo &objFuncEmitInfo) const = 0;
547     virtual void EmitIntrinsicInsn(const Insn &insn, ObjFuncEmitInfo &objFuncEmitInfo) = 0;
548     virtual void EmitSpinIntrinsicInsn(const Insn &insn, ObjFuncEmitInfo &objFuncEmitInfo) = 0;
549 
550     MapleString fileName;
551     MapleAllocator alloc;
552     MapleVector<Section *> sections;
553     Offset globalOffset = 0; /* global offset of the ifile */
554     Address globalAddr = 0;  /* global adress of the ifile */
555     FileHeader header {};
556     StringSection *shStrSection = nullptr;
557     StringSection *strTabSection = nullptr;
558     SymbolSection *symbolTabSection = nullptr;
559     DataSection *textSection = nullptr;
560     DataSection *dataSection = nullptr;
561     DataSection *rodataSection = nullptr;
562     RelaSection *relaSection = nullptr;
563     MapleVector<ObjFuncEmitInfo *> contents; /* each item is the code info of a cgfunc */
564     Label2OffsetMap globalLabel2Offset;      /* record global info */
565 };
566 } /* namespace maplebe */
567 
568 #endif /* MAPLEBE_INCLUDE_CG_OBJ_EMIT_H */
569