align_4k.c (4926B)
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 .now = -1}; 75 KitTargetOptions target_opts; 76 memset(&target_opts, 0, sizeof target_opts); 77 target_opts.spec = target; 78 KitTarget* kt = NULL; 79 if (kit_target_new(&ctx, &target_opts, &kt) != KIT_OK || !kt) { 80 fprintf(stderr, "FAIL: kit_target_new\n"); 81 return 1; 82 } 83 KitCompiler* cc = NULL; 84 if (kit_compiler_new(kt, &ctx, &cc) != KIT_OK || !cc) { 85 fprintf(stderr, "FAIL: kit_compiler_new\n"); 86 kit_target_free(kt); 87 return 1; 88 } 89 KitObjBuilder* in = NULL; 90 CHECK(kit_obj_builder_new(cc, &in) == KIT_OK && in, "kit_obj_builder_new"); 91 92 KitObjSection sec = KIT_SECTION_NONE; 93 KitObjSectionDesc text_desc = { 94 .name = kit_sym_intern(cc, KIT_SLICE_LIT(".text")), 95 .kind = KIT_SEC_TEXT, 96 .flags = KIT_SF_ALLOC | KIT_SF_EXEC, 97 .align = WANT_ALIGN, 98 .entsize = 0, 99 }; 100 CHECK(kit_obj_builder_section(in, &text_desc, &sec) == KIT_OK, 101 "section .text"); 102 CHECK(kit_obj_builder_write(in, sec, TEXT_BYTES, sizeof TEXT_BYTES) == KIT_OK, 103 "write .text"); 104 KitObjSymbol sym_f = KIT_OBJ_SYMBOL_NONE; 105 KitObjSymbolDesc f_desc = { 106 .name = kit_sym_intern(cc, KIT_SLICE_LIT("f")), 107 .bind = KIT_SB_GLOBAL, 108 .kind = KIT_SK_FUNC, 109 .section = sec, 110 .value = 0, 111 .size = sizeof TEXT_BYTES, 112 }; 113 CHECK(kit_obj_builder_symbol(in, &f_desc, &sym_f) == KIT_OK, "symbol f"); 114 CHECK(kit_obj_builder_finalize(in) == KIT_OK, "finalize"); 115 116 KitWriter* w = NULL; 117 (void)kit_writer_mem(&g_heap, &w); 118 CHECK(kit_obj_builder_emit(in, w) == KIT_OK, "emit"); 119 size_t out_len = 0; 120 const uint8_t* out_data = kit_writer_mem_bytes(w, &out_len); 121 uint8_t* roundtrip = (uint8_t*)malloc(out_len); 122 memcpy(roundtrip, out_data, out_len); 123 kit_writer_close(w); 124 125 KitSlice input = {.data = roundtrip, .len = out_len}; 126 KitObjFile* back = NULL; 127 CHECK( 128 kit_obj_open(&ctx, KIT_SLICE_LIT("align_4k"), &input, &back) == KIT_OK && 129 back, 130 "kit_obj_open failed"); 131 132 /* Locate .text by name. */ 133 int found = 0; 134 if (back) { 135 KitObjSection text = KIT_SECTION_NONE; 136 if (kit_obj_section_by_name(back, KIT_SLICE_LIT(".text"), &text) == 137 KIT_OK) { 138 KitObjSecInfo si; 139 CHECK(kit_obj_section(back, text, &si) == KIT_OK, "section info .text"); 140 found = 1; 141 CHECK(si.align == WANT_ALIGN, ".text align=%u after roundtrip, want %u", 142 si.align, WANT_ALIGN); 143 } 144 } 145 CHECK(found, ".text not present after roundtrip"); 146 147 if (back) kit_obj_free(back); 148 free(roundtrip); 149 kit_obj_builder_free(in); 150 kit_compiler_free(cc); 151 kit_target_free(kt); 152 153 if (g_failures) { 154 fprintf(stderr, "%d failure(s)\n", g_failures); 155 return 1; 156 } 157 fputs("align_4k: OK\n", stderr); 158 return 0; 159 }