1 /* 2 * Copyright (c) 2024 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 ECMASCRIPT_COMPILER_AOT_FILE_ELF_CHECKER_H 17 #define ECMASCRIPT_COMPILER_AOT_FILE_ELF_CHECKER_H 18 19 #include "ecmascript/compiler/aot_file/aot_file_manager.h" 20 #include "ecmascript/compiler/binary_section.h" 21 #include <fcntl.h> 22 #include <stddef.h> 23 #include <stdint.h> 24 #include <string> 25 #include <unistd.h> 26 27 #if BYTE_ORDER == LITTLE_ENDIAN 28 #define ELF_BYTEORDER llvm::ELF::ELFDATA2LSB 29 #else 30 #define ELF_BYTEORDER llvm::ELF::ELFDATA2MSB 31 #endif 32 #if (defined __i386__ || defined __x86_64__) && !CHECK_UNDEFINED 33 #define ALLOW_UNALIGNED 1 34 #else 35 #define ALLOW_UNALIGNED 0 36 #endif 37 38 namespace panda::ecmascript { 39 class ElfChecker { 40 public: 41 enum { ELF_F_MMAPPED = 0x40, ELF_F_MALLOCED = 0x80, ELF_F_FILEDATA = 0x100 }; 42 43 /* Identification values for recognized object files. */ 44 enum ElfKind { 45 ELF_KIND_NONE, /* Unknown. */ 46 ELF_KIND_COFF, /* Stupid old COFF. */ 47 ELF_KIND_ELF, /* ELF file. */ 48 /* Keep this the last entry. */ 49 ELF_KIND_NUM 50 }; 51 52 /* Commands for `...'. */ 53 enum ElfCommand { 54 ELF_CMD_NULL, /* Nothing, terminate, or compute only. */ 55 ELF_CMD_READ, /* Read .. */ 56 ELF_CMD_RDWR, /* Read and write .. */ 57 ELF_CMD_WRITE, /* Write .. */ 58 ELF_CMD_CLR, /* Clear flag. */ 59 ELF_CMD_SET, /* Set flag. */ 60 ELF_CMD_FDDONE, /* Signal that file descriptor will not be 61 used anymore. */ 62 ELF_CMD_FDREAD, /* Read rest of data so that file descriptor 63 is not used anymore. */ 64 /* The following are extensions. */ 65 ELF_CMD_READ_MMAP, /* Read, but mmap the file if possible. */ 66 ELF_CMD_RDWR_MMAP, /* Read and write, with mmap. */ 67 ELF_CMD_WRITE_MMAP, /* Write, with mmap. */ 68 ELF_CMD_READ_MMAP_PRIVATE, /* Read, but memory is writable, results are 69 not written to the file. */ 70 ELF_CMD_EMPTY, /* Copy basic file data but not the content. */ 71 /* Keep this the last entry. */ 72 ELF_CMD_NUM 73 }; 74 75 /* Known translation types. */ 76 enum ElfType { 77 ELF_TYPE_BYTE, /* unsigned char */ 78 ELF_TYPE_ADDR, /* Elf32_Addr, Elf64_Addr, ... */ 79 ELF_TYPE_DYN, /* Dynamic section record. */ 80 ELF_TYPE_EHDR, /* ELF header. */ 81 ELF_TYPE_HALF, /* Elf32_Half, Elf64_Half, ... */ 82 ELF_TYPE_OFF, /* Elf32_Off, Elf64_Off, ... */ 83 ELF_TYPE_PHDR, /* Program header. */ 84 ELF_TYPE_RELA, /* Relocation entry with addend. */ 85 ELF_TYPE_REL, /* Relocation entry. */ 86 ELF_TYPE_SHDR, /* Section header. */ 87 ELF_TYPE_SWORD, /* Elf32_Sword, Elf64_Sword, ... */ 88 ELF_TYPE_SYM, /* Symbol record. */ 89 ELF_TYPE_WORD, /* Elf32_Word, Elf64_Word, ... */ 90 ELF_TYPE_XWORD, /* Elf32_Xword, Elf64_Xword, ... */ 91 ELF_TYPE_SXWORD, /* Elf32_Sxword, Elf64_Sxword, ... */ 92 ELF_TYPE_VDEF, /* Elf32_Verdef, Elf64_Verdef, ... */ 93 ELF_TYPE_VDAUX, /* Elf32_Verdaux, Elf64_Verdaux, ... */ 94 ELF_TYPE_VNEED, /* Elf32_Verneed, Elf64_Verneed, ... */ 95 ELF_TYPE_VNAUX, /* Elf32_Vernaux, Elf64_Vernaux, ... */ 96 ELF_TYPE_NHDR, /* Elf32_Nhdr, Elf64_Nhdr, ... */ 97 ELF_TYPE_SYMINFO, /* Elf32_Syminfo, Elf64_Syminfo, ... */ 98 ELF_TYPE_MOVE, /* Elf32_Move, Elf64_Move, ... */ 99 ELF_TYPE_LIB, /* Elf32_Lib, Elf64_Lib, ... */ 100 ELF_TYPE_GNUHASH, /* GNU-style hash section. */ 101 ELF_TYPE_AUXV, /* Elf32_auxv_t, Elf64_auxv_t, ... */ 102 ELF_TYPE_CHDR, /* Compressed, Elf32_Chdr, Elf64_Chdr, ... */ 103 ELF_TYPE_NHDR8, /* Special GNU Properties note. Same as Nhdr, 104 except padding. */ 105 /* Keep this the last entry. */ 106 ELF_TYPE_NUM 107 }; 108 109 /* Error values. */ 110 enum { 111 ELF_ERR_NOERROR = 0, 112 ELF_ERR_UNKNOWN_ERROR, 113 ELF_ERR_UNKNOWN_VERSION, 114 ELF_ERR_UNKNOWN_TYPE, 115 ELF_ERR_INVALID_HANDLE, 116 ELF_ERR_SOURCE_SIZE, 117 ELF_ERR_DEST_SIZE, 118 ELF_ERR_INVALID_ENCODING, 119 ELF_ERR_NOMEM, 120 ELF_ERR_INVALID_FILE, 121 ELF_ERR_INVALID_ELF, 122 ELF_ERR_INVALID_OP, 123 ELF_ERR_NO_VERSION, 124 ELF_ERR_INVALID_CMD, 125 ELF_ERR_RANGE, 126 ELF_ERR_ARCHIVE_FMAG, 127 ELF_ERR_INVALID_ARCHIVE, 128 ELF_ERR_NO_ARCHIVE, 129 ELF_ERR_NO_INDEX, 130 ELF_ERR_READ_ERROR, 131 ELF_ERR_WRITE_ERROR, 132 ELF_ERR_INVALID_CLASS, 133 ELF_ERR_INVALID_INDEX, 134 ELF_ERR_INVALID_OPERAND, 135 ELF_ERR_INVALID_SECTION, 136 ELF_ERR_INVALID_COMMAND, 137 ELF_ERR_WRONG_ORDER_EHDR, 138 ELF_ERR_FD_DISABLED, 139 ELF_ERR_FD_MISMATCH, 140 ELF_ERR_OFFSET_RANGE, 141 ELF_ERR_NOT_NUL_SECTION, 142 ELF_ERR_DATA_MISMATCH, 143 ELF_ERR_INVALID_SECTION_HEADER, 144 ELF_ERR_INVALID_DATA, 145 ELF_ERR_DATA_ENCODING, 146 ELF_ERR_SECTION_TOO_SMALL, 147 ELF_ERR_INVALID_ALIGN, 148 ELF_ERR_INVALID_SHENTSIZE, 149 ELF_ERR_UPDATE_RO, 150 ELF_ERR_NOFILE, 151 ELF_ERR_GROUP_NOT_REL, 152 ELF_ERR_INVALID_PHDR, 153 ELF_ERR_NO_PHDR, 154 ELF_ERR_INVALID_OFFSET, 155 ELF_ERR_INVALID_SECTION_TYPE, 156 ELF_ERR_INVALID_SECTION_FLAGS, 157 ELF_ERR_NOT_COMPRESSED, 158 ELF_ERR_ALREADY_COMPRESSED, 159 ELF_ERR_UNKNOWN_COMPRESSION_TYPE, 160 ELF_ERR_COMPRESS_ERROR, 161 ELF_ERR_DECOMPRESS_ERROR, 162 /* Keep this as the last entry. */ 163 ELF_ERR_NUM 164 }; 165 166 /* Descriptor for data to be converted to or from memory format. */ 167 struct ElfData { 168 void* dataBuffer; /* Pointer to the actual data. */ 169 ElfType dataType; /* Type of this piece of data. */ 170 unsigned int dataVersion; /* ELF version. */ 171 size_t dataSize; /* Size in bytes. */ 172 int64_t sectionOffset; /* Offset into section. */ 173 size_t sectionAlignment; /* Alignment in section. */ 174 }; 175 176 struct ElfSectionBase; 177 struct ElfSectionList; 178 struct Elf; 179 180 /* The visible `ElfData' type is not sufficient for some operations due 181 to a misdesigned interface. Extend it for internal purposes. */ 182 struct ElfSectionData { 183 ElfData data; 184 ElfSectionBase* sectionPtr; 185 }; 186 187 /* List of `ElfData' descriptors. This is what makes up the section 188 contents. */ 189 struct ElfDataList { 190 /* `data' *must* be the first element in the struct. */ 191 ElfSectionData data; 192 struct ElfDataList* next; 193 int flags; 194 }; 195 196 /* Descriptor for ELF section. */ 197 struct ElfSectionBase { 198 /* Describe for elf sections */ 199 ElfDataList dataList; /* List of data buffers. */ 200 ElfDataList* dataListRear; /* Pointer to the rear of the data list. */ 201 202 ElfSectionData rawData; /* Uninterpreted data of the section. */ 203 204 int dataRead; /* Nonzero if the section was created by the 205 user or if the data from the file/memory 206 is read. */ 207 int extendSectionHeaderIndex; /* Index of the extended section index 208 table for this symbol table (if this 209 section is a symbol table). */ 210 211 size_t index; /* Index of this section. */ 212 struct Elf* elf; /* The underlying ELF file. */ 213 214 union { 215 llvm::ELF::Elf32_Shdr* e32; /* Pointer to 32bit section header. */ 216 llvm::ELF::Elf64_Shdr* e64; /* Pointer to 64bit section header. */ 217 } shdr; 218 219 unsigned int sectionHeaderFlags; /* Section header modified? */ 220 unsigned int flags; /* Section changed in size? */ 221 222 char* rawDataBase; /* The unmodified data of the section. */ 223 char* dataBase; /* The converted data of the section. */ 224 225 char* zipDataBase; /* The uncompressed data of the section. */ 226 size_t zipDataSize; /* If zipDataBase != NULL, the size of data. */ 227 size_t zipDataAlign; /* If zipDataBase != NULL, the addralign. */ 228 229 ElfSectionList* list; /* Pointer to the section list element the 230 data is in. */ 231 }; 232 233 /* List of section. */ 234 struct ElfSectionList { 235 unsigned int cnt; /* Number of elements of 'data' used. */ 236 unsigned int max; /* Number of elements of 'data' allocated. */ 237 struct ElfSectionList* next; /* Next block of sections. */ datapanda::ecmascript::ElfChecker::ElfSectionList238 ElfSectionBase* data() 239 { 240 return reinterpret_cast<ElfSectionBase*>(reinterpret_cast<char*>(this) + sizeof(ElfSectionList)); 241 } 242 }; 243 244 /* elf_getdata_rawchunk result. */ 245 struct ElfDataChunk { 246 ElfSectionData data; 247 union { 248 ElfSectionBase dummySection; 249 struct ElfDataChunk* next; 250 }; 251 int64_t offset; /* The original raw offset in the Elf image. */ 252 }; 253 254 struct Elf { 255 /* Address to which the file was mapped. NULL if not mapped. */ 256 void* mapAddress; 257 258 /* When created for an archive member this points to the descriptor 259 for the archive. */ 260 Elf* parent; 261 Elf* next; /* Used in list of archive descriptors. */ 262 263 /* What kind of file is underneath (ELF file, archive...). */ 264 ElfKind kind; 265 266 /* Command used to create this descriptor. */ 267 ElfCommand cmd; 268 269 /* The binary class. */ 270 unsigned int binaryClass; 271 272 /* The used file descriptor. -1 if not available anymore. */ 273 int fildes; 274 275 /* Offset in the archive this file starts or zero. */ 276 int64_t startOffset; 277 278 /* Size of the file in the archive or the entire file size, or ~0 279 for an (yet) unknown size. */ 280 size_t maxSize; 281 282 /* Describes the way the memory was allocated and if the dirty bit is 283 signalled it means that the whole file has to be rewritten since 284 the layout changed. */ 285 int flags; 286 287 /* Reference counting for the descriptor. */ 288 int refCount; 289 290 union { 291 struct { 292 void* elfHeaderPtr; 293 void* secHeaderPtr; 294 void* proHeaderPtr; 295 296 ElfSectionList* sectionLast; /* Last element in the section list. 297 If NULL the data has not yet been 298 read from the file. */ 299 ElfDataChunk* rawChunks; /* List of elf_getdata_rawchunk results. */ 300 unsigned int scnincr; /* Number of sections allocate the last 301 time. */ 302 int elfHeaderFlags; /* Flags (dirty) for ELF header. */ 303 int progHeaderFlags; /* Flags (dirty|malloc) for program header. */ 304 int secHeaderMalloced; /* Nonzero if shdr array was allocated. */ 305 off_t sizeStrOffset; /* Offset of the size string in the parent 306 if this is an archive member. */ 307 } elf; 308 309 struct { 310 llvm::ELF::Elf32_Ehdr* ehdr; /* Pointer to the ELF header. This is 311 never malloced. */ 312 llvm::ELF::Elf32_Shdr* shdr; /* Used when reading from a file. */ 313 llvm::ELF::Elf32_Phdr* phdr; /* Pointer to the program header array. */ 314 ElfSectionList* sectionLast; /* Last element in the section list. 315 If NULL the data has not yet been 316 read from the file. */ 317 ElfDataChunk* rawChunks; /* List of elf_getdata_rawchunk results. */ 318 unsigned int scnincr; /* Number of sections allocate the last 319 time. */ 320 int elfHeaderFlags; /* Flags (dirty) for ELF header. */ 321 int progHeaderFlags; /* Flags (dirty|malloc) for program header. */ 322 int secHeaderMalloced; /* Nonzero if shdr array was allocated. */ 323 int64_t sizeStrOffset; /* Offset of the size string in the parent 324 if this is an archive member. */ 325 llvm::ELF::Elf32_Ehdr elfHeaderMem; /* Memory used for ELF header when 326 not mmaped. */ 327 char fillToAlign[sizeof(llvm::ELF::Elf64_Ehdr) - sizeof(llvm::ELF::Elf32_Ehdr)]; 328 329 /* The section array. */ 330 ElfSectionList sections; 331 } elf32; 332 333 struct { 334 llvm::ELF::Elf64_Ehdr* ehdr; /* Pointer to the ELF header. This is 335 never malloced. */ 336 llvm::ELF::Elf64_Shdr* shdr; /* Used when reading from a file. */ 337 llvm::ELF::Elf64_Phdr* phdr; /* Pointer to the program header array. */ 338 ElfSectionList* sectionLast; /* Last element in the section list. 339 If NULL the data has not yet been 340 read from the file. */ 341 ElfDataChunk* rawChunks; /* List of elf_getdata_rawchunk results. */ 342 unsigned int scnincr; /* Number of sections allocate the last 343 time. */ 344 int elfHeaderFlags; /* Flags (dirty) for ELF header. */ 345 int progHeaderFlags; /* Flags (dirty|malloc) for program header. */ 346 int secHeaderMalloced; /* Nonzero if shdr array was allocated. */ 347 int64_t sizeStrOffset; /* Offset of the size string in the parent 348 if this is an archive member. */ 349 llvm::ELF::Elf64_Ehdr elfHeaderMem; /* Memory used for ELF header when 350 not mmaped. */ 351 352 /* The section array. */ 353 ElfSectionList sections; 354 } elf64; 355 } state; 356 357 /* There absolutely never must be anything following the union. */ 358 }; 359 360 ElfChecker() = delete; 361 ElfChecker(const ElfChecker&) = delete; 362 explicit ElfChecker(const void* data, int len); 363 explicit ElfChecker(const std::string&); 364 explicit ElfChecker(const MemMap&); 365 ~ElfChecker(); 366 bool CheckValidElf(); 367 368 private: 369 int CheckIfError(void) const; 370 void SetErrorCode(int value); 371 372 Elf* ElfAllocate( 373 void* map_address, int64_t offset, size_t maxsize, ElfCommand cmd, Elf* parent, ElfKind kind, size_t extra); 374 375 ElfKind GetElfKind(void* buf) const; 376 377 template <typename FromElfHeader, typename FromElfSectionHeader, typename SizeType> 378 size_t GetSectionHeaderNum( 379 FromElfHeader* ehdr, size_t maxsize, unsigned char* eIdent, void* mapAddress, int64_t offset); 380 size_t GetShnum(void* map_address, unsigned char* e_ident, int64_t offset, size_t maxsize); 381 /* Create descriptor for ELF file in memory. */ 382 template <typename ElfEhdr, typename ElfShdr, typename ElfItemField> 383 Elf* GetElfItem(ElfItemField& elfItemField, void* mapAddress, unsigned char* eIdent, int64_t offset, size_t maxSize, 384 ElfCommand cmd, size_t scnCnt, Elf* elf); 385 Elf* FileReadElf( 386 void* map_address, unsigned char* e_ident, int64_t offset, size_t maxsize, ElfCommand cmd, Elf* parent); 387 Elf* ReadMmapedFile(void* map_address, int64_t offset, size_t maxsize, ElfCommand cmd, Elf* parent); 388 Elf* ElfMemory(char* image, size_t size); 389 int ElfRelease(Elf* elf) const; 390 char* elfData_; 391 size_t elfLen_; 392 int elfErrorCode_ { 0 }; 393 const bool fromMmap_ { false }; 394 }; 395 } // namespace panda::ecmascript 396 #endif // ECMASCRIPT_COMPILER_AOT_FILE_ELF_CHECKER_H 397