18bf80f4bSopenharmony_ci/*
28bf80f4bSopenharmony_ci * Copyright (C) 2023 Huawei Device Co., Ltd.
38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License.
58bf80f4bSopenharmony_ci * You may obtain a copy of the License at
68bf80f4bSopenharmony_ci *
78bf80f4bSopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
88bf80f4bSopenharmony_ci *
98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software
108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and
138bf80f4bSopenharmony_ci * limitations under the License.
148bf80f4bSopenharmony_ci */
158bf80f4bSopenharmony_ci#include <cstddef>
168bf80f4bSopenharmony_ci#include <string.h>
178bf80f4bSopenharmony_ci#include <inttypes.h>
188bf80f4bSopenharmony_ci#include <algorithm>
198bf80f4bSopenharmony_ci#include <string>
208bf80f4bSopenharmony_ci#include <string_view>
218bf80f4bSopenharmony_ci#include <vector>
228bf80f4bSopenharmony_ci#include <set>
238bf80f4bSopenharmony_ci#include "dir.h"
248bf80f4bSopenharmony_ci#include "coff.h"
258bf80f4bSopenharmony_ci#include "elf32.h"
268bf80f4bSopenharmony_ci#include "elf64.h"
278bf80f4bSopenharmony_ci
288bf80f4bSopenharmony_ci#ifdef __APPLE__
298bf80f4bSopenharmony_ci#include <mach-o/loader.h>
308bf80f4bSopenharmony_ci#include <mach-o/nlist.h>
318bf80f4bSopenharmony_ci#include <mach-o/fat.h>
328bf80f4bSopenharmony_ci#endif
338bf80f4bSopenharmony_ci
348bf80f4bSopenharmony_cistruct fs_entry {
358bf80f4bSopenharmony_ci    char fname[256];
368bf80f4bSopenharmony_ci    uint64_t offset;
378bf80f4bSopenharmony_ci    uint64_t size;
388bf80f4bSopenharmony_ci};
398bf80f4bSopenharmony_ci
408bf80f4bSopenharmony_cistd::vector<fs_entry> directory;
418bf80f4bSopenharmony_cistd::vector<uint8_t> bin;
428bf80f4bSopenharmony_cistd::vector<std::string_view> valid_exts;
438bf80f4bSopenharmony_ci
448bf80f4bSopenharmony_civoid append_file(const std::string& filename, const std::string& storename)
458bf80f4bSopenharmony_ci{
468bf80f4bSopenharmony_ci    std::string_view ext;
478bf80f4bSopenharmony_ci    auto pos = filename.find_last_of(".");
488bf80f4bSopenharmony_ci    if (pos != std::string::npos) {
498bf80f4bSopenharmony_ci        // found it.
508bf80f4bSopenharmony_ci        ext = std::string_view(filename).substr(pos);
518bf80f4bSopenharmony_ci    }
528bf80f4bSopenharmony_ci    bool valid = false;
538bf80f4bSopenharmony_ci    for (const auto& e : valid_exts) {
548bf80f4bSopenharmony_ci        if (ext.compare(e) == 0) {
558bf80f4bSopenharmony_ci            valid = true;
568bf80f4bSopenharmony_ci            break;
578bf80f4bSopenharmony_ci        }
588bf80f4bSopenharmony_ci    }
598bf80f4bSopenharmony_ci    if (!valid) {
608bf80f4bSopenharmony_ci        printf("Skipped %s\n", storename.c_str());
618bf80f4bSopenharmony_ci        return;
628bf80f4bSopenharmony_ci    }
638bf80f4bSopenharmony_ci    if (storename.size() > 255) {
648bf80f4bSopenharmony_ci        printf("Filename too long [%s]\n", storename.c_str());
658bf80f4bSopenharmony_ci        exit(-1);
668bf80f4bSopenharmony_ci    }
678bf80f4bSopenharmony_ci    fs_entry tmp{};
688bf80f4bSopenharmony_ci    strcpy(tmp.fname, storename.c_str());
698bf80f4bSopenharmony_ci#if _WIN32
708bf80f4bSopenharmony_ci    struct _stat64 fileStat;
718bf80f4bSopenharmony_ci    if (-1 == _stat64(filename.c_str(), &fileStat)) {
728bf80f4bSopenharmony_ci#else
738bf80f4bSopenharmony_ci    struct stat fileStat;
748bf80f4bSopenharmony_ci    if (-1 == stat(filename.c_str(), &fileStat)) {
758bf80f4bSopenharmony_ci#endif
768bf80f4bSopenharmony_ci        printf("File [%s] not found\n", tmp.fname);
778bf80f4bSopenharmony_ci        exit(-1);
788bf80f4bSopenharmony_ci    }
798bf80f4bSopenharmony_ci    tmp.size = fileStat.st_size;
808bf80f4bSopenharmony_ci    auto padding = (8 - (bin.size() & 7)) & 7;
818bf80f4bSopenharmony_ci    tmp.offset = bin.size() + padding;
828bf80f4bSopenharmony_ci    directory.push_back(tmp);
838bf80f4bSopenharmony_ci    FILE* f = fopen(filename.c_str(), "rb");
848bf80f4bSopenharmony_ci    if (f == NULL) {
858bf80f4bSopenharmony_ci        printf("Could not open %s.\n", filename.c_str());
868bf80f4bSopenharmony_ci        exit(-1);
878bf80f4bSopenharmony_ci    }
888bf80f4bSopenharmony_ci    bin.resize((size_t)(bin.size() + padding + tmp.size));
898bf80f4bSopenharmony_ci    fread(bin.data() + tmp.offset, 1, (size_t)tmp.size, f);
908bf80f4bSopenharmony_ci    fclose(f);
918bf80f4bSopenharmony_ci    printf("Stored: %s [%" PRIu64 " , %" PRIu64 "]\n", tmp.fname, tmp.offset, tmp.size);
928bf80f4bSopenharmony_ci}
938bf80f4bSopenharmony_ci
948bf80f4bSopenharmony_civoid add_directory(const std::string& path, const std::string& outpath)
958bf80f4bSopenharmony_ci{
968bf80f4bSopenharmony_ci    struct dirent* pDirent = nullptr;
978bf80f4bSopenharmony_ci    DIR* pDir = opendir(path.c_str());
988bf80f4bSopenharmony_ci    if (pDir == NULL) {
998bf80f4bSopenharmony_ci        printf("Cannot open directory '%s'\n", path.c_str());
1008bf80f4bSopenharmony_ci        exit(1);
1018bf80f4bSopenharmony_ci    }
1028bf80f4bSopenharmony_ci    std::string p, op;
1038bf80f4bSopenharmony_ci    p = path;
1048bf80f4bSopenharmony_ci    if (!p.empty()) {
1058bf80f4bSopenharmony_ci        if (p.back() != '/') {
1068bf80f4bSopenharmony_ci            p += "/";
1078bf80f4bSopenharmony_ci        }
1088bf80f4bSopenharmony_ci    }
1098bf80f4bSopenharmony_ci    op = outpath;
1108bf80f4bSopenharmony_ci    if (!op.empty()) {
1118bf80f4bSopenharmony_ci        if (op.back() != '/') {
1128bf80f4bSopenharmony_ci            op += "/";
1138bf80f4bSopenharmony_ci        }
1148bf80f4bSopenharmony_ci    }
1158bf80f4bSopenharmony_ci
1168bf80f4bSopenharmony_ci    // sort the readdir result
1178bf80f4bSopenharmony_ci    auto alphaSort = [](dirent* x, dirent* y) { return std::string(x->d_name) < std::string(y->d_name); };
1188bf80f4bSopenharmony_ci    auto dirSet = std::set<dirent*, decltype(alphaSort)>(alphaSort);
1198bf80f4bSopenharmony_ci
1208bf80f4bSopenharmony_ci    while ((pDirent = readdir(pDir)) != NULL) {
1218bf80f4bSopenharmony_ci        // This structure may be statically allocated
1228bf80f4bSopenharmony_ci        dirSet.insert(pDirent);
1238bf80f4bSopenharmony_ci    }
1248bf80f4bSopenharmony_ci
1258bf80f4bSopenharmony_ci    for (auto &d : dirSet) {
1268bf80f4bSopenharmony_ci        if (d->d_type == DT_DIR) {
1278bf80f4bSopenharmony_ci            if (d->d_name[0] == '.') {
1288bf80f4bSopenharmony_ci                continue;
1298bf80f4bSopenharmony_ci            }
1308bf80f4bSopenharmony_ci            add_directory(p + d->d_name, op + d->d_name);
1318bf80f4bSopenharmony_ci            continue;
1328bf80f4bSopenharmony_ci        }
1338bf80f4bSopenharmony_ci        append_file(p + d->d_name, op + d->d_name);
1348bf80f4bSopenharmony_ci    }
1358bf80f4bSopenharmony_ci
1368bf80f4bSopenharmony_ci    closedir(pDir);
1378bf80f4bSopenharmony_ci}
1388bf80f4bSopenharmony_ci/*
1398bf80f4bSopenharmony_ci *   //Pseudo code for accessing files in blob
1408bf80f4bSopenharmony_ci *   struct fs_entry
1418bf80f4bSopenharmony_ci *   {
1428bf80f4bSopenharmony_ci *       char fname[256];
1438bf80f4bSopenharmony_ci *       uint64_t offset;
1448bf80f4bSopenharmony_ci *       uint64_t size;
1458bf80f4bSopenharmony_ci *   };
1468bf80f4bSopenharmony_ci *   extern "C" uint64_t SizeOfDataForReadOnlyFileSystem;
1478bf80f4bSopenharmony_ci *   extern "C" struct fs_entry BinaryDataForReadOnlyFileSystem[];
1488bf80f4bSopenharmony_ci *   void dump_files()
1498bf80f4bSopenharmony_ci *   {
1508bf80f4bSopenharmony_ci *       for (int i = 0; i < SizeOfDataForReadOnlyFileSystem; i++)
1518bf80f4bSopenharmony_ci *       {
1528bf80f4bSopenharmony_ci *           if (BinaryDataForReadOnlyFileSystem[i].fname[0] == 0) break;
1538bf80f4bSopenharmony_ci *           printf("%s\n", BinaryDataForReadOnlyFileSystem[i].fname);
1548bf80f4bSopenharmony_ci *           char* data = (char*)(BinaryDataForReadOnlyFileSystem[i].offset +
1558bf80f4bSopenharmony_ci * (uintptr_t)BinaryDataForReadOnlyFileSystem); printf("%lld\n", BinaryDataForReadOnlyFileSystem[i].offset);
1568bf80f4bSopenharmony_ci *       }
1578bf80f4bSopenharmony_ci *   }
1588bf80f4bSopenharmony_ci */
1598bf80f4bSopenharmony_ci
1608bf80f4bSopenharmony_cistd::string gDataName = "BinaryDataForReadOnlyFileSystem";
1618bf80f4bSopenharmony_cistd::string gSizeName = "SizeOfDataForReadOnlyFileSystem";
1628bf80f4bSopenharmony_ci
1638bf80f4bSopenharmony_civoid write_obj(const std::string& fname, const std::string& secname, size_t size_of_data, const void* data, bool x64)
1648bf80f4bSopenharmony_ci{
1658bf80f4bSopenharmony_ci    size_t size_of_section = sizeof(uint64_t) + size_of_data;
1668bf80f4bSopenharmony_ci#pragma pack(push, 1)
1678bf80f4bSopenharmony_ci    // Using headers and defines from winnt.h
1688bf80f4bSopenharmony_ci    struct ObjFile {
1698bf80f4bSopenharmony_ci        IMAGE_FILE_HEADER coffHead;
1708bf80f4bSopenharmony_ci        IMAGE_SECTION_HEADER sections[1];
1718bf80f4bSopenharmony_ci        IMAGE_SYMBOL symtab[2];
1728bf80f4bSopenharmony_ci    } obj{};
1738bf80f4bSopenharmony_ci#pragma pack(pop)
1748bf80f4bSopenharmony_ci
1758bf80f4bSopenharmony_ci    // fill coff header.
1768bf80f4bSopenharmony_ci    if (!x64)
1778bf80f4bSopenharmony_ci        obj.coffHead.Machine = IMAGE_FILE_MACHINE_I386;
1788bf80f4bSopenharmony_ci    else
1798bf80f4bSopenharmony_ci        obj.coffHead.Machine = IMAGE_FILE_MACHINE_AMD64;
1808bf80f4bSopenharmony_ci    obj.coffHead.NumberOfSections = sizeof(obj.sections) / sizeof(IMAGE_SECTION_HEADER);
1818bf80f4bSopenharmony_ci    obj.coffHead.TimeDateStamp = 0; // duh.
1828bf80f4bSopenharmony_ci    obj.coffHead.PointerToSymbolTable = offsetof(decltype(obj), symtab);
1838bf80f4bSopenharmony_ci    obj.coffHead.NumberOfSymbols = sizeof(obj.symtab) / sizeof(IMAGE_SYMBOL);
1848bf80f4bSopenharmony_ci    obj.coffHead.SizeOfOptionalHeader = 0;
1858bf80f4bSopenharmony_ci    obj.coffHead.Characteristics = 0; // if x86 use IMAGE_FILE_32BIT_MACHINE ?
1868bf80f4bSopenharmony_ci
1878bf80f4bSopenharmony_ci    // create stringtable
1888bf80f4bSopenharmony_ci    char stringtable[256]{ 0 };
1898bf80f4bSopenharmony_ci    char* dst = stringtable;
1908bf80f4bSopenharmony_ci    auto add_string = [&dst, &stringtable](std::string_view a) -> Elf32_Word {
1918bf80f4bSopenharmony_ci        const auto offset = dst - stringtable;
1928bf80f4bSopenharmony_ci        dst += a.copy(dst, 256u - offset);
1938bf80f4bSopenharmony_ci        *dst++ = '\0';
1948bf80f4bSopenharmony_ci        return static_cast<uint32_t>(offset + 4);
1958bf80f4bSopenharmony_ci    };
1968bf80f4bSopenharmony_ci
1978bf80f4bSopenharmony_ci    // obj.symtab[0].N.Name.Long = add_string("?BinaryDataForReadOnlyFileSystem@@3PAUfs_entry@@A");//
1988bf80f4bSopenharmony_ci    // ?BinaryDataForReadOnlyFileSystem@@3PADA"); obj.symtab[1].N.Name.Long =
1998bf80f4bSopenharmony_ci    // add_string("?SizeOfDataForReadOnlyFileSystem@@3KA");
2008bf80f4bSopenharmony_ci    if (!x64) {
2018bf80f4bSopenharmony_ci        // in win32 the symbols have extra "_" ?
2028bf80f4bSopenharmony_ci        std::string t = "_";
2038bf80f4bSopenharmony_ci        t += gDataName;
2048bf80f4bSopenharmony_ci        std::string t2 = "_";
2058bf80f4bSopenharmony_ci        t2 += gSizeName;
2068bf80f4bSopenharmony_ci        obj.symtab[1].N.Name.Long = add_string(t.c_str() /*"BinaryDataForReadOnlyFileSystem"*/);
2078bf80f4bSopenharmony_ci        obj.symtab[0].N.Name.Long = add_string(t2.c_str() /*"SizeOfDataForReadOnlyFileSystem"*/);
2088bf80f4bSopenharmony_ci    } else {
2098bf80f4bSopenharmony_ci        obj.symtab[1].N.Name.Long = add_string(gDataName.c_str() /*"BinaryDataForReadOnlyFileSystem"*/);
2108bf80f4bSopenharmony_ci        obj.symtab[0].N.Name.Long = add_string(gSizeName.c_str() /*"SizeOfDataForReadOnlyFileSystem"*/);
2118bf80f4bSopenharmony_ci    }
2128bf80f4bSopenharmony_ci    uint32_t stringTableSize = (uint32_t)((dst - stringtable) + 4);
2138bf80f4bSopenharmony_ci
2148bf80f4bSopenharmony_ci    // fill the section.
2158bf80f4bSopenharmony_ci    memcpy(&obj.sections[0].Name[0], secname.c_str(), secname.size());
2168bf80f4bSopenharmony_ci    obj.sections[0].Misc.VirtualSize = 0;
2178bf80f4bSopenharmony_ci    obj.sections[0].VirtualAddress = 0;
2188bf80f4bSopenharmony_ci    obj.sections[0].SizeOfRawData = (uint32_t)size_of_section; // sizeof the data on disk.
2198bf80f4bSopenharmony_ci    obj.sections[0].PointerToRawData =
2208bf80f4bSopenharmony_ci        ((sizeof(obj) + stringTableSize + 3) / 4) * 4; // DWORD align the data directly after the headers..
2218bf80f4bSopenharmony_ci    obj.sections[0].PointerToLinenumbers = 0;
2228bf80f4bSopenharmony_ci    obj.sections[0].NumberOfRelocations = 0;
2238bf80f4bSopenharmony_ci    obj.sections[0].NumberOfLinenumbers = 0;
2248bf80f4bSopenharmony_ci    obj.sections[0].Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_READ;
2258bf80f4bSopenharmony_ci    // fill symbols
2268bf80f4bSopenharmony_ci    obj.symtab[1].Value = (uint32_t)sizeof(uint64_t);
2278bf80f4bSopenharmony_ci    obj.symtab[1].SectionNumber = 1; // first section.. (one based)
2288bf80f4bSopenharmony_ci    obj.symtab[1].Type = IMAGE_SYM_TYPE_CHAR | (IMAGE_SYM_DTYPE_ARRAY << 8);
2298bf80f4bSopenharmony_ci    obj.symtab[1].StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
2308bf80f4bSopenharmony_ci    obj.symtab[1].NumberOfAuxSymbols = 0;
2318bf80f4bSopenharmony_ci
2328bf80f4bSopenharmony_ci    obj.symtab[0].Value = (uint32_t)0;
2338bf80f4bSopenharmony_ci    obj.symtab[0].SectionNumber = 1; // first section.. (one based)
2348bf80f4bSopenharmony_ci    // obj.symtab[0].Type = IMAGE_SYM_TYPE_UINT;  //(just use IMAGE_SYM_TYPE_NULL like mstools?)
2358bf80f4bSopenharmony_ci    obj.symtab[0].StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
2368bf80f4bSopenharmony_ci    obj.symtab[0].NumberOfAuxSymbols = 0;
2378bf80f4bSopenharmony_ci
2388bf80f4bSopenharmony_ci    FILE* d = fopen(fname.c_str(), "wb");
2398bf80f4bSopenharmony_ci    if (d == NULL) {
2408bf80f4bSopenharmony_ci        printf("Could not open %s.\n", fname.c_str());
2418bf80f4bSopenharmony_ci        exit(-1);
2428bf80f4bSopenharmony_ci    }
2438bf80f4bSopenharmony_ci    // write headers
2448bf80f4bSopenharmony_ci    fwrite(&obj, sizeof(obj), 1, d);
2458bf80f4bSopenharmony_ci    // write string table
2468bf80f4bSopenharmony_ci    fwrite(&stringTableSize, 1, sizeof(stringTableSize), d);
2478bf80f4bSopenharmony_ci    fwrite(stringtable, 1, stringTableSize - 4, d);
2488bf80f4bSopenharmony_ci    // write sections..
2498bf80f4bSopenharmony_ci    size_t p = ftell(d);
2508bf80f4bSopenharmony_ci    uint32_t pad = 0;
2518bf80f4bSopenharmony_ci    size_t padcount = obj.sections[0].PointerToRawData - p;
2528bf80f4bSopenharmony_ci    fwrite(&pad, padcount, 1, d);
2538bf80f4bSopenharmony_ci    fwrite(data, size_of_section, 1, d);
2548bf80f4bSopenharmony_ci    fclose(d);
2558bf80f4bSopenharmony_ci#undef add_string
2568bf80f4bSopenharmony_ci}
2578bf80f4bSopenharmony_ci
2588bf80f4bSopenharmony_citemplate<class type>
2598bf80f4bSopenharmony_civoid write_elf(
2608bf80f4bSopenharmony_ci    type o, uint8_t arch, const std::string& fname, const std::string& secname, size_t size_of_data, const void* data)
2618bf80f4bSopenharmony_ci{
2628bf80f4bSopenharmony_ci    size_t size_of_section = size_of_data + sizeof(uint64_t);
2638bf80f4bSopenharmony_ci    char stringtable[256];
2648bf80f4bSopenharmony_ci    o.head.e_type = ET_REL;
2658bf80f4bSopenharmony_ci    o.head.e_machine = arch; // machine id..
2668bf80f4bSopenharmony_ci    o.head.e_version = EV_CURRENT;
2678bf80f4bSopenharmony_ci    o.head.e_ehsize = sizeof(o.head);
2688bf80f4bSopenharmony_ci    o.head.e_shentsize = sizeof(o.sections[0]);
2698bf80f4bSopenharmony_ci    o.head.e_shnum = sizeof(o.sections) / sizeof(o.sections[0]);
2708bf80f4bSopenharmony_ci    o.head.e_shoff = sizeof(o.head);
2718bf80f4bSopenharmony_ci    o.head.e_shstrndx = 1;
2728bf80f4bSopenharmony_ci
2738bf80f4bSopenharmony_ci    // initialize stringtable.
2748bf80f4bSopenharmony_ci    char* dst = stringtable;
2758bf80f4bSopenharmony_ci    *dst = 0;
2768bf80f4bSopenharmony_ci    dst++;
2778bf80f4bSopenharmony_ci    auto add_string = [&dst, &stringtable](std::string_view a) -> Elf32_Word {
2788bf80f4bSopenharmony_ci        const auto offset = dst - stringtable;
2798bf80f4bSopenharmony_ci        dst += a.copy(dst, 256u - offset);
2808bf80f4bSopenharmony_ci        *dst++ = '\0';
2818bf80f4bSopenharmony_ci        return static_cast<Elf32_Word>(offset);
2828bf80f4bSopenharmony_ci    };
2838bf80f4bSopenharmony_ci
2848bf80f4bSopenharmony_ci    // create symbols
2858bf80f4bSopenharmony_ci    o.symbs[2].st_name = add_string(gDataName); // ?BinaryDataForReadOnlyFileSystem@@3PADA");
2868bf80f4bSopenharmony_ci    o.symbs[2].st_value = sizeof(uint64_t);
2878bf80f4bSopenharmony_ci    o.symbs[2].st_size = static_cast<Elf32_Word>(size_of_data);
2888bf80f4bSopenharmony_ci    o.symbs[2].st_info = o.symbs[1].st_info = ELF_ST_INFO(STB_GLOBAL, STT_OBJECT);
2898bf80f4bSopenharmony_ci    o.symbs[2].st_other = o.symbs[1].st_other = STV_HIDDEN;
2908bf80f4bSopenharmony_ci    o.symbs[2].st_shndx = o.symbs[1].st_shndx = 3;
2918bf80f4bSopenharmony_ci
2928bf80f4bSopenharmony_ci    o.symbs[1].st_name = add_string(gSizeName);
2938bf80f4bSopenharmony_ci    o.symbs[1].st_value = 0;
2948bf80f4bSopenharmony_ci    o.symbs[1].st_size = sizeof(uint64_t);
2958bf80f4bSopenharmony_ci
2968bf80f4bSopenharmony_ci    o.sections[2].sh_name = add_string(".symtab");
2978bf80f4bSopenharmony_ci    o.sections[2].sh_type = SHT_SYMTAB;
2988bf80f4bSopenharmony_ci    o.sections[2].sh_offset = offsetof(decltype(o), symbs); // sizeof(o) + size_of_section + stringtable_size;
2998bf80f4bSopenharmony_ci    o.sections[2].sh_addralign = 8;
3008bf80f4bSopenharmony_ci    o.sections[2].sh_size = sizeof(o.symbs);
3018bf80f4bSopenharmony_ci    o.sections[2].sh_entsize = sizeof(o.symbs[0]);
3028bf80f4bSopenharmony_ci    o.sections[2].sh_link = 1;
3038bf80f4bSopenharmony_ci    o.sections[2].sh_info = 1; // index of first non-local symbol.
3048bf80f4bSopenharmony_ci
3058bf80f4bSopenharmony_ci    std::string tmp = ".rodata.";
3068bf80f4bSopenharmony_ci    tmp += secname;
3078bf80f4bSopenharmony_ci    const char* sec;
3088bf80f4bSopenharmony_ci    sec = tmp.c_str();
3098bf80f4bSopenharmony_ci    /*sec = ".rodata.rofs"*/
3108bf80f4bSopenharmony_ci    o.sections[3].sh_name = add_string(sec);
3118bf80f4bSopenharmony_ci    o.sections[3].sh_type = SHT_PROGBITS;
3128bf80f4bSopenharmony_ci    o.sections[3].sh_flags = SHF_ALLOC | SHF_MERGE;
3138bf80f4bSopenharmony_ci    o.sections[3].sh_offset = sizeof(o);
3148bf80f4bSopenharmony_ci    o.sections[3].sh_addralign = 8;
3158bf80f4bSopenharmony_ci    o.sections[3].sh_size = static_cast<Elf32_Word>(size_of_section);
3168bf80f4bSopenharmony_ci
3178bf80f4bSopenharmony_ci    o.sections[1].sh_name = add_string(".strtab");
3188bf80f4bSopenharmony_ci    o.sections[1].sh_type = SHT_STRTAB;
3198bf80f4bSopenharmony_ci    o.sections[1].sh_offset = static_cast<Elf32_Off>(sizeof(o) + size_of_section);
3208bf80f4bSopenharmony_ci    o.sections[1].sh_addralign = 1;
3218bf80f4bSopenharmony_ci    o.sections[1].sh_size = static_cast<Elf32_Word>(dst - stringtable);
3228bf80f4bSopenharmony_ci
3238bf80f4bSopenharmony_ci    FILE* e = fopen(fname.c_str(), "wb");
3248bf80f4bSopenharmony_ci    if (e == NULL) {
3258bf80f4bSopenharmony_ci        printf("Could not open %s.\n", fname.c_str());
3268bf80f4bSopenharmony_ci        exit(-1);
3278bf80f4bSopenharmony_ci    }
3288bf80f4bSopenharmony_ci    fwrite(&o, sizeof(o), 1, e);
3298bf80f4bSopenharmony_ci    fwrite(data, size_of_section, 1, e);
3308bf80f4bSopenharmony_ci    fwrite(stringtable, (size_t)o.sections[1].sh_size, 1, e);
3318bf80f4bSopenharmony_ci    fclose(e);
3328bf80f4bSopenharmony_ci}
3338bf80f4bSopenharmony_ci
3348bf80f4bSopenharmony_civoid write_macho(const std::string& fname, const std::string& secname, size_t size_of_data_, const void* data)
3358bf80f4bSopenharmony_ci{
3368bf80f4bSopenharmony_ci#ifdef __APPLE__
3378bf80f4bSopenharmony_ci    // Write fat header for X64_64 and ARM64 object
3388bf80f4bSopenharmony_ci    struct fat_header fathdr;
3398bf80f4bSopenharmony_ci    fathdr.magic = FAT_CIGAM;
3408bf80f4bSopenharmony_ci    fathdr.nfat_arch = htonl(2); // big-endian values in fat header
3418bf80f4bSopenharmony_ci
3428bf80f4bSopenharmony_ci    struct fat_arch archs[2] = {
3438bf80f4bSopenharmony_ci        {
3448bf80f4bSopenharmony_ci            htonl(CPU_TYPE_X86_64),
3458bf80f4bSopenharmony_ci            htonl(CPU_SUBTYPE_X86_64_ALL),
3468bf80f4bSopenharmony_ci            0,
3478bf80f4bSopenharmony_ci            0, // size of data TBD
3488bf80f4bSopenharmony_ci            htonl(3)
3498bf80f4bSopenharmony_ci        },
3508bf80f4bSopenharmony_ci        {
3518bf80f4bSopenharmony_ci            htonl(CPU_TYPE_ARM64),
3528bf80f4bSopenharmony_ci            htonl(CPU_SUBTYPE_ARM64_ALL),
3538bf80f4bSopenharmony_ci            0, // offset,
3548bf80f4bSopenharmony_ci            0, // size of data TBD
3558bf80f4bSopenharmony_ci            htonl(3)
3568bf80f4bSopenharmony_ci        },
3578bf80f4bSopenharmony_ci    };
3588bf80f4bSopenharmony_ci
3598bf80f4bSopenharmony_ci    size_t fpos = 0; // "file" offsets are actually relative to the architecture header
3608bf80f4bSopenharmony_ci    archs[0].offset = htonl(sizeof(fathdr) + sizeof(archs));
3618bf80f4bSopenharmony_ci
3628bf80f4bSopenharmony_ci    size_t size_of_section = size_of_data_ + sizeof(uint64_t);
3638bf80f4bSopenharmony_ci
3648bf80f4bSopenharmony_ci    struct mach_header_64 x64_header = {
3658bf80f4bSopenharmony_ci        MH_MAGIC_64,
3668bf80f4bSopenharmony_ci        CPU_TYPE_X86_64,
3678bf80f4bSopenharmony_ci        CPU_SUBTYPE_X86_64_ALL,
3688bf80f4bSopenharmony_ci        MH_OBJECT,
3698bf80f4bSopenharmony_ci        2, // ncmds
3708bf80f4bSopenharmony_ci        sizeof(segment_command_64) + sizeof(section_64) + sizeof(symtab_command), // sizeofcmds
3718bf80f4bSopenharmony_ci        0, // flags
3728bf80f4bSopenharmony_ci        0  // reserved
3738bf80f4bSopenharmony_ci    };
3748bf80f4bSopenharmony_ci
3758bf80f4bSopenharmony_ci    struct mach_header_64 arm64_header = {
3768bf80f4bSopenharmony_ci        MH_MAGIC_64,
3778bf80f4bSopenharmony_ci        CPU_TYPE_ARM64,
3788bf80f4bSopenharmony_ci        CPU_SUBTYPE_ARM64_ALL,
3798bf80f4bSopenharmony_ci        MH_OBJECT,
3808bf80f4bSopenharmony_ci        2, // ncmds
3818bf80f4bSopenharmony_ci        sizeof(segment_command_64) + sizeof(section_64) + sizeof(symtab_command), // sizeofcmds
3828bf80f4bSopenharmony_ci        0, // flags
3838bf80f4bSopenharmony_ci        0  // reserved
3848bf80f4bSopenharmony_ci    };
3858bf80f4bSopenharmony_ci
3868bf80f4bSopenharmony_ci    struct segment_command_64 data_seg = {
3878bf80f4bSopenharmony_ci        LC_SEGMENT_64,
3888bf80f4bSopenharmony_ci        sizeof(data_seg) + sizeof(section_64),
3898bf80f4bSopenharmony_ci        "", // for object files name is empty
3908bf80f4bSopenharmony_ci        0, // vmaddress
3918bf80f4bSopenharmony_ci        (size_of_section + 7) & ~7, // vmsize aligned to 8 bytes
3928bf80f4bSopenharmony_ci        0, // fileoffset = TBD
3938bf80f4bSopenharmony_ci        size_of_section, // filesize = TBD
3948bf80f4bSopenharmony_ci        VM_PROT_READ, // maxprot
3958bf80f4bSopenharmony_ci        VM_PROT_READ, // initprot
3968bf80f4bSopenharmony_ci        1, // nsects
3978bf80f4bSopenharmony_ci        SG_NORELOC  // flags
3988bf80f4bSopenharmony_ci    };
3998bf80f4bSopenharmony_ci
4008bf80f4bSopenharmony_ci    struct section_64 data_sect = {
4018bf80f4bSopenharmony_ci        "__const",
4028bf80f4bSopenharmony_ci        "__DATA",
4038bf80f4bSopenharmony_ci        0, // addr
4048bf80f4bSopenharmony_ci        size_of_section, // vmsize aligned to 8 bytes
4058bf80f4bSopenharmony_ci        0, // offset = TBD
4068bf80f4bSopenharmony_ci        3, // alignment = 2^3 = 8 bytes
4078bf80f4bSopenharmony_ci        0, // reloff
4088bf80f4bSopenharmony_ci        0, // nreloc
4098bf80f4bSopenharmony_ci        S_REGULAR, // flags
4108bf80f4bSopenharmony_ci        0, // reserved1
4118bf80f4bSopenharmony_ci        0, // reserved2
4128bf80f4bSopenharmony_ci    };
4138bf80f4bSopenharmony_ci
4148bf80f4bSopenharmony_ci    std::string dataName = "_";
4158bf80f4bSopenharmony_ci    dataName += gDataName;
4168bf80f4bSopenharmony_ci    std::string sizeName = "_";
4178bf80f4bSopenharmony_ci    sizeName += gSizeName;
4188bf80f4bSopenharmony_ci
4198bf80f4bSopenharmony_ci    uint32_t string_size = dataName.size() + sizeName.size() + 3; // prepending plus two terminating nulls
4208bf80f4bSopenharmony_ci
4218bf80f4bSopenharmony_ci    struct symtab_command symtab = {
4228bf80f4bSopenharmony_ci        LC_SYMTAB,
4238bf80f4bSopenharmony_ci        sizeof(symtab),
4248bf80f4bSopenharmony_ci        0, // symoff = TBD
4258bf80f4bSopenharmony_ci        2, // nsyms
4268bf80f4bSopenharmony_ci        0, // stroff = TBD
4278bf80f4bSopenharmony_ci        string_size, // strsize
4288bf80f4bSopenharmony_ci    };
4298bf80f4bSopenharmony_ci
4308bf80f4bSopenharmony_ci    fpos += sizeof(x64_header) + sizeof(data_seg) + sizeof(data_sect) + sizeof(symtab);
4318bf80f4bSopenharmony_ci
4328bf80f4bSopenharmony_ci    data_seg.fileoff = static_cast<uint32_t>(fpos);
4338bf80f4bSopenharmony_ci    data_sect.offset = static_cast<uint32_t>(fpos);
4348bf80f4bSopenharmony_ci    fpos += size_of_section;
4358bf80f4bSopenharmony_ci
4368bf80f4bSopenharmony_ci    size_t sectionAligned = (fpos + 7) & ~7;
4378bf80f4bSopenharmony_ci    uint32_t sectionAlign = sectionAligned - fpos;
4388bf80f4bSopenharmony_ci    fpos = sectionAligned;
4398bf80f4bSopenharmony_ci
4408bf80f4bSopenharmony_ci    symtab.symoff = static_cast<uint32_t>(fpos);
4418bf80f4bSopenharmony_ci
4428bf80f4bSopenharmony_ci    struct nlist_64 syms[2] = {
4438bf80f4bSopenharmony_ci    {
4448bf80f4bSopenharmony_ci        1, // first string
4458bf80f4bSopenharmony_ci        N_EXT | N_SECT,
4468bf80f4bSopenharmony_ci        1, // segment
4478bf80f4bSopenharmony_ci        REFERENCE_FLAG_DEFINED,
4488bf80f4bSopenharmony_ci        0
4498bf80f4bSopenharmony_ci    },
4508bf80f4bSopenharmony_ci    {
4518bf80f4bSopenharmony_ci        static_cast<uint32_t>(sizeName.size() + 2), // second string
4528bf80f4bSopenharmony_ci        N_EXT | N_SECT,
4538bf80f4bSopenharmony_ci        1, // segment
4548bf80f4bSopenharmony_ci        REFERENCE_FLAG_DEFINED,
4558bf80f4bSopenharmony_ci        8
4568bf80f4bSopenharmony_ci    }
4578bf80f4bSopenharmony_ci    };
4588bf80f4bSopenharmony_ci
4598bf80f4bSopenharmony_ci    fpos += sizeof(syms);
4608bf80f4bSopenharmony_ci
4618bf80f4bSopenharmony_ci    symtab.stroff = static_cast<uint32_t>(fpos);
4628bf80f4bSopenharmony_ci    fpos += string_size;
4638bf80f4bSopenharmony_ci
4648bf80f4bSopenharmony_ci    archs[0].size = htonl(fpos);
4658bf80f4bSopenharmony_ci
4668bf80f4bSopenharmony_ci    size_t aligned = (fpos + 7) & ~7;
4678bf80f4bSopenharmony_ci    uint32_t align = aligned - fpos;
4688bf80f4bSopenharmony_ci    archs[1].offset = htonl(aligned + sizeof(fathdr) + sizeof(archs));
4698bf80f4bSopenharmony_ci    archs[1].size = archs[0].size;
4708bf80f4bSopenharmony_ci
4718bf80f4bSopenharmony_ci    FILE* e = fopen(fname.c_str(), "wb");
4728bf80f4bSopenharmony_ci    if (e == NULL) {
4738bf80f4bSopenharmony_ci        printf("Could not open %s.\n", fname.c_str());
4748bf80f4bSopenharmony_ci        exit(-1);
4758bf80f4bSopenharmony_ci    }
4768bf80f4bSopenharmony_ci
4778bf80f4bSopenharmony_ci    fwrite(&fathdr, sizeof(fathdr), 1, e);
4788bf80f4bSopenharmony_ci    fwrite(&archs, sizeof(archs), 1, e);
4798bf80f4bSopenharmony_ci    fwrite(&x64_header, sizeof(x64_header), 1, e);
4808bf80f4bSopenharmony_ci    fwrite(&data_seg, sizeof(data_seg), 1, e);
4818bf80f4bSopenharmony_ci    fwrite(&data_sect, sizeof(data_sect), 1, e);
4828bf80f4bSopenharmony_ci    fwrite(&symtab, sizeof(symtab), 1, e);
4838bf80f4bSopenharmony_ci    fwrite(data, size_of_section, 1, e);
4848bf80f4bSopenharmony_ci    for(int i = 0; i < sectionAlign; i++) {
4858bf80f4bSopenharmony_ci        fputc(0, e); // alignment byte to begin string table 8 byte boundary
4868bf80f4bSopenharmony_ci    }
4878bf80f4bSopenharmony_ci    fwrite(&syms, sizeof(syms), 1, e);
4888bf80f4bSopenharmony_ci    fputc(0, e); // filler byte to begin string table as it starts indexing at 1
4898bf80f4bSopenharmony_ci    fwrite(sizeName.c_str(), sizeName.size() + 1, 1, e);
4908bf80f4bSopenharmony_ci    fwrite(dataName.c_str(), dataName.size() + 1, 1, e);
4918bf80f4bSopenharmony_ci
4928bf80f4bSopenharmony_ci    for(int i = 0; i < align; i++) {
4938bf80f4bSopenharmony_ci        fputc(0, e); // alignment byte to begin arm64 architecture at 8 byte boundary
4948bf80f4bSopenharmony_ci    }
4958bf80f4bSopenharmony_ci
4968bf80f4bSopenharmony_ci    fwrite(&arm64_header, sizeof(arm64_header), 1, e);
4978bf80f4bSopenharmony_ci    fwrite(&data_seg, sizeof(data_seg), 1, e);
4988bf80f4bSopenharmony_ci    fwrite(&data_sect, sizeof(data_sect), 1, e);
4998bf80f4bSopenharmony_ci    fwrite(&symtab, sizeof(symtab), 1, e);
5008bf80f4bSopenharmony_ci    fwrite(data, size_of_section, 1, e);
5018bf80f4bSopenharmony_ci    for(int i = 0; i < sectionAlign; i++) {
5028bf80f4bSopenharmony_ci        fputc(0, e); // alignment byte to begin string table 8 byte boundary
5038bf80f4bSopenharmony_ci    }
5048bf80f4bSopenharmony_ci    fwrite(&syms, sizeof(syms), 1, e);
5058bf80f4bSopenharmony_ci    fputc(0, e); // filler byte to begin string table
5068bf80f4bSopenharmony_ci    fwrite(sizeName.c_str(), sizeName.size() + 1, 1, e);
5078bf80f4bSopenharmony_ci    fwrite(dataName.c_str(), dataName.size() + 1, 1, e);
5088bf80f4bSopenharmony_ci    fclose(e);
5098bf80f4bSopenharmony_ci#endif
5108bf80f4bSopenharmony_ci}
5118bf80f4bSopenharmony_ci
5128bf80f4bSopenharmony_ciint main(int argc, char* argv[])
5138bf80f4bSopenharmony_ci{
5148bf80f4bSopenharmony_ci    std::string obj32Name = "rofs_32.obj";
5158bf80f4bSopenharmony_ci    std::string obj64Name = "rofs_64.obj";
5168bf80f4bSopenharmony_ci    std::string o32Name = "rofs_32.o";
5178bf80f4bSopenharmony_ci    std::string o64Name = "rofs_64.o";
5188bf80f4bSopenharmony_ci    std::string x32Name = "rofs_x86.o";
5198bf80f4bSopenharmony_ci    std::string x64Name = "rofs_x64.o";
5208bf80f4bSopenharmony_ci    std::string macName = "rofs_mac.o";
5218bf80f4bSopenharmony_ci    std::string secName = "rofs";
5228bf80f4bSopenharmony_ci
5238bf80f4bSopenharmony_ci    bool buildX86 = true, buildX64 = true, buildV7 = true, buildV8 = true;
5248bf80f4bSopenharmony_ci    bool buildWindows = true, buildAndroid = true, buildMac = true;
5258bf80f4bSopenharmony_ci
5268bf80f4bSopenharmony_ci    std::string inPath = { "" }, roPath = { "" };
5278bf80f4bSopenharmony_ci
5288bf80f4bSopenharmony_ci    int baseArg = 0;
5298bf80f4bSopenharmony_ci    if (argc >= 2) {
5308bf80f4bSopenharmony_ci        if (argv[1][0] == '-') {
5318bf80f4bSopenharmony_ci            buildAndroid = false;
5328bf80f4bSopenharmony_ci            buildWindows = false;
5338bf80f4bSopenharmony_ci            buildMac = false;
5348bf80f4bSopenharmony_ci            buildX86 = buildX64 = buildV7 = buildV8 = false;
5358bf80f4bSopenharmony_ci        }
5368bf80f4bSopenharmony_ci        bool platset = false;
5378bf80f4bSopenharmony_ci        for (;;) {
5388bf80f4bSopenharmony_ci            if (baseArg + 1 >= argc) {
5398bf80f4bSopenharmony_ci                printf("Invalid argument!\n");
5408bf80f4bSopenharmony_ci                return 0;
5418bf80f4bSopenharmony_ci            }
5428bf80f4bSopenharmony_ci            if (argv[baseArg + 1][0] != '-')
5438bf80f4bSopenharmony_ci                break;
5448bf80f4bSopenharmony_ci            if (strcmp(argv[baseArg + 1], "-linux") == 0) {
5458bf80f4bSopenharmony_ci                platset = true;
5468bf80f4bSopenharmony_ci                buildAndroid = true;
5478bf80f4bSopenharmony_ci                baseArg++;
5488bf80f4bSopenharmony_ci            } else if (strcmp(argv[baseArg + 1], "-android") == 0) {
5498bf80f4bSopenharmony_ci                platset = true;
5508bf80f4bSopenharmony_ci                buildAndroid = true;
5518bf80f4bSopenharmony_ci                baseArg++;
5528bf80f4bSopenharmony_ci            } else if (strcmp(argv[baseArg + 1], "-windows") == 0) {
5538bf80f4bSopenharmony_ci                platset = true;
5548bf80f4bSopenharmony_ci                buildWindows = true;
5558bf80f4bSopenharmony_ci                baseArg++;
5568bf80f4bSopenharmony_ci            } else if (strcmp(argv[baseArg + 1], "-mac") == 0) {
5578bf80f4bSopenharmony_ci                platset = true;
5588bf80f4bSopenharmony_ci                buildMac = true;
5598bf80f4bSopenharmony_ci                baseArg++;
5608bf80f4bSopenharmony_ci            } else if (strcmp(argv[baseArg + 1], "-x86") == 0) {
5618bf80f4bSopenharmony_ci                buildX86 = true;
5628bf80f4bSopenharmony_ci                baseArg++;
5638bf80f4bSopenharmony_ci            } else if (strcmp(argv[baseArg + 1], "-x86_64") == 0) {
5648bf80f4bSopenharmony_ci                buildAndroid = true;
5658bf80f4bSopenharmony_ci                buildX64 = true;
5668bf80f4bSopenharmony_ci                baseArg++;
5678bf80f4bSopenharmony_ci            } else if (strcmp(argv[baseArg + 1], "-x64") == 0) {
5688bf80f4bSopenharmony_ci                buildX64 = true;
5698bf80f4bSopenharmony_ci                buildWindows = true;
5708bf80f4bSopenharmony_ci                baseArg++;
5718bf80f4bSopenharmony_ci            } else if (strcmp(argv[baseArg + 1], "-armeabi-v7a") == 0) {
5728bf80f4bSopenharmony_ci                buildV7 = true;
5738bf80f4bSopenharmony_ci                buildAndroid = true;
5748bf80f4bSopenharmony_ci                platset = true;
5758bf80f4bSopenharmony_ci                baseArg++;
5768bf80f4bSopenharmony_ci            } else if (strcmp(argv[baseArg + 1], "-arm64-v8a") == 0) {
5778bf80f4bSopenharmony_ci                buildV8 = true;
5788bf80f4bSopenharmony_ci                buildAndroid = true;
5798bf80f4bSopenharmony_ci                platset = true;
5808bf80f4bSopenharmony_ci                baseArg++;
5818bf80f4bSopenharmony_ci            } else if (strcmp(argv[baseArg + 1], "-extensions") == 0) {
5828bf80f4bSopenharmony_ci                baseArg++;
5838bf80f4bSopenharmony_ci                if (baseArg + 1 >= argc) {
5848bf80f4bSopenharmony_ci                    printf("Invalid argument!\n");
5858bf80f4bSopenharmony_ci                    return 0;
5868bf80f4bSopenharmony_ci                }
5878bf80f4bSopenharmony_ci                auto exts = std::string_view(argv[baseArg + 1]);
5888bf80f4bSopenharmony_ci                while (!exts.empty()) {
5898bf80f4bSopenharmony_ci                    auto pos = exts.find(';');
5908bf80f4bSopenharmony_ci                    pos = std::min(pos, exts.size());
5918bf80f4bSopenharmony_ci                    valid_exts.push_back(exts.substr(0, pos));
5928bf80f4bSopenharmony_ci                    exts.remove_prefix(std::min(pos + 1, exts.size()));
5938bf80f4bSopenharmony_ci                }
5948bf80f4bSopenharmony_ci                baseArg++;
5958bf80f4bSopenharmony_ci            } else {
5968bf80f4bSopenharmony_ci                printf("Invalid argument!\n");
5978bf80f4bSopenharmony_ci                return 0;
5988bf80f4bSopenharmony_ci            }
5998bf80f4bSopenharmony_ci        }
6008bf80f4bSopenharmony_ci        if (!platset) {
6018bf80f4bSopenharmony_ci            buildWindows = true;
6028bf80f4bSopenharmony_ci            buildAndroid = true;
6038bf80f4bSopenharmony_ci            buildMac = true;
6048bf80f4bSopenharmony_ci        }
6058bf80f4bSopenharmony_ci
6068bf80f4bSopenharmony_ci        if (argc < baseArg + 3) {
6078bf80f4bSopenharmony_ci            printf("invalid args");
6088bf80f4bSopenharmony_ci            return 0;
6098bf80f4bSopenharmony_ci        }
6108bf80f4bSopenharmony_ci
6118bf80f4bSopenharmony_ci        inPath = argv[baseArg + 1];
6128bf80f4bSopenharmony_ci    } else {
6138bf80f4bSopenharmony_ci        printf("Not enough arguments!\n");
6148bf80f4bSopenharmony_ci        return 0;
6158bf80f4bSopenharmony_ci    }
6168bf80f4bSopenharmony_ci    if (argc >= baseArg + 3) {
6178bf80f4bSopenharmony_ci        if (argv[baseArg + 2][0] == '/') {
6188bf80f4bSopenharmony_ci            roPath = argv[baseArg + 2] + 1;
6198bf80f4bSopenharmony_ci        } else {
6208bf80f4bSopenharmony_ci            roPath = argv[baseArg + 2];
6218bf80f4bSopenharmony_ci        }
6228bf80f4bSopenharmony_ci    }
6238bf80f4bSopenharmony_ci    if (argc >= baseArg + 5) {
6248bf80f4bSopenharmony_ci        gDataName = argv[baseArg + 3];
6258bf80f4bSopenharmony_ci        gSizeName = argv[baseArg + 4];
6268bf80f4bSopenharmony_ci    }
6278bf80f4bSopenharmony_ci    if (argc == baseArg + 6) {
6288bf80f4bSopenharmony_ci        secName = obj32Name = obj64Name = o32Name = o64Name = x32Name = x64Name = macName = argv[baseArg + 5];
6298bf80f4bSopenharmony_ci        obj32Name += "_32.obj";
6308bf80f4bSopenharmony_ci        obj64Name += "_64.obj";
6318bf80f4bSopenharmony_ci        o32Name += "_32.o";
6328bf80f4bSopenharmony_ci        o64Name += "_64.o";
6338bf80f4bSopenharmony_ci        x32Name += "_x86.o";
6348bf80f4bSopenharmony_ci        x64Name += "_x64.o";
6358bf80f4bSopenharmony_ci        macName += "_mac.o";
6368bf80f4bSopenharmony_ci    }
6378bf80f4bSopenharmony_ci    add_directory(inPath, roPath);
6388bf80f4bSopenharmony_ci
6398bf80f4bSopenharmony_ci    // fix offsets
6408bf80f4bSopenharmony_ci    size_t base_offset = sizeof(fs_entry) * (directory.size() + 1);
6418bf80f4bSopenharmony_ci    for (auto& d : directory) {
6428bf80f4bSopenharmony_ci        d.offset += base_offset;
6438bf80f4bSopenharmony_ci    }
6448bf80f4bSopenharmony_ci
6458bf80f4bSopenharmony_ci    // add terminator
6468bf80f4bSopenharmony_ci    directory.push_back({ { 0 }, 0, 0 });
6478bf80f4bSopenharmony_ci
6488bf80f4bSopenharmony_ci    const size_t size_of_dir = (sizeof(fs_entry) * directory.size());
6498bf80f4bSopenharmony_ci    const size_t size_of_data = bin.size() + size_of_dir;
6508bf80f4bSopenharmony_ci    uint8_t* data = new uint8_t[size_of_data + sizeof(uint64_t)];
6518bf80f4bSopenharmony_ci    *(uint64_t*)(data) = size_of_data;
6528bf80f4bSopenharmony_ci    memcpy(data + sizeof(uint64_t), directory.data(), size_of_dir);
6538bf80f4bSopenharmony_ci    memcpy(data + sizeof(uint64_t) + size_of_dir, bin.data(), bin.size());
6548bf80f4bSopenharmony_ci
6558bf80f4bSopenharmony_ci    // Build obj
6568bf80f4bSopenharmony_ci    if (buildWindows) {
6578bf80f4bSopenharmony_ci        if (buildX86) {
6588bf80f4bSopenharmony_ci            write_obj(obj32Name, secName, size_of_data, data, false);
6598bf80f4bSopenharmony_ci        }
6608bf80f4bSopenharmony_ci        if (buildX64) {
6618bf80f4bSopenharmony_ci            write_obj(obj64Name, secName, size_of_data, data, true);
6628bf80f4bSopenharmony_ci        }
6638bf80f4bSopenharmony_ci    }
6648bf80f4bSopenharmony_ci    // Create .elf (.o)
6658bf80f4bSopenharmony_ci    if (buildAndroid) {
6668bf80f4bSopenharmony_ci        struct {
6678bf80f4bSopenharmony_ci            Elf32_Ehdr head{};
6688bf80f4bSopenharmony_ci            Elf32_Shdr sections[4]{};
6698bf80f4bSopenharmony_ci            Elf32_Sym symbs[3]{};
6708bf80f4bSopenharmony_ci        } o32;
6718bf80f4bSopenharmony_ci        struct {
6728bf80f4bSopenharmony_ci            Elf64_Ehdr head{};
6738bf80f4bSopenharmony_ci            Elf64_Shdr sections[4]{};
6748bf80f4bSopenharmony_ci            Elf64_Sym symbs[3]{};
6758bf80f4bSopenharmony_ci        } o64;
6768bf80f4bSopenharmony_ci        if (buildV7) {
6778bf80f4bSopenharmony_ci            write_elf(o32, EM_ARM, o32Name, secName, size_of_data, data);
6788bf80f4bSopenharmony_ci        }
6798bf80f4bSopenharmony_ci        if (buildV8) {
6808bf80f4bSopenharmony_ci            write_elf(o64, EM_AARCH64, o64Name, secName, size_of_data, data);
6818bf80f4bSopenharmony_ci        }
6828bf80f4bSopenharmony_ci        if (buildX86) {
6838bf80f4bSopenharmony_ci            write_elf(o32, EM_386, x32Name, secName, size_of_data, data);
6848bf80f4bSopenharmony_ci        }
6858bf80f4bSopenharmony_ci        if (buildX64) {
6868bf80f4bSopenharmony_ci            write_elf(o64, EM_X86_64, x64Name, secName, size_of_data, data);
6878bf80f4bSopenharmony_ci        }
6888bf80f4bSopenharmony_ci    }
6898bf80f4bSopenharmony_ci    // Create mach-o (.o)
6908bf80f4bSopenharmony_ci    if (buildMac) {
6918bf80f4bSopenharmony_ci        write_macho(macName, secName, size_of_data, data);
6928bf80f4bSopenharmony_ci    }
6938bf80f4bSopenharmony_ci}
694