kit

kit
git clone https://git.ryansepassi.com/git/kit.git
Log | Files | Refs | README

archive_engine.c (3374B)


      1 #include "archive_engine.h"
      2 
      3 #include <kit/archive.h>
      4 
      5 #include "inputs.h"
      6 
      7 int driver_archive_emit(DriverEnv* env, const KitContext* ctx, const char* tool,
      8                         KitObjBuilder* const* objs, const KitSlice* names,
      9                         uint32_t n, uint64_t epoch, KitWriter* out) {
     10   KitArInput* members = NULL;
     11   KitWriter** memw = NULL;
     12   KitArMemberSymbols* msyms = NULL;
     13   void** sym_blobs = NULL;
     14   size_t* sym_blob_szs = NULL;
     15   KitArWriteOptions opts = {0};
     16   uint32_t i;
     17   int rc = 1;
     18 
     19   if (n == 0) {
     20     driver_errf(tool, "no objects to archive");
     21     return 1;
     22   }
     23 
     24   members = driver_alloc_zeroed(env, (size_t)n * sizeof(*members));
     25   memw = driver_alloc_zeroed(env, (size_t)n * sizeof(*memw));
     26   msyms = driver_alloc_zeroed(env, (size_t)n * sizeof(*msyms));
     27   sym_blobs = driver_alloc_zeroed(env, (size_t)n * sizeof(*sym_blobs));
     28   sym_blob_szs = driver_alloc_zeroed(env, (size_t)n * sizeof(*sym_blob_szs));
     29   if (!members || !memw || !msyms || !sym_blobs || !sym_blob_szs) {
     30     driver_errf(tool, "out of memory");
     31     goto out;
     32   }
     33 
     34   /* Serialize each builder into its own in-memory writer; the member bytes
     35    * alias that writer's buffer, so the writers stay open until kit_ar_write
     36    * has consumed them. */
     37   for (i = 0; i < n; ++i) {
     38     const uint8_t* bytes;
     39     size_t len = 0;
     40     if (kit_writer_mem(ctx->heap, &memw[i]) != KIT_OK) {
     41       driver_errf(tool, "out of memory");
     42       goto out;
     43     }
     44     if (kit_obj_builder_emit(objs[i], memw[i]) != KIT_OK ||
     45         kit_writer_status(memw[i]) != KIT_OK) {
     46       driver_errf(tool, "failed to serialize object: %.*s",
     47                   KIT_SLICE_ARG(names[i]));
     48       goto out;
     49     }
     50     bytes = kit_writer_mem_bytes(memw[i], &len);
     51     members[i].name = names[i];
     52     members[i].bytes.s = (const char*)bytes;
     53     members[i].bytes.len = len;
     54   }
     55 
     56   /* Build the archive symbol index so the result links like a normal static
     57    * library: collect each member's globally-defined symbols. */
     58   for (i = 0; i < n; ++i) {
     59     void* blob = NULL;
     60     size_t blob_size = 0;
     61     const KitSlice* syms = NULL;
     62     uint32_t count = 0;
     63     if (driver_collect_obj_global_syms(env, ctx, tool, &members[i].bytes, &blob,
     64                                        &blob_size, &syms, &count) != 0)
     65       goto out;
     66     if (count == 0) continue;
     67     sym_blobs[i] = blob;
     68     sym_blob_szs[i] = blob_size;
     69     msyms[i].names = syms;
     70     msyms[i].count = count;
     71   }
     72 
     73   opts.epoch = epoch;
     74   opts.long_names = 1;
     75   opts.symbol_index = 1;
     76   opts.member_symbols = msyms;
     77 
     78   if (kit_ar_write(out, members, n, &opts) != KIT_OK ||
     79       kit_writer_status(out) != KIT_OK) {
     80     driver_errf(tool, "failed to write archive");
     81     goto out;
     82   }
     83   rc = 0;
     84 
     85 out:
     86   if (sym_blobs && sym_blob_szs) {
     87     for (i = 0; i < n; ++i) {
     88       if (sym_blobs[i])
     89         driver_collect_obj_global_syms_free(env, sym_blobs[i], sym_blob_szs[i]);
     90     }
     91   }
     92   if (memw) {
     93     for (i = 0; i < n; ++i)
     94       if (memw[i]) kit_writer_close(memw[i]);
     95   }
     96   if (members) driver_free(env, members, (size_t)n * sizeof(*members));
     97   if (memw) driver_free(env, memw, (size_t)n * sizeof(*memw));
     98   if (msyms) driver_free(env, msyms, (size_t)n * sizeof(*msyms));
     99   if (sym_blobs) driver_free(env, sym_blobs, (size_t)n * sizeof(*sym_blobs));
    100   if (sym_blob_szs)
    101     driver_free(env, sym_blob_szs, (size_t)n * sizeof(*sym_blob_szs));
    102   return rc;
    103 }