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 }