Okay, so I thought everything was good, but it turns out one of the real issues was adding mixing object files and compilations into one tcc state, something my unit tests didn't cover. So here's a dump of the RUNTIME_FUNCTION array passed to RtlAddFunctionTable, where I compiled some stuff using
RF[0]: 0x0000000008830AD3 -> 0x0000000008830AC8 + 0xB .. 0x42 (uwinfo @ 0x44)
RF[1] : 0x0000000008830B1F -> 0x0000000008830AC8 + 0x57 .. 0x164 (uwinfo @ 0x44)
RF[2] : 0x0000000008830C37 -> 0x0000000008830AC8 + 0x16F .. 0x18C (uwinfo @ 0x44)
RF[3] : 0x0000000008830C5F -> 0x0000000008830AC8 + 0x197 .. 0x1B4 (uwinfo @ 0x44)
RF[4] : 0x0000000008830C87 -> 0x0000000008830AC8 + 0x1BF .. 0x33E (uwinfo @ 0x44)
RF[5] : 0x0000000008830E11 -> 0x0000000008830AC8 + 0x349 .. 0x4A0 (uwinfo @ 0x44)
RF[6] : 0x0000000008830F73 -> 0x0000000008830AC8 + 0x4AB .. 0x519 (uwinfo @ 0x44)
RF[7] : 0x0000000008830FEC -> 0x0000000008830AC8 + 0x524 .. 0x5C3 (uwinfo @ 0x44)
RF[8] : 0x0000000008831096 -> 0x0000000008830AC8 + 0x5CE .. 0x620 (uwinfo @ 0x44)
RF[9] : 0x00000000088310F3 -> 0x0000000008830AC8 + 0x62B .. 0x645 (uwinfo @ 0x44)
RF[10] : 0x0000000008831118 -> 0x0000000008830AC8 + 0x650 .. 0x672 (uwinfo @ 0x44)
RF[11] : 0x0000000008831145 -> 0x0000000008830AC8 + 0x67D .. 0x693 (uwinfo @ 0x44)
RF[12] : 0x0000000008831166 -> 0x0000000008830AC8 + 0x69E .. 0x6B4 (uwinfo @ 0x44)
RF[13] : 0x0000000008831187 -> 0x0000000008830AC8 + 0x6BF .. 0x708 (uwinfo @ 0x44)
RF[14] : 0x0000000008830AD3 -> 0x0000000008830AC8 + 0xB .. 0x42 (uwinfo @ 0x44)
RF[15] : 0x0000000008830B1F -> 0x0000000008830AC8 + 0x57 .. 0x68 (uwinfo @ 0x44)
RF[16] : 0x0000000008830B3B -> 0x0000000008830AC8 + 0x73 .. 0x7C (uwinfo @ 0x44)
RF[17] : 0x0000000008830B4F -> 0x0000000008830AC8 + 0x87 .. 0x14E (uwinfo @ 0x44)
RF[18] : 0x0000000008830C21 -> 0x0000000008830AC8 + 0x159 .. 0x1E8 (uwinfo @ 0x44)
RF[19] : 0x0000000008830CBB -> 0x0000000008830AC8 + 0x1F3 .. 0x26E (uwinfo @ 0x44)
RF[20] : 0x0000000008830D41 -> 0x0000000008830AC8 + 0x279 .. 0x29D (uwinfo @ 0x44)
RF[21] : 0x0000000008830D70 -> 0x0000000008830AC8 + 0x2A8 .. 0x2BD (uwinfo @ 0x44)
RF[22] : 0x0000000008830D90 -> 0x0000000008830AC8 + 0x2C8 .. 0x384 (uwinfo @ 0x44)
RF[23] : 0x0000000008830E57 -> 0x0000000008830AC8 + 0x38F .. 0x452 (uwinfo @ 0x44)
RF[24] : 0x0000000008830F25 -> 0x0000000008830AC8 + 0x45D .. 0x4F7 (uwinfo @ 0x44)
RF[25] : 0x0000000008830FCA -> 0x0000000008830AC8 + 0x502 .. 0x5AA (uwinfo @ 0x44)
RF[26] : 0x000000000883107D -> 0x0000000008830AC8 + 0x5B5 .. 0x607 (uwinfo @ 0x44)
RF[27] : 0x00000000088310DA -> 0x0000000008830AC8 + 0x612 .. 0x62C (uwinfo @ 0x44)
RF[28] : 0x00000000088310FF -> 0x0000000008830AC8 + 0x637 .. 0x659 (uwinfo @ 0x44)
RF[29] : 0x000000000883112C -> 0x0000000008830AC8 + 0x664 .. 0x67A (uwinfo @ 0x44)
RF[30] : 0x000000000883114D -> 0x0000000008830AC8 + 0x685 .. 0x69B (uwinfo @ 0x44)
RF[31] : 0x0000000008831876 -> 0x0000000008830AC8 + 0xDAE .. 0xDEF (uwinfo @ 0x44)
RF[32] : 0x00000000088318C2 -> 0x0000000008830AC8 + 0xDFA .. 0xE3B (uwinfo @ 0x44)
As can be seen, from runtime function 14, the function entries start to overlap again. Probably, there's a missing segment/section offset somewhere when TCC adds runtime functions from different contexts/sections/object files? However, I'm having a hard time discovering where exactly object files are added to the TCCState.uw_pdata (it is not done through pe_add_unwind_data).