kit

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

image.c (49188B)


      1 #include "obj/image.h"
      2 
      3 #include <kit/object.h>
      4 #include <string.h>
      5 
      6 #include "core/diag.h"
      7 
      8 /* A contiguous piece of output. Both the segment path (flat load image) and
      9  * the section path (ordered concatenation) lower to a list of these.
     10  *
     11  *   data/size : the bytes to emit (borrowed from object_bytes).
     12  *   addr/end  : layout addresses for the segment path; for the section path
     13  *               these are synthesized so the ranges pack with no holes.
     14  *   name      : diagnostic spelling.
     15  *   order     : stable tiebreak for equal addresses. */
     16 typedef struct ImageRange {
     17   const uint8_t* data;
     18   uint64_t size;
     19   uint64_t original_addr;
     20   uint64_t addr;
     21   uint64_t end; /* addr + on-disk size (file end) */
     22   KitSlice name;
     23   uint32_t order;
     24 } ImageRange;
     25 
     26 static int u64_add(uint64_t a, uint64_t b, uint64_t* out) {
     27   if (UINT64_MAX - a < b) return 0;
     28   *out = a + b;
     29   return 1;
     30 }
     31 
     32 static int u64_add_bias(uint64_t a, int64_t bias, uint64_t* out) {
     33   if (bias >= 0) return u64_add(a, (uint64_t)bias, out);
     34   {
     35     uint64_t mag = (uint64_t)(-(bias + 1)) + 1u;
     36     if (a < mag) return 0;
     37     *out = a - mag;
     38     return 1;
     39   }
     40 }
     41 
     42 static int u64_align_up(uint64_t v, uint64_t align, uint64_t* out) {
     43   uint64_t rem;
     44   if (align <= 1) {
     45     *out = v;
     46     return 1;
     47   }
     48   rem = v % align;
     49   if (!rem) {
     50     *out = v;
     51     return 1;
     52   }
     53   return u64_add(v, align - rem, out);
     54 }
     55 
     56 static void put_u32le(uint8_t* p, uint32_t v) {
     57   p[0] = (uint8_t)v;
     58   p[1] = (uint8_t)(v >> 8);
     59   p[2] = (uint8_t)(v >> 16);
     60   p[3] = (uint8_t)(v >> 24);
     61 }
     62 
     63 static void put_u64le(uint8_t* p, uint64_t v) {
     64   put_u32le(p, (uint32_t)v);
     65   put_u32le(p + 4, (uint32_t)(v >> 32));
     66 }
     67 
     68 static int ascii_lower(int c) {
     69   return (c >= 'A' && c <= 'Z') ? c + ('a' - 'A') : c;
     70 }
     71 
     72 static int slice_ieq(KitSlice a, KitSlice b) {
     73   size_t i;
     74   if (a.len != b.len) return 0;
     75   for (i = 0; i < a.len; ++i) {
     76     if (ascii_lower((unsigned char)a.s[i]) !=
     77         ascii_lower((unsigned char)b.s[i]))
     78       return 0;
     79   }
     80   return 1;
     81 }
     82 
     83 static int slice_eq(KitSlice a, KitSlice b) {
     84   if (a.len != b.len) return 0;
     85   return a.len == 0 || memcmp(a.s, b.s, a.len) == 0;
     86 }
     87 
     88 static int name_in_list(KitSlice name, const KitSlice* list, uint32_t n) {
     89   uint32_t i;
     90   for (i = 0; i < n; ++i) {
     91     if (slice_eq(name, list[i])) return 1;
     92   }
     93   return 0;
     94 }
     95 
     96 #define KIT_IHEX_DATA_MAX 16u
     97 #define KIT_SREC_DATA_MAX 16u
     98 
     99 static const char kHex[] = "0123456789ABCDEF";
    100 
    101 static void line_append_hex_u8(char* line, size_t* n, uint8_t v) {
    102   line[(*n)++] = kHex[(v >> 4) & 0xfu];
    103   line[(*n)++] = kHex[v & 0xfu];
    104 }
    105 
    106 static void line_append_hex_u16(char* line, size_t* n, uint16_t v) {
    107   line_append_hex_u8(line, n, (uint8_t)(v >> 8));
    108   line_append_hex_u8(line, n, (uint8_t)v);
    109 }
    110 
    111 static void line_append_hex_u64_be(char* line, size_t* n, uint64_t v,
    112                                   uint32_t nbytes) {
    113   uint32_t i;
    114   uint32_t shift = (nbytes - 1u) * 8u;
    115   for (i = 0; i < nbytes; ++i, shift -= 8u) {
    116     line_append_hex_u8(line, n, (uint8_t)(v >> shift));
    117   }
    118 }
    119 
    120 static KitStatus write_line(KitWriter* out, const char* data, size_t n) {
    121   return (kit_writer_write(out, data, n) == KIT_OK) ? KIT_OK : KIT_IO;
    122 }
    123 
    124 static KitSlice drop_pt_prefix(KitSlice s) {
    125   if (s.len > 3 && ascii_lower((unsigned char)s.s[0]) == 'p' &&
    126       ascii_lower((unsigned char)s.s[1]) == 't' && s.s[2] == '_') {
    127     s.s += 3;
    128     s.len -= 3;
    129   }
    130   return s;
    131 }
    132 
    133 static int segment_name_match(KitSlice have, KitSlice want) {
    134   have = drop_pt_prefix(have);
    135   want = drop_pt_prefix(want);
    136   return slice_ieq(have, want);
    137 }
    138 
    139 static int is_load_segment(KitSlice name) {
    140   return segment_name_match(name, KIT_SLICE_LIT("LOAD"));
    141 }
    142 
    143 static int segment_in_list(KitSlice have, const KitSlice* list, uint32_t n) {
    144   uint32_t i;
    145   for (i = 0; i < n; ++i) {
    146     if (segment_name_match(have, list[i])) return 1;
    147   }
    148   return 0;
    149 }
    150 
    151 static int select_segment(KitObjFmt fmt, const KitObjSegInfo* seg,
    152                           const KitImageOptions* opts) {
    153   /* --remove-section drops a segment by name regardless of base selection. */
    154   if (opts->nremove_sections &&
    155       segment_in_list(seg->name, opts->remove_sections,
    156                       opts->nremove_sections))
    157     return 0;
    158   /* --only-section, when given, is the authoritative keep-set. */
    159   if (opts->nonly_sections)
    160     return segment_in_list(seg->name, opts->only_sections,
    161                            opts->nonly_sections);
    162   if (opts->nsegments == 0) {
    163     if (fmt == KIT_OBJ_ELF) return is_load_segment(seg->name);
    164     return 1;
    165   }
    166   return segment_in_list(seg->name, opts->segments, opts->nsegments);
    167 }
    168 
    169 static int select_alloc_section(const KitObjSecInfo* sec,
    170                                 const KitImageOptions* opts) {
    171   if (!(sec->flags & KIT_SF_ALLOC)) return 0;
    172   if (opts->nonly_sections &&
    173       !name_in_list(sec->name, opts->only_sections, opts->nonly_sections))
    174     return 0;
    175   if (opts->nremove_sections &&
    176       name_in_list(sec->name, opts->remove_sections, opts->nremove_sections))
    177     return 0;
    178   return 1;
    179 }
    180 
    181 bool obj_image_segment_selected(KitObjFmt fmt, const KitObjSegInfo* seg,
    182                                 const KitImageOptions* opts) {
    183   /* A segment contributes bytes to the emitted image iff the base/only/remove
    184    * policy keeps it AND it has on-disk contents. This is the exact predicate
    185    * the segment collector applies (see collect_ranges): callers that need to
    186    * report "what the image contains" must route through here rather than
    187    * reimplementing the matching, which would drift from the emitter. */
    188   if (seg->file_size == 0) return false;
    189   return select_segment(fmt, seg, opts) != 0;
    190 }
    191 
    192 static uint64_t seg_addr(const KitObjSegInfo* seg,
    193                          const KitImageOptions* opts) {
    194   switch ((KitImageAddrKind)opts->addr) {
    195     case KIT_IMAGE_ADDR_PADDR:
    196     case KIT_IMAGE_ADDR_LMA:
    197       return seg->paddr;
    198     case KIT_IMAGE_ADDR_VADDR:
    199     default:
    200       return seg->vaddr;
    201   }
    202 }
    203 
    204 static KitStatus ranges_push(const KitContext* ctx, ImageRange** ranges,
    205                              uint32_t* nranges, uint32_t* cap,
    206                              const ImageRange* r) {
    207   KitHeap* h = ctx->heap;
    208   if (*nranges >= *cap) {
    209     uint32_t newcap = *cap ? *cap * 2u : 4u;
    210     ImageRange* next;
    211     if (newcap <= *cap) return KIT_NOMEM;
    212     next = (ImageRange*)h->alloc(h, (size_t)newcap * sizeof(*next),
    213                                  _Alignof(ImageRange));
    214     if (!next) return KIT_NOMEM;
    215     if (*ranges) {
    216       memcpy(next, *ranges, (size_t)(*nranges) * sizeof(*next));
    217       h->free(h, *ranges, (size_t)(*cap) * sizeof(**ranges));
    218     }
    219     *ranges = next;
    220     *cap = newcap;
    221   }
    222   (*ranges)[(*nranges)++] = *r;
    223   return KIT_OK;
    224 }
    225 
    226 static void ranges_free(const KitContext* ctx, ImageRange* ranges,
    227                         uint32_t cap) {
    228   if (ranges) ctx->heap->free(ctx->heap, ranges, (size_t)cap * sizeof(*ranges));
    229 }
    230 
    231 static void ranges_sort(ImageRange* r, uint32_t n) {
    232   uint32_t i;
    233   for (i = 1; i < n; ++i) {
    234     ImageRange key = r[i];
    235     uint32_t j = i;
    236     while (j > 0) {
    237       int move = r[j - 1].addr > key.addr ||
    238                  (r[j - 1].addr == key.addr && r[j - 1].order > key.order);
    239       if (!move) break;
    240       r[j] = r[j - 1];
    241       --j;
    242     }
    243     r[j] = key;
    244   }
    245 }
    246 
    247 /* Convert possibly-overlapping input ranges into disjoint fragments. Ranges
    248  * are applied in selection order; a later range replaces bytes from every
    249  * earlier range it covers. This is deterministic for relocatable formats
    250  * whose allocated sections commonly all report address zero, and avoids
    251  * allocating a potentially enormous flat staging buffer. */
    252 static KitStatus normalize_overlaps(const KitContext* ctx,
    253                                     const ImageRange* source,
    254                                     uint32_t nsource, ImageRange** ranges_out,
    255                                     uint32_t* nranges_out, uint32_t* cap_out) {
    256   ImageRange* ranges = NULL;
    257   uint32_t nranges = 0, cap = 0, i;
    258   KitStatus st;
    259 
    260   *ranges_out = NULL;
    261   *nranges_out = 0;
    262   *cap_out = 0;
    263   for (i = 0; i < nsource; ++i) {
    264     ImageRange incoming = source[i];
    265     uint32_t j = 0;
    266     while (j < nranges) {
    267       ImageRange old = ranges[j];
    268       if (old.end <= incoming.addr || old.addr >= incoming.end) {
    269         ++j;
    270         continue;
    271       }
    272       if (old.addr < incoming.addr) {
    273         /* Preserve the old prefix. If it also has a suffix, append that as a
    274          * second borrowed fragment before installing the incoming range. */
    275         ranges[j].size = incoming.addr - old.addr;
    276         ranges[j].end = incoming.addr;
    277         if (old.end > incoming.end) {
    278           ImageRange suffix = old;
    279           uint64_t delta = incoming.end - old.addr;
    280           suffix.data += (size_t)delta;
    281           suffix.size = old.end - incoming.end;
    282           suffix.original_addr += delta;
    283           suffix.addr = incoming.end;
    284           st = ranges_push(ctx, &ranges, &nranges, &cap, &suffix);
    285           if (st != KIT_OK) {
    286             ranges_free(ctx, ranges, cap);
    287             return st;
    288           }
    289         }
    290         ++j;
    291         continue;
    292       }
    293       if (old.end > incoming.end) {
    294         uint64_t delta = incoming.end - old.addr;
    295         ranges[j].data += (size_t)delta;
    296         ranges[j].size = old.end - incoming.end;
    297         ranges[j].original_addr += delta;
    298         ranges[j].addr = incoming.end;
    299         ++j;
    300         continue;
    301       }
    302       /* Fully covered old fragment. Preserve no ordering significance here;
    303        * the final address sort establishes the emission order. */
    304       if (j + 1u < nranges)
    305         memmove(&ranges[j], &ranges[j + 1u],
    306                 (size_t)(nranges - j - 1u) * sizeof(*ranges));
    307       --nranges;
    308     }
    309     st = ranges_push(ctx, &ranges, &nranges, &cap, &incoming);
    310     if (st != KIT_OK) {
    311       ranges_free(ctx, ranges, cap);
    312       return st;
    313     }
    314   }
    315   ranges_sort(ranges, nranges);
    316   *ranges_out = ranges;
    317   *nranges_out = nranges;
    318   *cap_out = cap;
    319   return KIT_OK;
    320 }
    321 
    322 static KitStatus collect_ranges(const KitContext* ctx, KitObjFile* obj,
    323                                 const KitSlice* bytes,
    324                                 const KitImageOptions* opts,
    325                                 ImageRange** ranges_out, uint32_t* nranges_out,
    326                                 uint32_t* cap_out, uint64_t* mem_end_out) {
    327   KitObjSegIter* it = NULL;
    328   KitObjSegInfo seg;
    329   ImageRange* ranges = NULL;
    330   uint32_t nranges = 0, cap = 0, order = 0;
    331   uint64_t mem_end_max = 0;
    332   KitStatus st;
    333   KitObjFmt fmt;
    334 
    335   *ranges_out = NULL;
    336   *nranges_out = 0;
    337   *cap_out = 0;
    338   *mem_end_out = 0;
    339 
    340   fmt = kit_obj_fmt(obj);
    341   st = kit_obj_segiter_new(obj, &it);
    342   if (st != KIT_OK) return st;
    343 
    344   while (kit_obj_segiter_next(it, &seg) == KIT_ITER_ITEM) {
    345     ImageRange r;
    346     uint64_t addr;
    347     uint64_t end;
    348 
    349     if (!select_segment(fmt, &seg, opts)) {
    350       ++order;
    351       continue;
    352     }
    353     /* Memory-span accounting runs for every selected loadable segment,
    354      * including BSS-only ones (file_size == 0) that contribute no bytes but do
    355      * extend the in-memory footprint an Image header's image_size must report.
    356      * vsize (>= file_size) carries the trailing BSS. */
    357     {
    358       uint64_t maddr, mend;
    359       uint64_t msize = seg.vsize >= seg.file_size ? seg.vsize : seg.file_size;
    360       if (u64_add_bias(seg_addr(&seg, opts), opts->bias, &maddr) &&
    361           u64_add(maddr, msize, &mend) && mend > mem_end_max)
    362         mem_end_max = mend;
    363     }
    364     if (seg.file_size == 0) {
    365       ++order;
    366       continue;
    367     }
    368     if (seg.file_off > bytes->len || seg.file_size > bytes->len - seg.file_off) {
    369       kit_ctx_diagf(ctx, "image: segment %.*s file range is out of bounds",
    370                     KIT_SLICE_ARG(seg.name));
    371       kit_obj_segiter_free(it);
    372       ranges_free(ctx, ranges, cap);
    373       return KIT_MALFORMED;
    374     }
    375     if (!u64_add_bias(seg_addr(&seg, opts), opts->bias, &addr) ||
    376         !u64_add(addr, seg.file_size, &end)) {
    377       kit_ctx_diagf(ctx, "image: segment %.*s address range overflows",
    378                     KIT_SLICE_ARG(seg.name));
    379       kit_obj_segiter_free(it);
    380       ranges_free(ctx, ranges, cap);
    381       return KIT_MALFORMED;
    382     }
    383 
    384     memset(&r, 0, sizeof r);
    385     r.data = bytes->data + (size_t)seg.file_off;
    386     r.size = seg.file_size;
    387     r.original_addr = seg_addr(&seg, opts);
    388     r.addr = addr;
    389     r.end = end;
    390     r.name = seg.name;
    391     r.order = order;
    392     st = ranges_push(ctx, &ranges, &nranges, &cap, &r);
    393     if (st != KIT_OK) {
    394       kit_obj_segiter_free(it);
    395       ranges_free(ctx, ranges, cap);
    396       return st;
    397     }
    398     ++order;
    399   }
    400   kit_obj_segiter_free(it);
    401 
    402   if (!nranges) {
    403     kit_ctx_diagf(ctx, "image: no selected loadable segment bytes");
    404     ranges_free(ctx, ranges, cap);
    405     return KIT_NOT_FOUND;
    406   }
    407   *ranges_out = ranges;
    408   *nranges_out = nranges;
    409   *cap_out = cap;
    410   *mem_end_out = mem_end_max;
    411   return KIT_OK;
    412 }
    413 
    414 static KitStatus reject_selected_relocations(const KitContext* ctx,
    415                                              KitObjFile* obj,
    416                                              const KitImageOptions* opts) {
    417   KitObjRelocIter* it = NULL;
    418   KitObjReloc reloc;
    419   KitStatus st = kit_obj_reliter_new(obj, &it);
    420   if (st != KIT_OK) return st;
    421   while (kit_obj_reliter_next(it, &reloc) == KIT_ITER_ITEM) {
    422     KitObjSecInfo sec;
    423     if (kit_obj_section(obj, reloc.section, &sec) != KIT_OK) {
    424       kit_obj_reliter_free(it);
    425       kit_ctx_diagf(ctx, "image: relocation refers to an invalid section");
    426       return KIT_MALFORMED;
    427     }
    428     if (!select_alloc_section(&sec, opts)) continue;
    429     kit_ctx_diagf(ctx,
    430                   "image: unapplied relocation %.*s in selected section %.*s"
    431                   "%s%.*s",
    432                   KIT_SLICE_ARG(reloc.kind_name), KIT_SLICE_ARG(sec.name),
    433                   reloc.sym_name.len ? " against " : "",
    434                   KIT_SLICE_ARG(reloc.sym_name));
    435     kit_obj_reliter_free(it);
    436     return KIT_UNSUPPORTED;
    437   }
    438   kit_obj_reliter_free(it);
    439   return KIT_OK;
    440 }
    441 
    442 /* Address-bearing allocated-section collection. Relocatable objects have no
    443  * load segments, so this is their canonical raw-image source. Linked inputs
    444  * use it only when section keep/drop filters are explicit. */
    445 static KitStatus collect_alloc_sections(const KitContext* ctx,
    446                                         KitObjFile* obj,
    447                                         const KitImageOptions* opts,
    448                                         ImageRange** ranges_out,
    449                                         uint32_t* nranges_out,
    450                                         uint32_t* cap_out,
    451                                         uint64_t* mem_end_out) {
    452   ImageRange* ranges = NULL;
    453   uint32_t nranges = 0, cap = 0, i, nsections;
    454   uint64_t mem_end_max = 0;
    455   KitStatus st;
    456 
    457   *ranges_out = NULL;
    458   *nranges_out = 0;
    459   *cap_out = 0;
    460   *mem_end_out = 0;
    461 
    462   if (kit_obj_kind(obj) == KIT_OBJ_KIND_REL) {
    463     if (opts->nsegments) {
    464       kit_ctx_diagf(ctx,
    465                     "image: --segment is not valid for a relocatable object; "
    466                     "use --only-section");
    467       return KIT_INVALID;
    468     }
    469     st = reject_selected_relocations(ctx, obj, opts);
    470     if (st != KIT_OK) return st;
    471   }
    472 
    473   nsections = kit_obj_nsections(obj);
    474   for (i = 0; i < nsections; ++i) {
    475     KitObjSecInfo sec;
    476     const uint8_t* data = NULL;
    477     size_t len = 0;
    478     uint64_t addr, end, mend;
    479     ImageRange r;
    480     st = kit_obj_section(obj, i, &sec);
    481     if (st == KIT_NOT_FOUND) continue;
    482     if (st != KIT_OK) {
    483       ranges_free(ctx, ranges, cap);
    484       return KIT_MALFORMED;
    485     }
    486     if (!select_alloc_section(&sec, opts)) continue;
    487     if (!u64_add_bias(sec.addr, opts->bias, &addr) ||
    488         !u64_add(addr, sec.size, &mend)) {
    489       kit_ctx_diagf(ctx, "image: section %.*s address range overflows",
    490                     KIT_SLICE_ARG(sec.name));
    491       ranges_free(ctx, ranges, cap);
    492       return KIT_MALFORMED;
    493     }
    494     if (mend > mem_end_max) mem_end_max = mend;
    495     if (sec.kind == KIT_SEC_BSS || sec.size == 0) continue;
    496     if (kit_obj_section_data(obj, i, &data, &len) != KIT_OK) {
    497       kit_ctx_diagf(ctx, "image: cannot read selected section %.*s",
    498                     KIT_SLICE_ARG(sec.name));
    499       ranges_free(ctx, ranges, cap);
    500       return KIT_MALFORMED;
    501     }
    502     if (!data || len == 0) continue;
    503     if (!u64_add(addr, (uint64_t)len, &end)) {
    504       kit_ctx_diagf(ctx, "image: section %.*s file range overflows",
    505                     KIT_SLICE_ARG(sec.name));
    506       ranges_free(ctx, ranges, cap);
    507       return KIT_MALFORMED;
    508     }
    509     memset(&r, 0, sizeof r);
    510     r.data = data;
    511     r.size = (uint64_t)len;
    512     r.original_addr = sec.addr;
    513     r.addr = addr;
    514     r.end = end;
    515     r.name = sec.name;
    516     r.order = i;
    517     st = ranges_push(ctx, &ranges, &nranges, &cap, &r);
    518     if (st != KIT_OK) {
    519       ranges_free(ctx, ranges, cap);
    520       return st;
    521     }
    522   }
    523   if (!nranges) {
    524     kit_ctx_diagf(ctx, "image: no selected allocated section bytes");
    525     ranges_free(ctx, ranges, cap);
    526     return KIT_NOT_FOUND;
    527   }
    528   *ranges_out = ranges;
    529   *nranges_out = nranges;
    530   *cap_out = cap;
    531   *mem_end_out = mem_end_max;
    532   return KIT_OK;
    533 }
    534 
    535 /* Section-based collection: gather sections named by opts->section_order in
    536  * that exact order. The result is a pure concatenation — addresses are
    537  * synthesized so the ranges pack with no holes, and the caller must not treat
    538  * the layout base as a load address (report->sections_concat is set). */
    539 static KitStatus collect_sections(const KitContext* ctx, KitObjFile* obj,
    540                                   const KitImageOptions* opts,
    541                                   ImageRange** ranges_out, uint32_t* nranges_out,
    542                                   uint32_t* cap_out, uint64_t* mem_end_out) {
    543   ImageRange* ranges = NULL;
    544   uint32_t nranges = 0, cap = 0;
    545   uint64_t cursor = 0;
    546   uint32_t i;
    547   KitStatus st;
    548 
    549   *ranges_out = NULL;
    550   *nranges_out = 0;
    551   *cap_out = 0;
    552   *mem_end_out = 0;
    553 
    554   if (opts->nsection_order == 0) {
    555     kit_ctx_diagf(ctx, "image: --format sections requires at least one "
    556                        "--section NAME");
    557     return KIT_INVALID;
    558   }
    559 
    560   for (i = 0; i < opts->nsection_order; ++i) {
    561     KitSlice want = opts->section_order[i];
    562     KitObjSection sid = KIT_SECTION_NONE;
    563     const uint8_t* data = NULL;
    564     size_t len = 0;
    565     ImageRange r;
    566     uint64_t end;
    567 
    568     if (opts->nremove_sections &&
    569         name_in_list(want, opts->remove_sections, opts->nremove_sections)) {
    570       kit_ctx_diagf(ctx,
    571                     "image: section %.*s is both selected and --remove-section",
    572                     KIT_SLICE_ARG(want));
    573       ranges_free(ctx, ranges, cap);
    574       return KIT_INVALID;
    575     }
    576     if (kit_obj_section_by_name(obj, want, &sid) != KIT_OK ||
    577         sid == KIT_SECTION_NONE) {
    578       kit_ctx_diagf(ctx, "image: section %.*s not found", KIT_SLICE_ARG(want));
    579       ranges_free(ctx, ranges, cap);
    580       return KIT_NOT_FOUND;
    581     }
    582     if (kit_obj_section_data(obj, sid, &data, &len) != KIT_OK) {
    583       kit_ctx_diagf(ctx, "image: cannot read section %.*s bytes",
    584                     KIT_SLICE_ARG(want));
    585       ranges_free(ctx, ranges, cap);
    586       return KIT_MALFORMED;
    587     }
    588     if (len == 0 || data == NULL) {
    589       /* A NOBITS (.bss) or empty section contributes no bytes; skip it but
    590        * keep the position so order is preserved deterministically. */
    591       continue;
    592     }
    593     if (!u64_add(cursor, (uint64_t)len, &end)) {
    594       kit_ctx_diagf(ctx, "image: concatenated section size overflows");
    595       ranges_free(ctx, ranges, cap);
    596       return KIT_MALFORMED;
    597     }
    598 
    599     memset(&r, 0, sizeof r);
    600     r.data = data;
    601     r.size = (uint64_t)len;
    602     r.addr = cursor;
    603     r.end = end;
    604     r.name = want;
    605     r.order = i;
    606     st = ranges_push(ctx, &ranges, &nranges, &cap, &r);
    607     if (st != KIT_OK) {
    608       ranges_free(ctx, ranges, cap);
    609       return st;
    610     }
    611     cursor = end;
    612   }
    613 
    614   if (!nranges) {
    615     kit_ctx_diagf(ctx, "image: selected sections contain no bytes");
    616     ranges_free(ctx, ranges, cap);
    617     return KIT_NOT_FOUND;
    618   }
    619   /* Already in declared order with packed addresses; no sort needed. */
    620   *ranges_out = ranges;
    621   *nranges_out = nranges;
    622   *cap_out = cap;
    623   *mem_end_out = cursor; /* concatenation has no separate memory image */
    624   return KIT_OK;
    625 }
    626 
    627 static KitStatus compute_layout(const KitContext* ctx, const ImageRange* ranges,
    628                                 uint32_t nranges, const KitImageOptions* opts,
    629                                 uint64_t seg_mem_end, KitImageReport* report) {
    630   uint64_t base = opts->have_base ? opts->base : ranges[0].addr;
    631   uint64_t cur = base;
    632   uint64_t payload = 0;
    633   uint64_t max_hole = 0;
    634   uint32_t i;
    635   int had_holes = 0;
    636 
    637   if (base > ranges[0].addr) {
    638     kit_ctx_diagf(ctx, "image: base 0x%llx is above first selected byte 0x%llx",
    639                   (unsigned long long)base,
    640                   (unsigned long long)ranges[0].addr);
    641     return KIT_INVALID;
    642   }
    643 
    644   for (i = 0; i < nranges; ++i) {
    645     const ImageRange* r = &ranges[i];
    646     uint64_t hole;
    647     if (r->addr < cur) {
    648       kit_ctx_diagf(ctx,
    649                     "image: selected segments overlap at address 0x%llx",
    650                     (unsigned long long)r->addr);
    651       return KIT_MALFORMED;
    652     }
    653     hole = r->addr - cur;
    654     if (hole) {
    655       had_holes = 1;
    656       if (hole > max_hole) max_hole = hole;
    657       if (opts->fail_on_holes) {
    658         kit_ctx_diagf(ctx, "image: hole of %llu bytes at address 0x%llx",
    659                       (unsigned long long)hole, (unsigned long long)cur);
    660         return KIT_ERR;
    661       }
    662       if (opts->have_max_hole && hole > opts->max_hole) {
    663         kit_ctx_diagf(
    664             ctx,
    665             "image: hole of %llu bytes at address 0x%llx exceeds limit %llu",
    666             (unsigned long long)hole, (unsigned long long)cur,
    667             (unsigned long long)opts->max_hole);
    668         return KIT_ERR;
    669       }
    670     }
    671     if (!u64_add(payload, r->size, &payload)) {
    672       kit_ctx_diagf(ctx, "image: payload size overflows");
    673       return KIT_MALFORMED;
    674     }
    675     cur = r->end;
    676   }
    677 
    678   report->base = base;
    679   report->size = cur - base;
    680   report->payload_size = payload;
    681   report->max_hole = max_hole;
    682   /* In-memory span from the image base. seg_mem_end covers BSS-only segments
    683    * the byte ranges skip; fall back to the file span if it is somehow lower. */
    684   report->mem_size = seg_mem_end > base ? seg_mem_end - base : cur - base;
    685   report->nranges = nranges;
    686   report->had_holes = had_holes ? true : false;
    687 
    688   if (opts->have_align) {
    689     uint64_t aligned;
    690     if (!u64_align_up(report->size, opts->align, &aligned)) {
    691       kit_ctx_diagf(ctx, "image: aligned output size overflows");
    692       return KIT_MALFORMED;
    693     }
    694     report->size = aligned;
    695   }
    696   if (opts->have_pad_to) {
    697     if (opts->pad_to < report->size) {
    698       kit_ctx_diagf(ctx, "image: --pad-to %llu is smaller than image size %llu",
    699                     (unsigned long long)opts->pad_to,
    700                     (unsigned long long)report->size);
    701       return KIT_ERR;
    702     }
    703     report->size = opts->pad_to;
    704   }
    705   if (opts->have_max_size && report->size > opts->max_size) {
    706     kit_ctx_diagf(ctx, "image: output size %llu exceeds maximum %llu",
    707                   (unsigned long long)report->size,
    708                   (unsigned long long)opts->max_size);
    709     return KIT_ERR;
    710   }
    711   return KIT_OK;
    712 }
    713 
    714 static KitStatus write_fill(KitWriter* out, uint8_t fill, uint64_t n) {
    715   uint8_t buf[256];
    716   memset(buf, fill, sizeof buf);
    717   while (n) {
    718     size_t chunk = n > sizeof buf ? sizeof buf : (size_t)n;
    719     if (kit_writer_write(out, buf, chunk) != KIT_OK) return KIT_IO;
    720     n -= chunk;
    721   }
    722   return KIT_OK;
    723 }
    724 
    725 static KitStatus write_bytes(KitWriter* out, const uint8_t* data, size_t n) {
    726   return n ? kit_writer_write(out, data, n) : KIT_OK;
    727 }
    728 
    729 /* Resolve a requested Image-header kind (possibly AUTO) to a concrete arch from
    730  * the object's machine. */
    731 static KitStatus resolve_image_header(const KitContext* ctx, KitObjFile* obj,
    732                                       uint32_t want, KitImageHeader* out) {
    733   KitTargetSpec spec;
    734   if (want == KIT_IMAGE_HEADER_ARM64 || want == KIT_IMAGE_HEADER_RISCV) {
    735     *out = (KitImageHeader)want;
    736     return KIT_OK;
    737   }
    738   spec = kit_obj_target(obj);
    739   switch (spec.arch) {
    740     case KIT_ARCH_ARM_64:
    741       *out = KIT_IMAGE_HEADER_ARM64;
    742       return KIT_OK;
    743     case KIT_ARCH_RV64:
    744     case KIT_ARCH_RV32:
    745       *out = KIT_IMAGE_HEADER_RISCV;
    746       return KIT_OK;
    747     default:
    748       break;
    749   }
    750   kit_ctx_diagf(ctx, "image: --image-header could not infer the architecture; "
    751                      "pass --image-header=arm64 or =riscv");
    752   return KIT_INVALID;
    753 }
    754 
    755 /* Fill a 64-byte flat-kernel Image header. code0/code1 (the first 8 bytes of the
    756  * first loadable segment, i.e. the author's entry branch) are preserved; the
    757  * 56-byte metadata tail is synthesized deterministically. */
    758 static KitStatus build_image_header(const KitContext* ctx, KitImageHeader kind,
    759                                     const ImageRange* first,
    760                                     const KitImageReport* report,
    761                                     const KitImageOptions* opts,
    762                                     uint8_t hdr[64]) {
    763   uint64_t flags = 0;
    764   uint64_t text_offset =
    765       opts->have_image_text_offset ? opts->image_text_offset : 0;
    766 
    767   if (first->addr != report->base) {
    768     kit_ctx_diagf(ctx, "image: --image-header needs the first loadable segment "
    769                        "at the image base (no leading hole)");
    770     return KIT_INVALID;
    771   }
    772   if (first->size < 64) {
    773     kit_ctx_diagf(ctx, "image: --image-header needs the first loadable segment "
    774                        "to reserve a 64-byte header");
    775     return KIT_INVALID;
    776   }
    777 
    778   if (opts->image_big_endian) flags |= 1u;
    779   if (opts->image_page_size_kib) {
    780     if (kind != KIT_IMAGE_HEADER_ARM64) {
    781       kit_ctx_diagf(ctx,
    782                     "image: --image-page-size applies only to the arm64 header");
    783       return KIT_INVALID;
    784     }
    785     switch (opts->image_page_size_kib) {
    786       case 4:
    787         flags |= (uint64_t)1u << 1;
    788         break;
    789       case 16:
    790         flags |= (uint64_t)2u << 1;
    791         break;
    792       case 64:
    793         flags |= (uint64_t)3u << 1;
    794         break;
    795       default:
    796         kit_ctx_diagf(ctx,
    797                       "image: --image-page-size must be 4, 16, or 64 (KiB)");
    798         return KIT_INVALID;
    799     }
    800   }
    801 
    802   memset(hdr, 0, 64);
    803   memcpy(hdr, first->data, 8); /* code0/code1: preserve the entry branch */
    804   put_u64le(hdr + 8, text_offset);
    805   put_u64le(hdr + 16, report->mem_size);
    806   put_u64le(hdr + 24, flags);
    807   if (kind == KIT_IMAGE_HEADER_ARM64) {
    808     /* res2..res4 zero; magic "ARM\x64" at 56; PE-offset slot (60) zero. */
    809     hdr[56] = 0x41;
    810     hdr[57] = 0x52;
    811     hdr[58] = 0x4d;
    812     hdr[59] = 0x64;
    813   } else {
    814     /* version 2 at 32; reserved/deprecated-magic zero; magic2 "RSC\x05" at 56. */
    815     put_u32le(hdr + 32, 0x00000002u);
    816     hdr[56] = 0x52;
    817     hdr[57] = 0x53;
    818     hdr[58] = 0x43;
    819     hdr[59] = 0x05;
    820   }
    821   return KIT_OK;
    822 }
    823 
    824 static KitStatus write_layout(const KitContext* ctx, const ImageRange* ranges,
    825                               uint32_t nranges, const KitImageOptions* opts,
    826                               const KitImageReport* report,
    827                               const uint8_t* image_hdr, KitWriter* out) {
    828   uint64_t cur = report->base;
    829   uint32_t i;
    830   for (i = 0; i < nranges; ++i) {
    831     const ImageRange* r = &ranges[i];
    832     uint64_t hole = r->addr - cur;
    833     if (hole && write_fill(out, opts->fill, hole) != KIT_OK) {
    834       kit_ctx_diagf(ctx, "image: failed to write hole fill");
    835       return KIT_IO;
    836     }
    837     /* The synthesized header overlays the first 64 bytes of the first range
    838      * (validated >= 64 and at the base); the remaining bytes follow verbatim. */
    839     if (i == 0 && image_hdr) {
    840       if (write_bytes(out, image_hdr, 64) != KIT_OK ||
    841           write_bytes(out, r->data + 64, (size_t)(r->size - 64)) != KIT_OK) {
    842         kit_ctx_diagf(ctx, "image: failed to write header + segment bytes");
    843         return KIT_IO;
    844       }
    845       cur = r->end;
    846       continue;
    847     }
    848     if (write_bytes(out, r->data, (size_t)r->size) != KIT_OK) {
    849       kit_ctx_diagf(ctx, "image: failed to write segment bytes");
    850       return KIT_IO;
    851     }
    852     cur = r->end;
    853   }
    854   if (report->size > cur - report->base) {
    855     uint64_t pad = report->size - (cur - report->base);
    856     if (write_fill(out, opts->fill, pad) != KIT_OK) {
    857       kit_ctx_diagf(ctx, "image: failed to write trailing padding");
    858       return KIT_IO;
    859     }
    860   }
    861   return kit_writer_status(out);
    862 }
    863 
    864 static KitStatus check_32bit_text_image_range(const KitContext* ctx,
    865                                               const KitImageReport* report,
    866                                               const char* name) {
    867   if (report->base > UINT32_MAX ||
    868       report->size > ((uint64_t)UINT32_MAX + 1u) - report->base) {
    869     kit_ctx_diagf(ctx, "image: %s cannot emit above 32-bit addresses", name);
    870     return KIT_UNSUPPORTED;
    871   }
    872   return KIT_OK;
    873 }
    874 
    875 static KitStatus emit_ihex_ela_record(KitWriter* out, uint16_t upper) {
    876   uint8_t payload[2];
    877   char line[32];
    878   uint32_t sum;
    879   size_t n = 0;
    880 
    881   payload[0] = (uint8_t)(upper >> 8);
    882   payload[1] = (uint8_t)(upper & 0xffu);
    883   sum = 2u + 0u + 0u + 4u + payload[0] + payload[1];
    884 
    885   line[n++] = ':';
    886   line_append_hex_u8(line, &n, 2u);
    887   line_append_hex_u16(line, &n, 0u);
    888   line_append_hex_u8(line, &n, 4u);
    889   line_append_hex_u8(line, &n, payload[0]);
    890   line_append_hex_u8(line, &n, payload[1]);
    891   line_append_hex_u8(line, &n, (uint8_t)(~sum + 1u));
    892   line[n++] = '\n';
    893 
    894   return write_line(out, line, n);
    895 }
    896 
    897 static KitStatus emit_ihex_data_record(KitWriter* out, uint16_t addr,
    898                                        const uint8_t* data, size_t len) {
    899   uint32_t sum;
    900   size_t i;
    901   char line[64];
    902   size_t n = 0;
    903 
    904   if (len > KIT_IHEX_DATA_MAX || !len) return KIT_INVALID;
    905 
    906   sum = (uint32_t)len;
    907   sum += (uint32_t)(addr >> 8);
    908   sum += (uint32_t)(addr & 0xffu);
    909   sum += 0u;
    910   line[n++] = ':';
    911   line_append_hex_u8(line, &n, (uint8_t)len);
    912   line_append_hex_u16(line, &n, addr);
    913   line_append_hex_u8(line, &n, 0u);
    914   for (i = 0; i < len; ++i) {
    915     line_append_hex_u8(line, &n, data[i]);
    916     sum += data[i];
    917   }
    918   line_append_hex_u8(line, &n, (uint8_t)(~sum + 1u));
    919   line[n++] = '\n';
    920   return write_line(out, line, n);
    921 }
    922 
    923 static KitStatus emit_ihex_eof_record(KitWriter* out) {
    924   char line[16];
    925   size_t n = 0;
    926 
    927   line[n++] = ':';
    928   line_append_hex_u8(line, &n, 0u);
    929   line_append_hex_u16(line, &n, 0u);
    930   line_append_hex_u8(line, &n, 1u);
    931   line_append_hex_u8(line, &n, 0xffu);
    932   line[n++] = '\n';
    933   return write_line(out, line, n);
    934 }
    935 
    936 static KitStatus emit_ihex_start_record(KitWriter* out, uint32_t entry) {
    937   uint8_t payload[4];
    938   uint32_t sum;
    939   size_t i;
    940   char line[32];
    941   size_t n = 0;
    942 
    943   payload[0] = (uint8_t)(entry >> 24);
    944   payload[1] = (uint8_t)(entry >> 16);
    945   payload[2] = (uint8_t)(entry >> 8);
    946   payload[3] = (uint8_t)entry;
    947   sum = 4u + 5u;
    948 
    949   line[n++] = ':';
    950   line_append_hex_u8(line, &n, 4u);
    951   line_append_hex_u16(line, &n, 0u);
    952   line_append_hex_u8(line, &n, 5u);
    953   for (i = 0; i < sizeof payload; ++i) {
    954     line_append_hex_u8(line, &n, payload[i]);
    955     sum += payload[i];
    956   }
    957   line_append_hex_u8(line, &n, (uint8_t)(~sum + 1u));
    958   line[n++] = '\n';
    959   return write_line(out, line, n);
    960 }
    961 
    962 static KitStatus emit_ihex_blob(const KitContext* ctx, KitWriter* out,
    963                                uint64_t addr, const uint8_t* src,
    964                                uint64_t len, uint8_t fill, int as_fill,
    965                                uint16_t* current_upper) {
    966   uint8_t chunk[KIT_IHEX_DATA_MAX];
    967   uint16_t upper;
    968   uint32_t chunk_len;
    969   uint64_t at;
    970   KitStatus st;
    971 
    972   while (len) {
    973     if (addr > UINT32_MAX) {
    974       kit_ctx_diagf(ctx, "image: ihex cannot emit above 32-bit addresses");
    975       return KIT_UNSUPPORTED;
    976     }
    977     upper = (uint16_t)(addr >> 16);
    978     if (*current_upper != upper) {
    979       st = emit_ihex_ela_record(out, upper);
    980       if (st != KIT_OK) return st;
    981       *current_upper = upper;
    982     }
    983     at = addr & 0xffffu;
    984     chunk_len = (uint32_t)(0x10000ull - at);
    985     if (chunk_len > len) chunk_len = (uint32_t)len;
    986     if (chunk_len > KIT_IHEX_DATA_MAX) chunk_len = KIT_IHEX_DATA_MAX;
    987     if (as_fill) {
    988       memset(chunk, fill, (size_t)chunk_len);
    989     } else {
    990       memcpy(chunk, src, (size_t)chunk_len);
    991       src += chunk_len;
    992     }
    993     st = emit_ihex_data_record(out, (uint16_t)addr, chunk, (size_t)chunk_len);
    994     if (st != KIT_OK) return st;
    995     addr += chunk_len;
    996     len -= chunk_len;
    997   }
    998   return KIT_OK;
    999 }
   1000 
   1001 static KitStatus write_ihex_records(const KitContext* ctx, const ImageRange* ranges,
   1002                                    uint32_t nranges, const KitImageOptions* opts,
   1003                                    const KitImageReport* report,
   1004                                    KitWriter* out) {
   1005   uint64_t cur = report->base;
   1006   uint64_t pad = 0;
   1007   uint16_t current_upper = 0xffffu;
   1008   uint32_t i;
   1009   KitStatus st;
   1010 
   1011   for (i = 0; i < nranges; ++i) {
   1012     const ImageRange* r = &ranges[i];
   1013     uint64_t hole = r->addr - cur;
   1014     if (hole) {
   1015       st = emit_ihex_blob(ctx, out, cur, NULL, hole, opts->fill, 1,
   1016                           &current_upper);
   1017       if (st != KIT_OK) return st;
   1018     }
   1019     st = emit_ihex_blob(ctx, out, r->addr, r->data, r->size, 0, 0,
   1020                         &current_upper);
   1021     if (st != KIT_OK) return st;
   1022     cur = r->end;
   1023   }
   1024   if (report->size > cur - report->base) {
   1025     pad = report->size - (cur - report->base);
   1026     st = emit_ihex_blob(ctx, out, cur, NULL, pad, opts->fill, 1,
   1027                         &current_upper);
   1028     if (st != KIT_OK) return st;
   1029   }
   1030   if (report->has_entry) {
   1031     st = emit_ihex_start_record(out, (uint32_t)report->emitted_entry);
   1032     if (st != KIT_OK) return st;
   1033   }
   1034   return emit_ihex_eof_record(out);
   1035 }
   1036 
   1037 static KitStatus srec_data_type(const KitContext* ctx, uint64_t addr, char* type,
   1038                                uint32_t* addr_bytes) {
   1039   if (addr <= 0xffffu) {
   1040     *type = '1';
   1041     *addr_bytes = 2u;
   1042     return KIT_OK;
   1043   }
   1044   if (addr <= 0xffffffu) {
   1045     *type = '2';
   1046     *addr_bytes = 3u;
   1047     return KIT_OK;
   1048   }
   1049   if (addr <= 0xffffffffu) {
   1050     *type = '3';
   1051     *addr_bytes = 4u;
   1052     return KIT_OK;
   1053   }
   1054   kit_ctx_diagf(ctx,
   1055                 "image: srec cannot emit above 32-bit addresses (got 0x%llx)",
   1056                 (unsigned long long)addr);
   1057   return KIT_UNSUPPORTED;
   1058 }
   1059 
   1060 static KitStatus emit_srec_data_record(KitWriter* out, char type, uint32_t addr_bytes,
   1061                                       uint64_t addr, const uint8_t* data,
   1062                                       size_t len) {
   1063   uint8_t sum;
   1064   size_t i;
   1065   char line[128];
   1066   size_t n = 0;
   1067   uint8_t count;
   1068 
   1069   if (addr_bytes < 2u || addr_bytes > 4u) return KIT_INVALID;
   1070   if (len > KIT_SREC_DATA_MAX) return KIT_INVALID;
   1071   if (!data && len != 0u) return KIT_INVALID;
   1072 
   1073   count = (uint8_t)(addr_bytes + len + 1u);
   1074   sum = count;
   1075 
   1076   line[n++] = 'S';
   1077   line[n++] = (char)type;
   1078   line_append_hex_u8(line, &n, count);
   1079   line_append_hex_u64_be(line, &n, addr, addr_bytes);
   1080   for (i = 0; i < addr_bytes; ++i) {
   1081     sum += (uint8_t)(addr >> (8u * (addr_bytes - 1u - i)));
   1082   }
   1083   if (data) {
   1084     for (i = 0; i < len; ++i) {
   1085       line_append_hex_u8(line, &n, data[i]);
   1086       sum += data[i];
   1087     }
   1088   }
   1089   line_append_hex_u8(line, &n, (uint8_t)(~sum));
   1090   line[n++] = '\n';
   1091   return write_line(out, line, n);
   1092 }
   1093 
   1094 static KitStatus emit_srec_blob(const KitContext* ctx, KitWriter* out, uint64_t addr,
   1095                                const uint8_t* src, uint64_t len, uint8_t fill,
   1096                                int as_fill) {
   1097   uint8_t chunk[KIT_SREC_DATA_MAX];
   1098   size_t chunk_len_u;
   1099   uint64_t chunk_len;
   1100   uint64_t block_size;
   1101   uint64_t at;
   1102   char type;
   1103   uint32_t addr_bytes;
   1104   KitStatus st;
   1105 
   1106   while (len) {
   1107     st = srec_data_type(ctx, addr, &type, &addr_bytes);
   1108     if (st != KIT_OK) return st;
   1109     at = addr & (((uint64_t)1u << (addr_bytes * 8u)) - 1u);
   1110     block_size = (uint64_t)1u << (addr_bytes * 8u);
   1111     chunk_len = block_size - at;
   1112     if (chunk_len > len) chunk_len = len;
   1113     if (chunk_len > KIT_SREC_DATA_MAX) chunk_len = KIT_SREC_DATA_MAX;
   1114     chunk_len_u = (size_t)chunk_len;
   1115     if (as_fill) {
   1116       memset(chunk, fill, chunk_len_u);
   1117     } else {
   1118       memcpy(chunk, src, chunk_len_u);
   1119       src += chunk_len_u;
   1120     }
   1121     st = emit_srec_data_record(out, type, addr_bytes, addr, chunk, chunk_len_u);
   1122     if (st != KIT_OK) return st;
   1123     addr += chunk_len;
   1124     len -= chunk_len;
   1125   }
   1126   return KIT_OK;
   1127 }
   1128 
   1129 static char srec_start_type(uint64_t addr) {
   1130   if (addr <= 0xffffu) return '9';
   1131   if (addr <= 0xffffffu) return '8';
   1132   return '7';
   1133 }
   1134 
   1135 static uint32_t srec_start_addr_bytes(uint64_t addr) {
   1136   if (addr <= 0xffffu) return 2u;
   1137   if (addr <= 0xffffffu) return 3u;
   1138   return 4u;
   1139 }
   1140 
   1141 static KitStatus write_srec_records(const KitContext* ctx, const ImageRange* ranges,
   1142                                    uint32_t nranges, const KitImageOptions* opts,
   1143                                    const KitImageReport* report,
   1144                                    KitWriter* out) {
   1145   const uint8_t header_name[] = "KIT";
   1146   uint64_t cur;
   1147   uint64_t pad = 0;
   1148   uint32_t i;
   1149   KitStatus st;
   1150 
   1151   if (emit_srec_data_record(out, '0', 2u, 0u, header_name,
   1152                            sizeof(header_name) - 1u) != KIT_OK) {
   1153     return KIT_IO;
   1154   }
   1155 
   1156   if (nranges == 0) return KIT_NOT_FOUND;
   1157   cur = report->base;
   1158   for (i = 0; i < nranges; ++i) {
   1159     const ImageRange* r = &ranges[i];
   1160     uint64_t hole = r->addr - cur;
   1161     if (hole) {
   1162       st = emit_srec_blob(ctx, out, cur, NULL, hole, opts->fill, 1);
   1163       if (st != KIT_OK) return st;
   1164     }
   1165     st = emit_srec_blob(ctx, out, r->addr, r->data, r->size, 0u, 0);
   1166     if (st != KIT_OK) return st;
   1167     cur = r->end;
   1168   }
   1169   if (report->size > cur - report->base) {
   1170     pad = report->size - (cur - report->base);
   1171     st = emit_srec_blob(ctx, out, cur, NULL, pad, opts->fill, 1);
   1172     if (st != KIT_OK) return st;
   1173   }
   1174   if (report->has_entry) {
   1175     uint64_t entry = report->emitted_entry;
   1176     if (emit_srec_data_record(out, srec_start_type(entry),
   1177                              srec_start_addr_bytes(entry), entry, NULL, 0u) !=
   1178         KIT_OK) {
   1179       return KIT_IO;
   1180     }
   1181   }
   1182   return KIT_OK;
   1183 }
   1184 
   1185 /* Validation pass: --require-entry / --require-symbol / --require-section /
   1186  * --no-dynamic. Runs against the opened object before any bytes are written. */
   1187 static KitStatus validate_object(const KitContext* ctx, KitObjFile* obj,
   1188                                  const KitImageOptions* opts) {
   1189   uint32_t i;
   1190 
   1191   if (opts->require_entry) {
   1192     KitObjImageInfo info;
   1193     if (kit_obj_image_info(obj, &info) != KIT_OK || info.entry == 0) {
   1194       kit_ctx_diagf(ctx, "image: --require-entry: input declares no entry point");
   1195       return KIT_NOT_FOUND;
   1196     }
   1197   }
   1198 
   1199   for (i = 0; i < opts->nrequire_sections; ++i) {
   1200     KitObjSection sid = KIT_SECTION_NONE;
   1201     KitSlice want = opts->require_sections[i];
   1202     if (kit_obj_section_by_name(obj, want, &sid) != KIT_OK ||
   1203         sid == KIT_SECTION_NONE) {
   1204       kit_ctx_diagf(ctx, "image: --require-section: %.*s not found",
   1205                     KIT_SLICE_ARG(want));
   1206       return KIT_NOT_FOUND;
   1207     }
   1208   }
   1209 
   1210   for (i = 0; i < opts->nrequire_symbols; ++i) {
   1211     KitObjSymInfo si;
   1212     KitSlice want = opts->require_symbols[i];
   1213     if (kit_obj_symbol_by_name(obj, want, &si) != KIT_OK) {
   1214       /* Fall back to the dynamic symbol table for stripped linked images. */
   1215       KitObjSymIter* dit = NULL;
   1216       int found = 0;
   1217       if (kit_obj_dynsymiter_new(obj, &dit) == KIT_OK) {
   1218         KitObjSymInfo di;
   1219         while (kit_obj_symiter_next(dit, &di) == KIT_ITER_ITEM) {
   1220           if (slice_eq(di.name, want)) {
   1221             found = 1;
   1222             break;
   1223           }
   1224         }
   1225         kit_obj_symiter_free(dit);
   1226       }
   1227       if (!found) {
   1228         kit_ctx_diagf(ctx, "image: --require-symbol: %.*s not found",
   1229                       KIT_SLICE_ARG(want));
   1230         return KIT_NOT_FOUND;
   1231       }
   1232     }
   1233   }
   1234 
   1235   if (opts->no_dynamic) {
   1236     KitObjImageInfo info;
   1237     KitObjDepIter* dep = NULL;
   1238     KitObjDepInfo di;
   1239     int has_dep = 0;
   1240     KitObjSection sid = KIT_SECTION_NONE;
   1241     static const char* dyn_secs[] = {".dynamic", ".interp", ".plt",
   1242                                      ".got.plt", ".got",     ".dynsym"};
   1243     size_t k;
   1244 
   1245     if (kit_obj_image_info(obj, &info) == KIT_OK && info.interp.len) {
   1246       kit_ctx_diagf(ctx,
   1247                     "image: --no-dynamic: input has a dynamic interpreter %.*s",
   1248                     KIT_SLICE_ARG(info.interp));
   1249       return KIT_ERR;
   1250     }
   1251     if (kit_obj_depiter_new(obj, &dep) == KIT_OK) {
   1252       if (kit_obj_depiter_next(dep, &di) == KIT_ITER_ITEM) has_dep = 1;
   1253       kit_obj_depiter_free(dep);
   1254     }
   1255     if (has_dep) {
   1256       kit_ctx_diagf(ctx,
   1257                     "image: --no-dynamic: input depends on a shared library");
   1258       return KIT_ERR;
   1259     }
   1260     for (k = 0; k < sizeof(dyn_secs) / sizeof(dyn_secs[0]); ++k) {
   1261       if (kit_obj_section_by_name(obj, kit_slice_cstr(dyn_secs[k]), &sid) ==
   1262               KIT_OK &&
   1263           sid != KIT_SECTION_NONE) {
   1264         kit_ctx_diagf(ctx,
   1265                       "image: --no-dynamic: input has a dynamic section %s",
   1266                       dyn_secs[k]);
   1267         return KIT_ERR;
   1268       }
   1269     }
   1270   }
   1271 
   1272   return KIT_OK;
   1273 }
   1274 
   1275 KitStatus obj_emit_image(const KitContext* ctx, KitObjFile* obj,
   1276                          const KitSlice* object_bytes,
   1277                          const KitImageOptions* opts, KitWriter* out,
   1278                          KitImageReport* report_out) {
   1279   KitImageOptions defopts;
   1280   KitImageReport report;
   1281   ImageRange* ranges = NULL;
   1282   uint32_t nranges = 0, cap = 0;
   1283   KitImageFormat format;
   1284   KitStatus st;
   1285   int from_sections;
   1286   int address_sections;
   1287   uint64_t seg_mem_end = 0;
   1288   uint8_t image_hdr[64];
   1289   const uint8_t* image_hdr_p = NULL;
   1290 
   1291   if (!ctx || !ctx->heap || !obj || !object_bytes || !out) return KIT_INVALID;
   1292   if (!object_bytes->data && object_bytes->len) return KIT_INVALID;
   1293 
   1294   if (!opts) {
   1295     memset(&defopts, 0, sizeof defopts);
   1296     defopts.format = KIT_IMAGE_FORMAT_BIN;
   1297     defopts.from = KIT_IMAGE_FROM_SEGMENTS;
   1298     defopts.addr = KIT_IMAGE_ADDR_VADDR;
   1299     defopts.fill = 0;
   1300     opts = &defopts;
   1301   }
   1302 
   1303   format = (KitImageFormat)opts->format;
   1304   if (format != KIT_IMAGE_FORMAT_BIN && format != KIT_IMAGE_FORMAT_ROM &&
   1305       format != KIT_IMAGE_FORMAT_SECTIONS && format != KIT_IMAGE_FORMAT_IHEX &&
   1306       format != KIT_IMAGE_FORMAT_SREC && format != KIT_IMAGE_FORMAT_ELF) {
   1307     kit_ctx_diagf(ctx, "image: unknown output format");
   1308     return KIT_INVALID;
   1309   }
   1310   if (format == KIT_IMAGE_FORMAT_ELF) {
   1311     kit_ctx_diagf(ctx,
   1312                   "image: --format elf is not implemented; use `kit objcopy` "
   1313                   "/ `kit strip` to copy, normalize, or strip a linked ELF");
   1314     return KIT_UNSUPPORTED;
   1315   }
   1316   if (opts->have_base &&
   1317       (format == KIT_IMAGE_FORMAT_IHEX || format == KIT_IMAGE_FORMAT_SREC)) {
   1318     kit_ctx_diagf(ctx,
   1319                   "image: --base is only valid for flat output; use --bias "
   1320                   "to rebase ihex/srec addresses");
   1321     return KIT_INVALID;
   1322   }
   1323   if (opts->from != KIT_IMAGE_FROM_SEGMENTS &&
   1324       opts->from != KIT_IMAGE_FROM_SECTIONS) {
   1325     kit_ctx_diagf(ctx, "image: invalid --from source");
   1326     return KIT_INVALID;
   1327   }
   1328   if (opts->addr != KIT_IMAGE_ADDR_VADDR &&
   1329       opts->addr != KIT_IMAGE_ADDR_PADDR && opts->addr != KIT_IMAGE_ADDR_LMA) {
   1330     kit_ctx_diagf(ctx, "image: invalid address kind");
   1331     return KIT_INVALID;
   1332   }
   1333   if (opts->nsegments && !opts->segments) {
   1334     kit_ctx_diagf(ctx, "image: segment list is missing");
   1335     return KIT_INVALID;
   1336   }
   1337   if (opts->have_align && opts->align == 0) {
   1338     kit_ctx_diagf(ctx, "image: --align must be non-zero");
   1339     return KIT_INVALID;
   1340   }
   1341 
   1342   /* Source selection. Five formats, two byte sources:
   1343    *   bin/srec/ihex     : linked load segments, or allocated sections for a
   1344    *                       relocatable input / explicit section filters.
   1345    *   rom               : load segments by default, or named sections when a
   1346    *                       --section list (or --from sections) is supplied.
   1347    *   sections          : named sections only (the format IS the concatenation).
   1348    * --section is the section-order list; it implies the section source for the
   1349    * formats that allow it and is rejected for bin / ihex / srec. */
   1350   if ((format == KIT_IMAGE_FORMAT_BIN || format == KIT_IMAGE_FORMAT_IHEX ||
   1351        format == KIT_IMAGE_FORMAT_SREC) &&
   1352       opts->nsection_order) {
   1353     kit_ctx_diagf(ctx,
   1354                   "image: --section is only valid with --format sections or "
   1355                   "--format rom");
   1356     return KIT_INVALID;
   1357   }
   1358   if ((format == KIT_IMAGE_FORMAT_BIN || format == KIT_IMAGE_FORMAT_IHEX ||
   1359        format == KIT_IMAGE_FORMAT_SREC) &&
   1360       opts->from == KIT_IMAGE_FROM_SECTIONS) {
   1361     kit_ctx_diagf(ctx,
   1362                   "image: --from sections requires --format sections or rom");
   1363     return KIT_INVALID;
   1364   }
   1365   from_sections = (format == KIT_IMAGE_FORMAT_SECTIONS) ||
   1366                   (opts->from == KIT_IMAGE_FROM_SECTIONS) ||
   1367                   (format == KIT_IMAGE_FORMAT_ROM && opts->nsection_order > 0);
   1368   if (from_sections && opts->nsection_order == 0) {
   1369     kit_ctx_diagf(ctx,
   1370                   "image: a section source requires at least one --section "
   1371                   "NAME");
   1372     return KIT_INVALID;
   1373   }
   1374   if (format == KIT_IMAGE_FORMAT_ROM && !opts->have_pad_to) {
   1375     kit_ctx_diagf(ctx,
   1376                   "image: --format rom requires an explicit size via --pad-to");
   1377     return KIT_INVALID;
   1378   }
   1379   if (opts->image_header != KIT_IMAGE_HEADER_NONE) {
   1380     if (format != KIT_IMAGE_FORMAT_BIN && format != KIT_IMAGE_FORMAT_ROM) {
   1381       kit_ctx_diagf(ctx, "image: --image-header requires --format bin or rom");
   1382       return KIT_INVALID;
   1383     }
   1384     if (from_sections) {
   1385       kit_ctx_diagf(
   1386           ctx, "image: --image-header is incompatible with a section source");
   1387       return KIT_INVALID;
   1388     }
   1389   }
   1390 
   1391   st = validate_object(ctx, obj, opts);
   1392   if (st != KIT_OK) return st;
   1393 
   1394   address_sections = !from_sections &&
   1395                      (kit_obj_kind(obj) == KIT_OBJ_KIND_REL ||
   1396                       opts->nonly_sections || opts->nremove_sections);
   1397   if (from_sections) {
   1398     st = collect_sections(ctx, obj, opts, &ranges, &nranges, &cap, &seg_mem_end);
   1399   } else if (address_sections) {
   1400     st = collect_alloc_sections(ctx, obj, opts, &ranges, &nranges, &cap,
   1401                                 &seg_mem_end);
   1402   } else {
   1403     st = collect_ranges(ctx, obj, object_bytes, opts, &ranges, &nranges, &cap,
   1404                         &seg_mem_end);
   1405   }
   1406   if (st == KIT_OK && !from_sections) {
   1407     ImageRange* normalized = NULL;
   1408     uint32_t nnormalized = 0, normalized_cap = 0;
   1409     st = normalize_overlaps(ctx, ranges, nranges, &normalized, &nnormalized,
   1410                             &normalized_cap);
   1411     if (st == KIT_OK) {
   1412       ranges_free(ctx, ranges, cap);
   1413       ranges = normalized;
   1414       nranges = nnormalized;
   1415       cap = normalized_cap;
   1416     }
   1417   }
   1418   if (st == KIT_OK) {
   1419     KitObjImageInfo info;
   1420     memset(&report, 0, sizeof report);
   1421     report.sections_concat = from_sections ? true : false;
   1422     report.section_ranges = address_sections ? true : false;
   1423     report.base_is_load_address =
   1424         (!from_sections && !address_sections) ? true : false;
   1425     if (!from_sections) report.original_base = ranges[0].original_addr;
   1426     st = compute_layout(ctx, ranges, nranges, opts, seg_mem_end, &report);
   1427     if (st == KIT_OK) {
   1428       report.emitted_base = report.base;
   1429       if (kit_obj_kind(obj) != KIT_OBJ_KIND_REL &&
   1430           kit_obj_image_info(obj, &info) == KIT_OK && info.entry != 0) {
   1431         report.has_entry = true;
   1432         report.original_entry = info.entry;
   1433         if (!u64_add_bias(info.entry, opts->bias, &report.emitted_entry)) {
   1434           kit_ctx_diagf(ctx, "image: entry address overflows after --bias");
   1435           st = KIT_INVALID;
   1436         }
   1437       }
   1438     }
   1439   }
   1440   if (st == KIT_OK && opts->image_header != KIT_IMAGE_HEADER_NONE) {
   1441     KitImageHeader kind;
   1442     st = resolve_image_header(ctx, obj, opts->image_header, &kind);
   1443     if (st == KIT_OK)
   1444       st = build_image_header(ctx, kind, &ranges[0], &report, opts, image_hdr);
   1445     if (st == KIT_OK) {
   1446       image_hdr_p = image_hdr;
   1447       report.image_header = (uint32_t)kind;
   1448     }
   1449   }
   1450   if (st == KIT_OK) {
   1451     if (format == KIT_IMAGE_FORMAT_IHEX) {
   1452       st = check_32bit_text_image_range(ctx, &report, "ihex");
   1453       if (st == KIT_OK && report.has_entry &&
   1454           report.emitted_entry > UINT32_MAX) {
   1455         kit_ctx_diagf(ctx,
   1456                       "image: ihex entry cannot emit above 32-bit addresses");
   1457         st = KIT_UNSUPPORTED;
   1458       }
   1459       if (st == KIT_OK)
   1460         st = write_ihex_records(ctx, ranges, nranges, opts, &report, out);
   1461     } else if (format == KIT_IMAGE_FORMAT_SREC) {
   1462       st = check_32bit_text_image_range(ctx, &report, "srec");
   1463       if (st == KIT_OK && report.has_entry &&
   1464           report.emitted_entry > UINT32_MAX) {
   1465         kit_ctx_diagf(ctx,
   1466                       "image: srec entry cannot emit above 32-bit addresses");
   1467         st = KIT_UNSUPPORTED;
   1468       }
   1469       if (st == KIT_OK)
   1470         st = write_srec_records(ctx, ranges, nranges, opts, &report, out);
   1471     } else {
   1472       st = write_layout(ctx, ranges, nranges, opts, &report, image_hdr_p, out);
   1473     }
   1474   }
   1475   if (st == KIT_OK && report_out) *report_out = report;
   1476   ranges_free(ctx, ranges, cap);
   1477   return st;
   1478 }