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 §ion, 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