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#include <cstddef> 16#include <string.h> 17#include <inttypes.h> 18#include <algorithm> 19#include <string> 20#include <string_view> 21#include <vector> 22#include <set> 23#include "dir.h" 24#include "coff.h" 25#include "elf32.h" 26#include "elf64.h" 27 28#ifdef __APPLE__ 29#include <mach-o/loader.h> 30#include <mach-o/nlist.h> 31#include <mach-o/fat.h> 32#endif 33 34struct fs_entry { 35 char fname[256]; 36 uint64_t offset; 37 uint64_t size; 38}; 39 40std::vector<fs_entry> directory; 41std::vector<uint8_t> bin; 42std::vector<std::string_view> valid_exts; 43 44void append_file(const std::string& filename, const std::string& storename) 45{ 46 std::string_view ext; 47 auto pos = filename.find_last_of("."); 48 if (pos != std::string::npos) { 49 // found it. 50 ext = std::string_view(filename).substr(pos); 51 } 52 bool valid = false; 53 for (const auto& e : valid_exts) { 54 if (ext.compare(e) == 0) { 55 valid = true; 56 break; 57 } 58 } 59 if (!valid) { 60 printf("Skipped %s\n", storename.c_str()); 61 return; 62 } 63 if (storename.size() > 255) { 64 printf("Filename too long [%s]\n", storename.c_str()); 65 exit(-1); 66 } 67 fs_entry tmp{}; 68 strcpy(tmp.fname, storename.c_str()); 69#if _WIN32 70 struct _stat64 fileStat; 71 if (-1 == _stat64(filename.c_str(), &fileStat)) { 72#else 73 struct stat fileStat; 74 if (-1 == stat(filename.c_str(), &fileStat)) { 75#endif 76 printf("File [%s] not found\n", tmp.fname); 77 exit(-1); 78 } 79 tmp.size = fileStat.st_size; 80 auto padding = (8 - (bin.size() & 7)) & 7; 81 tmp.offset = bin.size() + padding; 82 directory.push_back(tmp); 83 FILE* f = fopen(filename.c_str(), "rb"); 84 if (f == NULL) { 85 printf("Could not open %s.\n", filename.c_str()); 86 exit(-1); 87 } 88 bin.resize((size_t)(bin.size() + padding + tmp.size)); 89 fread(bin.data() + tmp.offset, 1, (size_t)tmp.size, f); 90 fclose(f); 91 printf("Stored: %s [%" PRIu64 " , %" PRIu64 "]\n", tmp.fname, tmp.offset, tmp.size); 92} 93 94void add_directory(const std::string& path, const std::string& outpath) 95{ 96 struct dirent* pDirent = nullptr; 97 DIR* pDir = opendir(path.c_str()); 98 if (pDir == NULL) { 99 printf("Cannot open directory '%s'\n", path.c_str()); 100 exit(1); 101 } 102 std::string p, op; 103 p = path; 104 if (!p.empty()) { 105 if (p.back() != '/') { 106 p += "/"; 107 } 108 } 109 op = outpath; 110 if (!op.empty()) { 111 if (op.back() != '/') { 112 op += "/"; 113 } 114 } 115 116 // sort the readdir result 117 auto alphaSort = [](dirent* x, dirent* y) { return std::string(x->d_name) < std::string(y->d_name); }; 118 auto dirSet = std::set<dirent*, decltype(alphaSort)>(alphaSort); 119 120 while ((pDirent = readdir(pDir)) != NULL) { 121 // This structure may be statically allocated 122 dirSet.insert(pDirent); 123 } 124 125 for (auto &d : dirSet) { 126 if (d->d_type == DT_DIR) { 127 if (d->d_name[0] == '.') { 128 continue; 129 } 130 add_directory(p + d->d_name, op + d->d_name); 131 continue; 132 } 133 append_file(p + d->d_name, op + d->d_name); 134 } 135 136 closedir(pDir); 137} 138/* 139 * //Pseudo code for accessing files in blob 140 * struct fs_entry 141 * { 142 * char fname[256]; 143 * uint64_t offset; 144 * uint64_t size; 145 * }; 146 * extern "C" uint64_t SizeOfDataForReadOnlyFileSystem; 147 * extern "C" struct fs_entry BinaryDataForReadOnlyFileSystem[]; 148 * void dump_files() 149 * { 150 * for (int i = 0; i < SizeOfDataForReadOnlyFileSystem; i++) 151 * { 152 * if (BinaryDataForReadOnlyFileSystem[i].fname[0] == 0) break; 153 * printf("%s\n", BinaryDataForReadOnlyFileSystem[i].fname); 154 * char* data = (char*)(BinaryDataForReadOnlyFileSystem[i].offset + 155 * (uintptr_t)BinaryDataForReadOnlyFileSystem); printf("%lld\n", BinaryDataForReadOnlyFileSystem[i].offset); 156 * } 157 * } 158 */ 159 160std::string gDataName = "BinaryDataForReadOnlyFileSystem"; 161std::string gSizeName = "SizeOfDataForReadOnlyFileSystem"; 162 163void write_obj(const std::string& fname, const std::string& secname, size_t size_of_data, const void* data, bool x64) 164{ 165 size_t size_of_section = sizeof(uint64_t) + size_of_data; 166#pragma pack(push, 1) 167 // Using headers and defines from winnt.h 168 struct ObjFile { 169 IMAGE_FILE_HEADER coffHead; 170 IMAGE_SECTION_HEADER sections[1]; 171 IMAGE_SYMBOL symtab[2]; 172 } obj{}; 173#pragma pack(pop) 174 175 // fill coff header. 176 if (!x64) 177 obj.coffHead.Machine = IMAGE_FILE_MACHINE_I386; 178 else 179 obj.coffHead.Machine = IMAGE_FILE_MACHINE_AMD64; 180 obj.coffHead.NumberOfSections = sizeof(obj.sections) / sizeof(IMAGE_SECTION_HEADER); 181 obj.coffHead.TimeDateStamp = 0; // duh. 182 obj.coffHead.PointerToSymbolTable = offsetof(decltype(obj), symtab); 183 obj.coffHead.NumberOfSymbols = sizeof(obj.symtab) / sizeof(IMAGE_SYMBOL); 184 obj.coffHead.SizeOfOptionalHeader = 0; 185 obj.coffHead.Characteristics = 0; // if x86 use IMAGE_FILE_32BIT_MACHINE ? 186 187 // create stringtable 188 char stringtable[256]{ 0 }; 189 char* dst = stringtable; 190 auto add_string = [&dst, &stringtable](std::string_view a) -> Elf32_Word { 191 const auto offset = dst - stringtable; 192 dst += a.copy(dst, 256u - offset); 193 *dst++ = '\0'; 194 return static_cast<uint32_t>(offset + 4); 195 }; 196 197 // obj.symtab[0].N.Name.Long = add_string("?BinaryDataForReadOnlyFileSystem@@3PAUfs_entry@@A");// 198 // ?BinaryDataForReadOnlyFileSystem@@3PADA"); obj.symtab[1].N.Name.Long = 199 // add_string("?SizeOfDataForReadOnlyFileSystem@@3KA"); 200 if (!x64) { 201 // in win32 the symbols have extra "_" ? 202 std::string t = "_"; 203 t += gDataName; 204 std::string t2 = "_"; 205 t2 += gSizeName; 206 obj.symtab[1].N.Name.Long = add_string(t.c_str() /*"BinaryDataForReadOnlyFileSystem"*/); 207 obj.symtab[0].N.Name.Long = add_string(t2.c_str() /*"SizeOfDataForReadOnlyFileSystem"*/); 208 } else { 209 obj.symtab[1].N.Name.Long = add_string(gDataName.c_str() /*"BinaryDataForReadOnlyFileSystem"*/); 210 obj.symtab[0].N.Name.Long = add_string(gSizeName.c_str() /*"SizeOfDataForReadOnlyFileSystem"*/); 211 } 212 uint32_t stringTableSize = (uint32_t)((dst - stringtable) + 4); 213 214 // fill the section. 215 memcpy(&obj.sections[0].Name[0], secname.c_str(), secname.size()); 216 obj.sections[0].Misc.VirtualSize = 0; 217 obj.sections[0].VirtualAddress = 0; 218 obj.sections[0].SizeOfRawData = (uint32_t)size_of_section; // sizeof the data on disk. 219 obj.sections[0].PointerToRawData = 220 ((sizeof(obj) + stringTableSize + 3) / 4) * 4; // DWORD align the data directly after the headers.. 221 obj.sections[0].PointerToLinenumbers = 0; 222 obj.sections[0].NumberOfRelocations = 0; 223 obj.sections[0].NumberOfLinenumbers = 0; 224 obj.sections[0].Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ; 225 // fill symbols 226 obj.symtab[1].Value = (uint32_t)sizeof(uint64_t); 227 obj.symtab[1].SectionNumber = 1; // first section.. (one based) 228 obj.symtab[1].Type = IMAGE_SYM_TYPE_CHAR | (IMAGE_SYM_DTYPE_ARRAY << 8); 229 obj.symtab[1].StorageClass = IMAGE_SYM_CLASS_EXTERNAL; 230 obj.symtab[1].NumberOfAuxSymbols = 0; 231 232 obj.symtab[0].Value = (uint32_t)0; 233 obj.symtab[0].SectionNumber = 1; // first section.. (one based) 234 // obj.symtab[0].Type = IMAGE_SYM_TYPE_UINT; //(just use IMAGE_SYM_TYPE_NULL like mstools?) 235 obj.symtab[0].StorageClass = IMAGE_SYM_CLASS_EXTERNAL; 236 obj.symtab[0].NumberOfAuxSymbols = 0; 237 238 FILE* d = fopen(fname.c_str(), "wb"); 239 if (d == NULL) { 240 printf("Could not open %s.\n", fname.c_str()); 241 exit(-1); 242 } 243 // write headers 244 fwrite(&obj, sizeof(obj), 1, d); 245 // write string table 246 fwrite(&stringTableSize, 1, sizeof(stringTableSize), d); 247 fwrite(stringtable, 1, stringTableSize - 4, d); 248 // write sections.. 249 size_t p = ftell(d); 250 uint32_t pad = 0; 251 size_t padcount = obj.sections[0].PointerToRawData - p; 252 fwrite(&pad, padcount, 1, d); 253 fwrite(data, size_of_section, 1, d); 254 fclose(d); 255#undef add_string 256} 257 258template<class type> 259void write_elf( 260 type o, uint8_t arch, const std::string& fname, const std::string& secname, size_t size_of_data, const void* data) 261{ 262 size_t size_of_section = size_of_data + sizeof(uint64_t); 263 char stringtable[256]; 264 o.head.e_type = ET_REL; 265 o.head.e_machine = arch; // machine id.. 266 o.head.e_version = EV_CURRENT; 267 o.head.e_ehsize = sizeof(o.head); 268 o.head.e_shentsize = sizeof(o.sections[0]); 269 o.head.e_shnum = sizeof(o.sections) / sizeof(o.sections[0]); 270 o.head.e_shoff = sizeof(o.head); 271 o.head.e_shstrndx = 1; 272 273 // initialize stringtable. 274 char* dst = stringtable; 275 *dst = 0; 276 dst++; 277 auto add_string = [&dst, &stringtable](std::string_view a) -> Elf32_Word { 278 const auto offset = dst - stringtable; 279 dst += a.copy(dst, 256u - offset); 280 *dst++ = '\0'; 281 return static_cast<Elf32_Word>(offset); 282 }; 283 284 // create symbols 285 o.symbs[2].st_name = add_string(gDataName); // ?BinaryDataForReadOnlyFileSystem@@3PADA"); 286 o.symbs[2].st_value = sizeof(uint64_t); 287 o.symbs[2].st_size = static_cast<Elf32_Word>(size_of_data); 288 o.symbs[2].st_info = o.symbs[1].st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT); 289 o.symbs[2].st_other = o.symbs[1].st_other = STV_HIDDEN; 290 o.symbs[2].st_shndx = o.symbs[1].st_shndx = 3; 291 292 o.symbs[1].st_name = add_string(gSizeName); 293 o.symbs[1].st_value = 0; 294 o.symbs[1].st_size = sizeof(uint64_t); 295 296 o.sections[2].sh_name = add_string(".symtab"); 297 o.sections[2].sh_type = SHT_SYMTAB; 298 o.sections[2].sh_offset = offsetof(decltype(o), symbs); // sizeof(o) + size_of_section + stringtable_size; 299 o.sections[2].sh_addralign = 8; 300 o.sections[2].sh_size = sizeof(o.symbs); 301 o.sections[2].sh_entsize = sizeof(o.symbs[0]); 302 o.sections[2].sh_link = 1; 303 o.sections[2].sh_info = 1; // index of first non-local symbol. 304 305 std::string tmp = ".rodata."; 306 tmp += secname; 307 const char* sec; 308 sec = tmp.c_str(); 309 /*sec = ".rodata.rofs"*/ 310 o.sections[3].sh_name = add_string(sec); 311 o.sections[3].sh_type = SHT_PROGBITS; 312 o.sections[3].sh_flags = SHF_ALLOC | SHF_MERGE; 313 o.sections[3].sh_offset = sizeof(o); 314 o.sections[3].sh_addralign = 8; 315 o.sections[3].sh_size = static_cast<Elf32_Word>(size_of_section); 316 317 o.sections[1].sh_name = add_string(".strtab"); 318 o.sections[1].sh_type = SHT_STRTAB; 319 o.sections[1].sh_offset = static_cast<Elf32_Off>(sizeof(o) + size_of_section); 320 o.sections[1].sh_addralign = 1; 321 o.sections[1].sh_size = static_cast<Elf32_Word>(dst - stringtable); 322 323 FILE* e = fopen(fname.c_str(), "wb"); 324 if (e == NULL) { 325 printf("Could not open %s.\n", fname.c_str()); 326 exit(-1); 327 } 328 fwrite(&o, sizeof(o), 1, e); 329 fwrite(data, size_of_section, 1, e); 330 fwrite(stringtable, (size_t)o.sections[1].sh_size, 1, e); 331 fclose(e); 332} 333 334void write_macho(const std::string& fname, const std::string& secname, size_t size_of_data_, const void* data) 335{ 336#ifdef __APPLE__ 337 // Write fat header for X64_64 and ARM64 object 338 struct fat_header fathdr; 339 fathdr.magic = FAT_CIGAM; 340 fathdr.nfat_arch = htonl(2); // big-endian values in fat header 341 342 struct fat_arch archs[2] = { 343 { 344 htonl(CPU_TYPE_X86_64), 345 htonl(CPU_SUBTYPE_X86_64_ALL), 346 0, 347 0, // size of data TBD 348 htonl(3) 349 }, 350 { 351 htonl(CPU_TYPE_ARM64), 352 htonl(CPU_SUBTYPE_ARM64_ALL), 353 0, // offset, 354 0, // size of data TBD 355 htonl(3) 356 }, 357 }; 358 359 size_t fpos = 0; // "file" offsets are actually relative to the architecture header 360 archs[0].offset = htonl(sizeof(fathdr) + sizeof(archs)); 361 362 size_t size_of_section = size_of_data_ + sizeof(uint64_t); 363 364 struct mach_header_64 x64_header = { 365 MH_MAGIC_64, 366 CPU_TYPE_X86_64, 367 CPU_SUBTYPE_X86_64_ALL, 368 MH_OBJECT, 369 2, // ncmds 370 sizeof(segment_command_64) + sizeof(section_64) + sizeof(symtab_command), // sizeofcmds 371 0, // flags 372 0 // reserved 373 }; 374 375 struct mach_header_64 arm64_header = { 376 MH_MAGIC_64, 377 CPU_TYPE_ARM64, 378 CPU_SUBTYPE_ARM64_ALL, 379 MH_OBJECT, 380 2, // ncmds 381 sizeof(segment_command_64) + sizeof(section_64) + sizeof(symtab_command), // sizeofcmds 382 0, // flags 383 0 // reserved 384 }; 385 386 struct segment_command_64 data_seg = { 387 LC_SEGMENT_64, 388 sizeof(data_seg) + sizeof(section_64), 389 "", // for object files name is empty 390 0, // vmaddress 391 (size_of_section + 7) & ~7, // vmsize aligned to 8 bytes 392 0, // fileoffset = TBD 393 size_of_section, // filesize = TBD 394 VM_PROT_READ, // maxprot 395 VM_PROT_READ, // initprot 396 1, // nsects 397 SG_NORELOC // flags 398 }; 399 400 struct section_64 data_sect = { 401 "__const", 402 "__DATA", 403 0, // addr 404 size_of_section, // vmsize aligned to 8 bytes 405 0, // offset = TBD 406 3, // alignment = 2^3 = 8 bytes 407 0, // reloff 408 0, // nreloc 409 S_REGULAR, // flags 410 0, // reserved1 411 0, // reserved2 412 }; 413 414 std::string dataName = "_"; 415 dataName += gDataName; 416 std::string sizeName = "_"; 417 sizeName += gSizeName; 418 419 uint32_t string_size = dataName.size() + sizeName.size() + 3; // prepending plus two terminating nulls 420 421 struct symtab_command symtab = { 422 LC_SYMTAB, 423 sizeof(symtab), 424 0, // symoff = TBD 425 2, // nsyms 426 0, // stroff = TBD 427 string_size, // strsize 428 }; 429 430 fpos += sizeof(x64_header) + sizeof(data_seg) + sizeof(data_sect) + sizeof(symtab); 431 432 data_seg.fileoff = static_cast<uint32_t>(fpos); 433 data_sect.offset = static_cast<uint32_t>(fpos); 434 fpos += size_of_section; 435 436 size_t sectionAligned = (fpos + 7) & ~7; 437 uint32_t sectionAlign = sectionAligned - fpos; 438 fpos = sectionAligned; 439 440 symtab.symoff = static_cast<uint32_t>(fpos); 441 442 struct nlist_64 syms[2] = { 443 { 444 1, // first string 445 N_EXT | N_SECT, 446 1, // segment 447 REFERENCE_FLAG_DEFINED, 448 0 449 }, 450 { 451 static_cast<uint32_t>(sizeName.size() + 2), // second string 452 N_EXT | N_SECT, 453 1, // segment 454 REFERENCE_FLAG_DEFINED, 455 8 456 } 457 }; 458 459 fpos += sizeof(syms); 460 461 symtab.stroff = static_cast<uint32_t>(fpos); 462 fpos += string_size; 463 464 archs[0].size = htonl(fpos); 465 466 size_t aligned = (fpos + 7) & ~7; 467 uint32_t align = aligned - fpos; 468 archs[1].offset = htonl(aligned + sizeof(fathdr) + sizeof(archs)); 469 archs[1].size = archs[0].size; 470 471 FILE* e = fopen(fname.c_str(), "wb"); 472 if (e == NULL) { 473 printf("Could not open %s.\n", fname.c_str()); 474 exit(-1); 475 } 476 477 fwrite(&fathdr, sizeof(fathdr), 1, e); 478 fwrite(&archs, sizeof(archs), 1, e); 479 fwrite(&x64_header, sizeof(x64_header), 1, e); 480 fwrite(&data_seg, sizeof(data_seg), 1, e); 481 fwrite(&data_sect, sizeof(data_sect), 1, e); 482 fwrite(&symtab, sizeof(symtab), 1, e); 483 fwrite(data, size_of_section, 1, e); 484 for(int i = 0; i < sectionAlign; i++) { 485 fputc(0, e); // alignment byte to begin string table 8 byte boundary 486 } 487 fwrite(&syms, sizeof(syms), 1, e); 488 fputc(0, e); // filler byte to begin string table as it starts indexing at 1 489 fwrite(sizeName.c_str(), sizeName.size() + 1, 1, e); 490 fwrite(dataName.c_str(), dataName.size() + 1, 1, e); 491 492 for(int i = 0; i < align; i++) { 493 fputc(0, e); // alignment byte to begin arm64 architecture at 8 byte boundary 494 } 495 496 fwrite(&arm64_header, sizeof(arm64_header), 1, e); 497 fwrite(&data_seg, sizeof(data_seg), 1, e); 498 fwrite(&data_sect, sizeof(data_sect), 1, e); 499 fwrite(&symtab, sizeof(symtab), 1, e); 500 fwrite(data, size_of_section, 1, e); 501 for(int i = 0; i < sectionAlign; i++) { 502 fputc(0, e); // alignment byte to begin string table 8 byte boundary 503 } 504 fwrite(&syms, sizeof(syms), 1, e); 505 fputc(0, e); // filler byte to begin string table 506 fwrite(sizeName.c_str(), sizeName.size() + 1, 1, e); 507 fwrite(dataName.c_str(), dataName.size() + 1, 1, e); 508 fclose(e); 509#endif 510} 511 512int main(int argc, char* argv[]) 513{ 514 std::string obj32Name = "rofs_32.obj"; 515 std::string obj64Name = "rofs_64.obj"; 516 std::string o32Name = "rofs_32.o"; 517 std::string o64Name = "rofs_64.o"; 518 std::string x32Name = "rofs_x86.o"; 519 std::string x64Name = "rofs_x64.o"; 520 std::string macName = "rofs_mac.o"; 521 std::string secName = "rofs"; 522 523 bool buildX86 = true, buildX64 = true, buildV7 = true, buildV8 = true; 524 bool buildWindows = true, buildAndroid = true, buildMac = true; 525 526 std::string inPath = { "" }, roPath = { "" }; 527 528 int baseArg = 0; 529 if (argc >= 2) { 530 if (argv[1][0] == '-') { 531 buildAndroid = false; 532 buildWindows = false; 533 buildMac = false; 534 buildX86 = buildX64 = buildV7 = buildV8 = false; 535 } 536 bool platset = false; 537 for (;;) { 538 if (baseArg + 1 >= argc) { 539 printf("Invalid argument!\n"); 540 return 0; 541 } 542 if (argv[baseArg + 1][0] != '-') 543 break; 544 if (strcmp(argv[baseArg + 1], "-linux") == 0) { 545 platset = true; 546 buildAndroid = true; 547 baseArg++; 548 } else if (strcmp(argv[baseArg + 1], "-android") == 0) { 549 platset = true; 550 buildAndroid = true; 551 baseArg++; 552 } else if (strcmp(argv[baseArg + 1], "-windows") == 0) { 553 platset = true; 554 buildWindows = true; 555 baseArg++; 556 } else if (strcmp(argv[baseArg + 1], "-mac") == 0) { 557 platset = true; 558 buildMac = true; 559 baseArg++; 560 } else if (strcmp(argv[baseArg + 1], "-x86") == 0) { 561 buildX86 = true; 562 baseArg++; 563 } else if (strcmp(argv[baseArg + 1], "-x86_64") == 0) { 564 buildAndroid = true; 565 buildX64 = true; 566 baseArg++; 567 } else if (strcmp(argv[baseArg + 1], "-x64") == 0) { 568 buildX64 = true; 569 buildWindows = true; 570 baseArg++; 571 } else if (strcmp(argv[baseArg + 1], "-armeabi-v7a") == 0) { 572 buildV7 = true; 573 buildAndroid = true; 574 platset = true; 575 baseArg++; 576 } else if (strcmp(argv[baseArg + 1], "-arm64-v8a") == 0) { 577 buildV8 = true; 578 buildAndroid = true; 579 platset = true; 580 baseArg++; 581 } else if (strcmp(argv[baseArg + 1], "-extensions") == 0) { 582 baseArg++; 583 if (baseArg + 1 >= argc) { 584 printf("Invalid argument!\n"); 585 return 0; 586 } 587 auto exts = std::string_view(argv[baseArg + 1]); 588 while (!exts.empty()) { 589 auto pos = exts.find(';'); 590 pos = std::min(pos, exts.size()); 591 valid_exts.push_back(exts.substr(0, pos)); 592 exts.remove_prefix(std::min(pos + 1, exts.size())); 593 } 594 baseArg++; 595 } else { 596 printf("Invalid argument!\n"); 597 return 0; 598 } 599 } 600 if (!platset) { 601 buildWindows = true; 602 buildAndroid = true; 603 buildMac = true; 604 } 605 606 if (argc < baseArg + 3) { 607 printf("invalid args"); 608 return 0; 609 } 610 611 inPath = argv[baseArg + 1]; 612 } else { 613 printf("Not enough arguments!\n"); 614 return 0; 615 } 616 if (argc >= baseArg + 3) { 617 if (argv[baseArg + 2][0] == '/') { 618 roPath = argv[baseArg + 2] + 1; 619 } else { 620 roPath = argv[baseArg + 2]; 621 } 622 } 623 if (argc >= baseArg + 5) { 624 gDataName = argv[baseArg + 3]; 625 gSizeName = argv[baseArg + 4]; 626 } 627 if (argc == baseArg + 6) { 628 secName = obj32Name = obj64Name = o32Name = o64Name = x32Name = x64Name = macName = argv[baseArg + 5]; 629 obj32Name += "_32.obj"; 630 obj64Name += "_64.obj"; 631 o32Name += "_32.o"; 632 o64Name += "_64.o"; 633 x32Name += "_x86.o"; 634 x64Name += "_x64.o"; 635 macName += "_mac.o"; 636 } 637 add_directory(inPath, roPath); 638 639 // fix offsets 640 size_t base_offset = sizeof(fs_entry) * (directory.size() + 1); 641 for (auto& d : directory) { 642 d.offset += base_offset; 643 } 644 645 // add terminator 646 directory.push_back({ { 0 }, 0, 0 }); 647 648 const size_t size_of_dir = (sizeof(fs_entry) * directory.size()); 649 const size_t size_of_data = bin.size() + size_of_dir; 650 uint8_t* data = new uint8_t[size_of_data + sizeof(uint64_t)]; 651 *(uint64_t*)(data) = size_of_data; 652 memcpy(data + sizeof(uint64_t), directory.data(), size_of_dir); 653 memcpy(data + sizeof(uint64_t) + size_of_dir, bin.data(), bin.size()); 654 655 // Build obj 656 if (buildWindows) { 657 if (buildX86) { 658 write_obj(obj32Name, secName, size_of_data, data, false); 659 } 660 if (buildX64) { 661 write_obj(obj64Name, secName, size_of_data, data, true); 662 } 663 } 664 // Create .elf (.o) 665 if (buildAndroid) { 666 struct { 667 Elf32_Ehdr head{}; 668 Elf32_Shdr sections[4]{}; 669 Elf32_Sym symbs[3]{}; 670 } o32; 671 struct { 672 Elf64_Ehdr head{}; 673 Elf64_Shdr sections[4]{}; 674 Elf64_Sym symbs[3]{}; 675 } o64; 676 if (buildV7) { 677 write_elf(o32, EM_ARM, o32Name, secName, size_of_data, data); 678 } 679 if (buildV8) { 680 write_elf(o64, EM_AARCH64, o64Name, secName, size_of_data, data); 681 } 682 if (buildX86) { 683 write_elf(o32, EM_386, x32Name, secName, size_of_data, data); 684 } 685 if (buildX64) { 686 write_elf(o64, EM_X86_64, x64Name, secName, size_of_data, data); 687 } 688 } 689 // Create mach-o (.o) 690 if (buildMac) { 691 write_macho(macName, secName, size_of_data, data); 692 } 693} 694