kit

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

link_image_id.c (2060B)


      1 /* link_image_id_compute: format-agnostic 16-byte identity hash for a
      2  * resolved LinkImage.
      3  *
      4  * A single SHA-256 stream is fed each segment's vaddr, file_size, and
      5  * post-shift bytes, so the digest changes if either content or layout
      6  * shifts.  The 16-byte image id is the first half of the 32-byte digest.
      7  * The SHA-256 core uses the AArch64 crypto extension where the host has
      8  * it (the same hardware path that hashes the Mach-O code signature), so
      9  * the per-byte fold is far cheaper than the old twin-FNV mix — this was
     10  * the residual top frame on pathologically large links.  Determinism (no
     11  * time / random component) is intentional — reproducible builds.
     12  *
     13  * Wrapped per format:
     14  *   - ELF      .note.gnu.build-id (link_emit_elf)
     15  *   - Mach-O   LC_UUID payload    (link_emit_macho, Phase 3)
     16  *   - COFF/PE  debug directory    (deferred)
     17  *
     18  * Lived in link_elf.c through Phase 0; lifted out so the Mach-O writer
     19  * sees the same bytes. */
     20 
     21 #include "core/core.h"
     22 #include "core/sha256.h"
     23 #include "link/link_internal.h"
     24 
     25 /* sha256_update takes a u32 length; feed large segments in chunks so a
     26  * >4 GiB segment can never truncate the stream. */
     27 static void image_id_update(Sha256* s, const u8* data, size_t n) {
     28   while (n) {
     29     u32 chunk = n > 0x40000000u ? 0x40000000u : (u32)n;
     30     sha256_update(s, data, chunk);
     31     data += chunk;
     32     n -= chunk;
     33   }
     34 }
     35 
     36 void link_image_id_compute(const LinkImage* img, u8 out[LINK_IMAGE_ID_BYTES]) {
     37   Sha256 s;
     38   sha256_init(&s);
     39   u32 i;
     40   for (i = 0; i < img->nsegments; ++i) {
     41     const LinkSegment* seg = &img->segments[i];
     42     u64 vaddr = seg->vaddr;
     43     u64 fsz = seg->file_size;
     44     sha256_update(&s, (const u8*)&vaddr, (u32)sizeof vaddr);
     45     sha256_update(&s, (const u8*)&fsz, (u32)sizeof fsz);
     46     if (img->segment_bytes[i] && fsz)
     47       image_id_update(&s, img->segment_bytes[i], (size_t)fsz);
     48   }
     49   u8 digest[SHA256_DIGEST_LEN];
     50   sha256_final(&s, digest);
     51   /* Image id is the first 16 bytes of the 256-bit digest. */
     52   for (i = 0; i < LINK_IMAGE_ID_BYTES; ++i) out[i] = digest[i];
     53 }