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_IFILE_H 17 #define MAPLEBE_INCLUDE_CG_IFILE_H 18 19 #include <fstream> 20 #include "elf_types.h" 21 #include "types_def.h" 22 #include "common_utils.h" 23 #include "mempool.h" 24 #include "mempool_allocator.h" 25 #include "maple_string.h" 26 #include "mir_symbol.h" 27 #include "cg.h" 28 29 namespace maplebe { 30 class ObjEmitter; 31 class Fixup; 32 33 class Alignment { 34 public: 35 template <typename T> Align(T offset,T align)36 static T Align(T offset, T align) 37 { 38 if (align <= 1) { 39 return offset; 40 } 41 return (offset + align - 1) & (~(align - 1)); 42 } 43 }; /* class Alignment */ 44 45 struct ObjLabel { 46 Offset offset; 47 size_t size; 48 }; 49 50 enum LabelFixupKind : uint8 { 51 kLabelFixupDirect, 52 kLabelFixupInDirect, 53 kLabelFixupInDirectAdd, 54 kLabelFixupSize, 55 kLabelFixupDirect64, 56 kLabelFixupInDirect64, 57 kLabelFixupInDirectAdd64, 58 kLabelFixupSize64, 59 kLabelFixupGctib, 60 }; 61 62 enum IFileClassStatus : uint32 { kIFileClassResolved, kIFileClassUnresolved, kIFileClassUnknown }; 63 64 class LabelFixup { 65 public: LabelFixup(const std::string & label,uint32 offset,LabelFixupKind kind)66 LabelFixup(const std::string &label, uint32 offset, LabelFixupKind kind) : label(label), offset(offset), kind(kind) 67 { 68 } 69 ~LabelFixup() = default; 70 GetLabel()71 const std::string GetLabel() const 72 { 73 return label; 74 } 75 GetOffset()76 uint32 GetOffset() const 77 { 78 return offset; 79 } 80 GetFixupKind()81 LabelFixupKind GetFixupKind() const 82 { 83 return kind; 84 } 85 86 private: 87 std::string label; 88 uint32 offset; 89 LabelFixupKind kind; 90 }; 91 92 using Label2OffsetMap = std::unordered_map<std::string, ObjLabel>; 93 using LabelFixupVec = MapleVector<LabelFixup *>; 94 95 struct SectionDesc { 96 uint32 sectionOffset = 0; 97 uint32 sectionSize = 0; 98 }; 99 100 class Section { 101 public: 102 Section(std::string name, Word type, Word flags, uint32 align, ObjEmitter &emitter, MemPool &memPool); 103 104 virtual ~Section() = default; 105 virtual void GenerateData() = 0; 106 virtual void WriteSection(std::ofstream &outStream) = 0; ClearData()107 virtual void ClearData() 108 { 109 return; 110 } 111 HandleGlobalFixup(const Label2OffsetMap & globalLabel2Offset)112 virtual void HandleGlobalFixup(const Label2OffsetMap &globalLabel2Offset) 113 { 114 (void)globalLabel2Offset; 115 return; 116 } 117 HandleLocalFixup()118 virtual void HandleLocalFixup() {} 119 120 virtual void Layout(); 121 SetIndex(uint32 idx)122 void SetIndex(uint32 idx) 123 { 124 index = idx; 125 } 126 SetInfo(uint32 value)127 void SetInfo(uint32 value) 128 { 129 secHeader.sh_info = value; 130 } 131 SetLink(const Section & section)132 void SetLink(const Section §ion) 133 { 134 secHeader.sh_link = section.GetIndex(); 135 } 136 SetEntSize(uint32 value)137 void SetEntSize(uint32 value) 138 { 139 secHeader.sh_entsize = value; 140 } 141 SetDataSize(Word size)142 void SetDataSize(Word size) 143 { 144 secHeader.sh_size = size; 145 } 146 GetDataSize()147 virtual uint32 GetDataSize() 148 { 149 return secHeader.sh_size; 150 } 151 SetAddr(Address addr)152 void SetAddr(Address addr) 153 { 154 secHeader.sh_addr = addr; 155 } 156 GetAddr()157 Address GetAddr() const 158 { 159 return secHeader.sh_addr; 160 } 161 GetFlags()162 Word GetFlags() const 163 { 164 return secHeader.sh_flags; 165 } 166 SetOffset(Offset value)167 void SetOffset(Offset value) 168 { 169 secHeader.sh_offset = value; 170 } 171 GetOffset()172 Offset GetOffset() const 173 { 174 return secHeader.sh_offset; 175 } 176 GetIndex()177 SectionIndex GetIndex() const 178 { 179 return index; 180 } 181 GetAlign()182 Word GetAlign() const 183 { 184 return secHeader.sh_addralign; 185 } 186 GetName()187 const MapleString &GetName() const 188 { 189 return name; 190 } 191 SetSectionHeaderNameIndex(size_t index)192 void SetSectionHeaderNameIndex(size_t index) 193 { 194 secHeader.sh_name = index; 195 } 196 GetType()197 Word GetType() const 198 { 199 return secHeader.sh_type; 200 } 201 GetSectionHeader()202 const SectionHeader &GetSectionHeader() const 203 { 204 return secHeader; 205 } 206 207 protected: 208 ObjEmitter &emitter; 209 210 private: 211 MapleString name; 212 SectionIndex index {}; 213 SectionHeader secHeader {}; 214 }; 215 216 class DataSection : public Section { 217 public: DataSection(const std::string & name,Word type,Word flags,Word align,ObjEmitter & emitter,MemPool & inputMemPool)218 DataSection(const std::string &name, Word type, Word flags, Word align, ObjEmitter &emitter, MemPool &inputMemPool) 219 : Section(name, type, flags, align, emitter, inputMemPool), 220 memPool(inputMemPool), 221 alloc(&memPool), 222 data(alloc.Adapter()) 223 { 224 } 225 226 ~DataSection() = default; 227 GenerateData()228 virtual void GenerateData() override 229 { 230 SetDataSize(data.size()); 231 if (GetName() == ".ifile.hex") { 232 SetDataSize(k8BitSize); 233 } 234 } 235 ClearData()236 virtual void ClearData() override 237 { 238 data.clear(); 239 } 240 HandleGlobalFixup(const Label2OffsetMap & globalLabel2Offset)241 virtual void HandleGlobalFixup(const Label2OffsetMap &globalLabel2Offset) override 242 { 243 (void)globalLabel2Offset; 244 return; 245 } 246 WriteSection(std::ofstream & outStream)247 virtual void WriteSection(std::ofstream &outStream) override 248 { 249 outStream.write(reinterpret_cast<const char *>(data.data()), data.size()); 250 } 251 AppendData(const void * value,size_t size)252 void AppendData(const void *value, size_t size) 253 { 254 auto pdata = reinterpret_cast<const uint8 *>(value); 255 data.insert(data.end(), pdata, pdata + size); 256 } 257 AppendData(MapleVector<uint8> value)258 void AppendData(MapleVector<uint8> value) 259 { 260 data.insert(data.end(), value.begin(), value.end()); 261 } 262 GetDataSize()263 uint32 GetDataSize() override 264 { 265 return data.size(); 266 } 267 FillPadding(uint32 paddingNum)268 void FillPadding(uint32 paddingNum) 269 { 270 if (paddingNum == 0) { 271 return; 272 } 273 std::vector<uint8> paddingData(paddingNum, 0); 274 auto pdata = reinterpret_cast<const uint8 *>(paddingData.data()); 275 data.insert(data.end(), pdata, pdata + paddingNum); 276 } 277 GetDataElem32(size_t index)278 uint32 GetDataElem32(size_t index) 279 { 280 uint32 value = 0; 281 errno_t res = memcpy_s(&value, sizeof(uint32), data.data() + index, sizeof(uint32)); 282 CHECK_FATAL(res == EOK, "call memcpy_s failed"); 283 return value; 284 } 285 GetDataElem64(size_t index)286 uint64 GetDataElem64(size_t index) 287 { 288 uint64 value = 0; 289 errno_t res = memcpy_s(&value, sizeof(uint64), data.data() + index, sizeof(uint64)); 290 CHECK_FATAL(res == EOK, "call memcpy_s failed"); 291 return value; 292 } 293 GetData()294 const MapleVector<uint8> &GetData() const 295 { 296 return data; 297 } 298 Swap(const void * value,size_t index,size_t size)299 void Swap(const void *value, size_t index, size_t size) 300 { 301 errno_t res = memcpy_s(data.data() + index, size, value, size); 302 CHECK_FATAL(res == EOK, "call memcpy_s failed"); 303 } 304 AddLabel2Offset(Label2OffsetMap & label2Offsets,const std::string & name,ObjLabel & objLabel)305 static void AddLabel2Offset(Label2OffsetMap &label2Offsets, const std::string &name, ObjLabel &objLabel) 306 { 307 label2Offsets.insert(std::make_pair(name, objLabel)); 308 } 309 AddLabelFixup(LabelFixupVec & labelFixups,LabelFixup & labelFixup)310 static void AddLabelFixup(LabelFixupVec &labelFixups, LabelFixup &labelFixup) 311 { 312 labelFixups.emplace_back(&labelFixup); 313 } 314 315 protected: 316 MemPool &memPool; 317 MapleAllocator alloc; 318 MapleVector<uint8> data; 319 }; 320 321 struct MethodHeader { 322 uint32 methodMetaOffset = 0; 323 uint16 localRefOffset = 0; 324 uint16 localRefNumber = 0; 325 uint32 codeInfoOffset = 0; 326 uint32 codeSize = 0; 327 }; 328 329 class StringSection : public DataSection { 330 public: StringSection(const std::string & name,Word type,Word flags,Word align,ObjEmitter & emitter,MemPool & memPool)331 StringSection(const std::string &name, Word type, Word flags, Word align, ObjEmitter &emitter, MemPool &memPool) 332 : DataSection(name, type, flags, align, emitter, memPool) 333 { 334 AddString("\0"); 335 } 336 337 ~StringSection() = default; 338 AddString(const std::string & str)339 size_t AddString(const std::string &str) 340 { 341 size_t pos = data.size(); 342 AppendData(str.c_str(), str.size() + 1); 343 return pos; 344 } 345 AddString(const MapleString & str)346 size_t AddString(const MapleString &str) 347 { 348 size_t pos = data.size(); 349 AppendData(str.c_str(), str.length() + 1); 350 return pos; 351 } 352 }; 353 354 class SymbolSection : public Section { 355 public: SymbolSection(const std::string & name,Word type,Word flags,Word align,ObjEmitter & emitter,MemPool & memPool,const Section & link)356 SymbolSection(const std::string &name, Word type, Word flags, Word align, ObjEmitter &emitter, MemPool &memPool, 357 const Section &link) 358 : Section(name, type, flags, align, emitter, memPool), alloc(&memPool), symbols(alloc.Adapter()) 359 { 360 SetEntSize(sizeof(Symbol)); 361 SetLink(link); 362 SetInfo(1); 363 AppendSymbol({0, 0, 0, 0, 0, 0}); 364 } 365 366 ~SymbolSection() = default; 367 GenerateData()368 void GenerateData() override 369 { 370 SetDataSize(symbols.size() * sizeof(Symbol)); 371 } 372 WriteSection(std::ofstream & outStream)373 void WriteSection(std::ofstream &outStream) override 374 { 375 outStream.write(reinterpret_cast<const char *>(symbols.data()), symbols.size() * sizeof(Symbol)); 376 } 377 AppendSymbol(Symbol symbol)378 void AppendSymbol(Symbol symbol) 379 { 380 symbols.push_back(symbol); 381 } 382 GetSymbolsSize()383 uint32 GetSymbolsSize() const 384 { 385 return symbols.size(); 386 } 387 GetIdxInSymbols(int64 symIdx)388 uint64 GetIdxInSymbols(int64 symIdx) const 389 { 390 return symbolIdxMap.at(symIdx); 391 } 392 AppendIdxInSymbols(int64 symIdx)393 void AppendIdxInSymbols(int64 symIdx) 394 { 395 symbolIdxMap[symIdx] = static_cast<uint64>(GetSymbolsSize() - 1); 396 } 397 ExistSymInSymbols(int64 symIdx)398 bool ExistSymInSymbols(int64 symIdx) 399 { 400 return symbolIdxMap.count(symIdx) != 0; 401 } 402 403 private: 404 MapleAllocator alloc; 405 MapleVector<Symbol> symbols; 406 std::unordered_map<int64, uint64> symbolIdxMap; 407 }; 408 409 class RelaSection : public Section { 410 public: RelaSection(const std::string & name,Word type,Word flags,Word info,Word align,const Section & link,ObjEmitter & emitter,MemPool & memPool)411 RelaSection(const std::string &name, Word type, Word flags, Word info, Word align, const Section &link, 412 ObjEmitter &emitter, MemPool &memPool) 413 : Section(name, type, flags, align, emitter, memPool), alloc(&memPool), relas(alloc.Adapter()) 414 { 415 SetEntSize(sizeof(Rela)); 416 SetInfo(info); 417 SetLink(link); 418 } 419 420 ~RelaSection() = default; 421 GenerateData()422 void GenerateData() override 423 { 424 SetDataSize(relas.size() * sizeof(Rela)); 425 } 426 WriteSection(std::ofstream & outStream)427 void WriteSection(std::ofstream &outStream) override 428 { 429 outStream.write(reinterpret_cast<const char *>(relas.data()), relas.size() * sizeof(Rela)); 430 } 431 AppendRela(Rela rela)432 void AppendRela(Rela rela) 433 { 434 relas.push_back(rela); 435 } 436 437 private: 438 MapleAllocator alloc; 439 MapleVector<Rela> relas; 440 }; /* class RelaSection */ 441 442 struct EmitInfo { 443 MIRConst &elemConst; 444 Offset &offset; 445 Label2OffsetMap &label2Offsets; 446 LabelFixupVec &labelFixups; 447 }; 448 } /* namespace maplebe */ 449 450 #endif /* MAPLEBE_INCLUDE_CG_IFILE_H */ 451