kit

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

commit b8dcd8a7bdd3f2ce01756fd8ce410d64786424de
parent 11895ae0ea7cc7f8fc16664bae5d2fff4aa87c1d
Author: Ryan Sepassi <rsepassi@gmail.com>
Date:   Thu,  4 Jun 2026 16:41:30 -0700

coff: emit PE exception directory metadata

Diffstat:
Msrc/obj/coff/link.c | 29++++++++++++++++++++++++-----
1 file changed, 24 insertions(+), 5 deletions(-)

diff --git a/src/obj/coff/link.c b/src/obj/coff/link.c @@ -118,8 +118,9 @@ typedef enum CoffBucket { COFF_BUCKET_DATA = 3, COFF_BUCKET_TLS = 4, COFF_BUCKET_BSS = 5, - COFF_BUCKET_RELOC = 6, - COFF_NBUCKETS = 7, + COFF_BUCKET_PDATA = 6, + COFF_BUCKET_RELOC = 7, + COFF_NBUCKETS = 8, } CoffBucket; /* IMAGE_TLS_DIRECTORY64 wire size: u64*4 + u32*2 = 40 bytes. */ @@ -160,7 +161,12 @@ static void coff_write_zeroes(Writer* w, u64 n) { * code resolve against the merged TLS image, not against .data. * Everything else partitions on SF_EXEC / SF_WRITE plus the SSEM_NOBITS * bit for .bss. */ -static CoffBucket coff_bucket_for(const LinkSection* ls) { +static CoffBucket coff_bucket_for(Compiler* c, const LinkSection* ls) { + if (ls->name) { + Slice nm = pool_slice(c->global, ls->name); + if (nm.s && nm.len >= 6u && memcmp(nm.s, ".pdata", 6u) == 0) + return COFF_BUCKET_PDATA; + } if (ls->flags & SF_EXEC) return COFF_BUCKET_TEXT; if (ls->flags & SF_TLS) return COFF_BUCKET_TLS; if (ls->sem == SSEM_NOBITS) return COFF_BUCKET_BSS; @@ -901,7 +907,7 @@ static void coff_place_section(LinkImage* img, CoffSection out[COFF_NBUCKETS], u32 bucket_cap[COFF_NBUCKETS], const LinkSection* ls) { Heap* heap = img->heap; - CoffBucket b2 = coff_bucket_for(ls); + CoffBucket b2 = coff_bucket_for(img->c, ls); u32 align = ls->align ? ls->align : 1u; u64 cur = bucket_cur[b2]; cur = ALIGN_UP(cur, (u64)align); @@ -997,6 +1003,10 @@ static void coff_build_buckets(LinkImage* img, CoffSection out[COFF_NBUCKETS], IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE; out[COFF_BUCKET_BSS].has_file_bytes = 0; + out[COFF_BUCKET_PDATA].name = ".pdata"; + out[COFF_BUCKET_PDATA].characteristics = + IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; + out[COFF_BUCKET_PDATA].has_file_bytes = 1; out[COFF_BUCKET_RELOC].name = ".reloc"; out[COFF_BUCKET_RELOC].characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | @@ -1400,7 +1410,11 @@ static void coff_write_optional_header(Writer* w, u32 entry_rva, out[COFF_BUCKET_TEXT].in_image ? out[COFF_BUCKET_TEXT].size_raw : 0; u32 size_init = (out[COFF_BUCKET_RDATA].in_image ? out[COFF_BUCKET_RDATA].size_raw : 0) + - (out[COFF_BUCKET_DATA].in_image ? out[COFF_BUCKET_DATA].size_raw : 0); + (out[COFF_BUCKET_IDATA].in_image ? out[COFF_BUCKET_IDATA].size_raw : 0) + + (out[COFF_BUCKET_DATA].in_image ? out[COFF_BUCKET_DATA].size_raw : 0) + + (out[COFF_BUCKET_TLS].in_image ? out[COFF_BUCKET_TLS].size_raw : 0) + + (out[COFF_BUCKET_PDATA].in_image ? out[COFF_BUCKET_PDATA].size_raw : 0) + + (out[COFF_BUCKET_RELOC].in_image ? out[COFF_BUCKET_RELOC].size_raw : 0); u32 size_uninit = out[COFF_BUCKET_BSS].in_image ? out[COFF_BUCKET_BSS].size : 0; coff_wr_u32(w, size_code); @@ -1433,6 +1447,7 @@ static void coff_write_optional_header(Writer* w, u32 entry_rva, coff_wr_u32(w, (u32)PE_NUM_DATA_DIRS); /* DataDirectory[16]. Populated entries: * [1] IMPORT — descriptor table RVA + total descriptor bytes + * [3] EXCEPTION — .pdata runtime-function table * [5] BASERELOC — when PIE and .reloc is in the image * [12] IAT — first IAT block RVA + sum of per-DLL IAT sizes * Everything else stays zero. */ @@ -1442,6 +1457,10 @@ static void coff_write_optional_header(Writer* w, u32 entry_rva, if (i == IMAGE_DIRECTORY_ENTRY_IMPORT && has_idata) { coff_wr_u32(w, out[COFF_BUCKET_IDATA].rva + it->desc_off); coff_wr_u32(w, it->desc_size); + } else if (i == IMAGE_DIRECTORY_ENTRY_EXCEPTION && + out[COFF_BUCKET_PDATA].in_image) { + coff_wr_u32(w, out[COFF_BUCKET_PDATA].rva); + coff_wr_u32(w, out[COFF_BUCKET_PDATA].size); } else if (i == IMAGE_DIRECTORY_ENTRY_IAT && has_idata) { coff_wr_u32(w, out[COFF_BUCKET_IDATA].rva + it->iat_base); coff_wr_u32(w, it->iat_total);