kit

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

align_4k.c (4963B)


      1 /* Hand-built KitObjBuilder roundtrip — verifies large sh_addralign.
      2  *
      3  * Builds an ELF with a .text section aligned to 4096 (page size),
      4  * emits and reads it back, asserts the align field round-trips.
      5  * Clang doesn't emit such large alignments naturally for .o files,
      6  * so this gap can only be covered by a hand-built case. */
      7 
      8 #include <kit/core.h>
      9 #include <kit/object.h>
     10 #include <stdarg.h>
     11 #include <stdio.h>
     12 #include <stdlib.h>
     13 #include <string.h>
     14 
     15 #include "lib/kit_test_target.h"
     16 
     17 static void* heap_alloc(KitHeap* h, size_t n, size_t a) {
     18   (void)h;
     19   (void)a;
     20   return n ? malloc(n) : NULL;
     21 }
     22 static void* heap_realloc(KitHeap* h, void* p, size_t o, size_t n, size_t a) {
     23   (void)h;
     24   (void)o;
     25   (void)a;
     26   return realloc(p, n);
     27 }
     28 static void heap_free(KitHeap* h, void* p, size_t n) {
     29   (void)h;
     30   (void)n;
     31   free(p);
     32 }
     33 static KitHeap g_heap = {heap_alloc, heap_realloc, heap_free, NULL};
     34 
     35 static void diag_emit(KitDiagSink* s, KitDiagKind k, KitSrcLoc loc,
     36                       const char* fmt, va_list ap) {
     37   static const char* names[] = {"note", "warning", "error", "fatal"};
     38   (void)s;
     39   (void)loc;
     40   fprintf(stderr, "%s: ", names[k]);
     41   vfprintf(stderr, fmt, ap);
     42   fputc('\n', stderr);
     43 }
     44 static KitDiagSink g_diag = {diag_emit, NULL, 0, 0};
     45 
     46 static int g_failures;
     47 #define CHECK(cond, ...)                                   \
     48   do {                                                     \
     49     if (!(cond)) {                                         \
     50       fprintf(stderr, "FAIL %s:%d: ", __FILE__, __LINE__); \
     51       fprintf(stderr, __VA_ARGS__);                        \
     52       fputc('\n', stderr);                                 \
     53       g_failures++;                                        \
     54     }                                                      \
     55   } while (0)
     56 
     57 /* mov w0, #0 ; ret */
     58 static const uint8_t TEXT_BYTES[8] = {
     59     0x00, 0x00, 0x80, 0x52, 0xc0, 0x03, 0x5f, 0xd6,
     60 };
     61 
     62 #define WANT_ALIGN 4096u
     63 
     64 int main(void) {
     65   KitTargetSpec target;
     66   if (kit_test_target_init(&target) != 0) {
     67     fprintf(stderr, "FAIL: kit_test_target_init\n");
     68     return 1;
     69   }
     70 
     71   KitContext ctx = {.heap = &g_heap,
     72                     .file_io = NULL,
     73                     .diag = &g_diag,
     74                     .metrics = NULL,
     75                     .now = -1};
     76   KitTargetOptions target_opts;
     77   memset(&target_opts, 0, sizeof target_opts);
     78   target_opts.spec = target;
     79   KitTarget* kt = NULL;
     80   if (kit_target_new(&ctx, &target_opts, &kt) != KIT_OK || !kt) {
     81     fprintf(stderr, "FAIL: kit_target_new\n");
     82     return 1;
     83   }
     84   KitCompiler* cc = NULL;
     85   if (kit_compiler_new(kt, &ctx, &cc) != KIT_OK || !cc) {
     86     fprintf(stderr, "FAIL: kit_compiler_new\n");
     87     kit_target_free(kt);
     88     return 1;
     89   }
     90   KitObjBuilder* in = NULL;
     91   CHECK(kit_obj_builder_new(cc, &in) == KIT_OK && in, "kit_obj_builder_new");
     92 
     93   KitObjSection sec = KIT_SECTION_NONE;
     94   KitObjSectionDesc text_desc = {
     95       .name = kit_sym_intern(cc, KIT_SLICE_LIT(".text")),
     96       .kind = KIT_SEC_TEXT,
     97       .flags = KIT_SF_ALLOC | KIT_SF_EXEC,
     98       .align = WANT_ALIGN,
     99       .entsize = 0,
    100   };
    101   CHECK(kit_obj_builder_section(in, &text_desc, &sec) == KIT_OK,
    102         "section .text");
    103   CHECK(kit_obj_builder_write(in, sec, TEXT_BYTES, sizeof TEXT_BYTES) == KIT_OK,
    104         "write .text");
    105   KitObjSymbol sym_f = KIT_OBJ_SYMBOL_NONE;
    106   KitObjSymbolDesc f_desc = {
    107       .name = kit_sym_intern(cc, KIT_SLICE_LIT("f")),
    108       .bind = KIT_SB_GLOBAL,
    109       .kind = KIT_SK_FUNC,
    110       .section = sec,
    111       .value = 0,
    112       .size = sizeof TEXT_BYTES,
    113   };
    114   CHECK(kit_obj_builder_symbol(in, &f_desc, &sym_f) == KIT_OK, "symbol f");
    115   CHECK(kit_obj_builder_finalize(in) == KIT_OK, "finalize");
    116 
    117   KitWriter* w = NULL;
    118   (void)kit_writer_mem(&g_heap, &w);
    119   CHECK(kit_obj_builder_emit(in, w) == KIT_OK, "emit");
    120   size_t out_len = 0;
    121   const uint8_t* out_data = kit_writer_mem_bytes(w, &out_len);
    122   uint8_t* roundtrip = (uint8_t*)malloc(out_len);
    123   memcpy(roundtrip, out_data, out_len);
    124   kit_writer_close(w);
    125 
    126   KitSlice input = {.data = roundtrip, .len = out_len};
    127   KitObjFile* back = NULL;
    128   CHECK(
    129       kit_obj_open(&ctx, KIT_SLICE_LIT("align_4k"), &input, &back) == KIT_OK &&
    130           back,
    131       "kit_obj_open failed");
    132 
    133   /* Locate .text by name. */
    134   int found = 0;
    135   if (back) {
    136     KitObjSection text = KIT_SECTION_NONE;
    137     if (kit_obj_section_by_name(back, KIT_SLICE_LIT(".text"), &text) ==
    138         KIT_OK) {
    139       KitObjSecInfo si;
    140       CHECK(kit_obj_section(back, text, &si) == KIT_OK, "section info .text");
    141       found = 1;
    142       CHECK(si.align == WANT_ALIGN, ".text align=%u after roundtrip, want %u",
    143             si.align, WANT_ALIGN);
    144     }
    145   }
    146   CHECK(found, ".text not present after roundtrip");
    147 
    148   if (back) kit_obj_free(back);
    149   free(roundtrip);
    150   kit_obj_builder_free(in);
    151   kit_compiler_free(cc);
    152   kit_target_free(kt);
    153 
    154   if (g_failures) {
    155     fprintf(stderr, "%d failure(s)\n", g_failures);
    156     return 1;
    157   }
    158   fputs("align_4k: OK\n", stderr);
    159   return 0;
    160 }