reloc_apply_test.c (9365B)
1 /* Relocation byte-encoder migration guard (doc/plan/RELOC.md, WS-C). 2 * 3 * WS-C moves the per-arch *instruction-immediate* byte encoders out of the 4 * format-neutral src/obj/reloc_apply.c into each backend's 5 * src/arch/<arch>/reloc.c (reached via LinkArchDesc.reloc_apply_insn), while 6 * link_reloc_apply stays the single public byte-patcher entry. The move must 7 * be byte-identical: the dispatcher routes each kind to the same encoder it 8 * had before, producing the same patched bytes. 9 * 10 * This test pins that. For one representative, in-range relocation of every 11 * instruction-embedded kind (plus a sampling of the arch-neutral data-word 12 * kinds the obj core keeps), it drives link_reloc_apply and asserts the 13 * patched bytes equal a frozen golden. The goldens were captured from the 14 * pre-WS-C implementation; do not "improve" them — they are the spec the 15 * partitioned encoders must match. A drift in any encoder turns this red and 16 * bisects to the exact kind (hence arch). 17 * 18 * Run with KIT_RELOC_APPLY_CAPTURE=1 in the environment to re-emit the golden 19 * column (used once to seed it from the frozen implementation). 20 * 21 * Exit 0 = pass; non-zero = fail. */ 22 23 #include "obj/reloc_apply.h" 24 25 #include <kit/cg.h> 26 #include <kit/core.h> 27 28 #include "core/core.h" 29 #include "lib/kit_unit.h" 30 #include "obj/obj.h" 31 32 static KitUnit g_u; 33 #define EXPECT(cond, ...) CU_EXPECT(&g_u, cond, __VA_ARGS__) 34 35 typedef struct ApplyCase { 36 const char* name; 37 KitArchKind arch; 38 RelocKind kind; 39 u64 in; /* initial site bytes, little-endian packed */ 40 u32 nbytes; /* bytes the encoder touches / we compare */ 41 u64 S; 42 i64 A; 43 u64 P; 44 u64 want; /* golden patched bytes, little-endian packed */ 45 } ApplyCase; 46 47 /* Instruction-immediate encoders (the WS-C movers) plus a sampling of the 48 * arch-neutral data-word arms the obj core retains. Inputs are chosen 49 * in-range so no encoder range check panics. */ 50 static const ApplyCase kCases[] = { 51 /* ---- AArch64 instruction-immediate encoders ---- */ 52 {"aa64 CONDBR19", KIT_ARCH_ARM_64, R_AARCH64_CONDBR19, 0x54000000u, 4, 53 0x2000, 0, 0x1000, 0x54008000u}, 54 {"aa64 LD_PREL_LO19", KIT_ARCH_ARM_64, R_AARCH64_LD_PREL_LO19, 0x58000000u, 55 4, 0x2000, 0, 0x1000, 0x58008000u}, 56 {"aa64 TSTBR14", KIT_ARCH_ARM_64, R_AARCH64_TSTBR14, 0x36000000u, 4, 0x1100, 57 0, 0x1000, 0x36000800u}, 58 {"aa64 ADR_PREL_LO21", KIT_ARCH_ARM_64, R_AARCH64_ADR_PREL_LO21, 59 0x10000000u, 4, 0x1234, 0, 0x1000, 0x100011a0u}, 60 {"aa64 JUMP26", KIT_ARCH_ARM_64, R_AARCH64_JUMP26, 0x14000000u, 4, 0x5000, 61 0, 0x1000, 0x14001000u}, 62 {"aa64 CALL26", KIT_ARCH_ARM_64, R_AARCH64_CALL26, 0x94000000u, 4, 0x5000, 63 0, 0x1000, 0x94001000u}, 64 {"aa64 ADR_PREL_PG_HI21", KIT_ARCH_ARM_64, R_AARCH64_ADR_PREL_PG_HI21, 65 0x90000000u, 4, 0x100000, 0, 0x1000, 0xf00007e0u}, 66 {"aa64 ADR_PREL_PG_HI21_NC", KIT_ARCH_ARM_64, R_AARCH64_ADR_PREL_PG_HI21_NC, 67 0x90000000u, 4, 0x100000, 0, 0x1000, 0xf00007e0u}, 68 {"aa64 ADR_GOT_PAGE", KIT_ARCH_ARM_64, R_AARCH64_ADR_GOT_PAGE, 0x90000000u, 69 4, 0x100000, 0, 0x1000, 0xf00007e0u}, 70 {"aa64 TLSIE_ADR_GOTTPREL_PAGE21", KIT_ARCH_ARM_64, 71 R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, 0x90000000u, 4, 0x100000, 0, 0x1000, 72 0xf00007e0u}, 73 {"aa64 TLVP_LOAD_PAGE21", KIT_ARCH_ARM_64, R_AARCH64_TLVP_LOAD_PAGE21, 74 0x90000000u, 4, 0x100000, 0, 0x1000, 0xf00007e0u}, 75 {"aa64 ADD_ABS_LO12_NC", KIT_ARCH_ARM_64, R_AARCH64_ADD_ABS_LO12_NC, 76 0x91000000u, 4, 0x1abc, 0, 0, 0x912af000u}, 77 {"aa64 TLSLE_ADD_TPREL_HI12", KIT_ARCH_ARM_64, 78 R_AARCH64_TLSLE_ADD_TPREL_HI12, 0x91000000u, 4, 0x12345, 0, 0, 79 0x91004800u}, 80 {"aa64 TLSLE_ADD_TPREL_LO12_NC", KIT_ARCH_ARM_64, 81 R_AARCH64_TLSLE_ADD_TPREL_LO12_NC, 0x91000000u, 4, 0x12345, 0, 0, 82 0x910d1400u}, 83 {"aa64 LDST8_ABS_LO12_NC", KIT_ARCH_ARM_64, R_AARCH64_LDST8_ABS_LO12_NC, 84 0xf9400000u, 4, 0x1100, 0, 0, 0xf9440000u}, 85 {"aa64 LDST16_ABS_LO12_NC", KIT_ARCH_ARM_64, R_AARCH64_LDST16_ABS_LO12_NC, 86 0xf9400000u, 4, 0x1100, 0, 0, 0xf9420000u}, 87 {"aa64 LDST32_ABS_LO12_NC", KIT_ARCH_ARM_64, R_AARCH64_LDST32_ABS_LO12_NC, 88 0xf9400000u, 4, 0x1100, 0, 0, 0xf9410000u}, 89 {"aa64 LDST64_ABS_LO12_NC", KIT_ARCH_ARM_64, R_AARCH64_LDST64_ABS_LO12_NC, 90 0xf9400000u, 4, 0x1100, 0, 0, 0xf9408000u}, 91 {"aa64 LDST128_ABS_LO12_NC", KIT_ARCH_ARM_64, R_AARCH64_LDST128_ABS_LO12_NC, 92 0xf9400000u, 4, 0x1100, 0, 0, 0xf9404000u}, 93 {"aa64 LD64_GOT_LO12_NC", KIT_ARCH_ARM_64, R_AARCH64_LD64_GOT_LO12_NC, 94 0xf9400000u, 4, 0x1100, 0, 0, 0xf9408000u}, 95 {"aa64 TLSIE_LD64_GOTTPREL_LO12_NC", KIT_ARCH_ARM_64, 96 R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, 0xf9400000u, 4, 0x1100, 0, 0, 97 0xf9408000u}, 98 {"aa64 TLVP_LOAD_PAGEOFF12", KIT_ARCH_ARM_64, R_AARCH64_TLVP_LOAD_PAGEOFF12, 99 0xf9400000u, 4, 0x1100, 0, 0, 0xf9408000u}, 100 /* ---- AArch64 neutral data words (kept in obj core) ---- */ 101 {"aa64 ABS16", KIT_ARCH_ARM_64, R_ABS16, 0x0000u, 2, 0x1234, 0, 0, 102 0x1234u}, 103 {"aa64 PREL16", KIT_ARCH_ARM_64, R_PREL16, 0x0000u, 2, 0x2000, 0, 104 0x1000, 0x1000u}, 105 106 /* ---- x86-64 instruction-immediate + neutral data words ---- */ 107 {"x64 PC8", KIT_ARCH_X86_64, R_X64_PC8, 0x00u, 1, 0x1010, -2, 0x1000, 108 0x0eu}, 109 {"x64 ABS32", KIT_ARCH_X86_64, R_ABS32, 0x0u, 4, 0xdeadbeefu, 0, 0, 110 0xdeadbeefu}, 111 {"x64 ABS64", KIT_ARCH_X86_64, R_ABS64, 0x0u, 8, 0x1122334455667788ull, 0, 112 0, 0x1122334455667788ull}, 113 {"x64 PC32", KIT_ARCH_X86_64, R_PC32, 0x0u, 4, 0x2000, -4, 0x1000, 0xffcu}, 114 {"x64 TPOFF32", KIT_ARCH_X86_64, R_X64_TPOFF32, 0x0u, 4, 0x12345678u, 0, 0, 115 0x12345678u}, 116 {"x64 GLOB_DAT", KIT_ARCH_X86_64, R_X64_GLOB_DAT, 0x0u, 8, 0xcafebabeu, 0, 117 0, 0xcafebabeu}, 118 119 /* ---- RISC-V instruction-immediate encoders ---- */ 120 {"rv HI20", KIT_ARCH_RV64, R_RV_HI20, 0x00000537u, 4, 0x12345, 0, 0, 121 0x00012537u}, 122 {"rv TPREL_HI20", KIT_ARCH_RV64, R_RV_TPREL_HI20, 0x00000537u, 4, 0x12345, 123 0, 0, 0x00012537u}, 124 {"rv PCREL_HI20", KIT_ARCH_RV64, R_RV_PCREL_HI20, 0x00000517u, 4, 0x13345, 125 0, 0x1000, 0x00012517u}, 126 {"rv GOT_HI20", KIT_ARCH_RV64, R_RV_GOT_HI20, 0x00000517u, 4, 0x13345, 0, 127 0x1000, 0x00012517u}, 128 {"rv TLS_GOT_HI20", KIT_ARCH_RV64, R_RV_TLS_GOT_HI20, 0x00000517u, 4, 129 0x13345, 0, 0x1000, 0x00012517u}, 130 {"rv LO12_I", KIT_ARCH_RV64, R_RV_LO12_I, 0x00000013u, 4, 0x12345, 0, 0, 131 0x34500013u}, 132 {"rv TPREL_LO12_I", KIT_ARCH_RV64, R_RV_TPREL_LO12_I, 0x00000013u, 4, 133 0x12345, 0, 0, 0x34500013u}, 134 {"rv LO12_S", KIT_ARCH_RV64, R_RV_LO12_S, 0x00000023u, 4, 0x12345, 0, 0, 135 0x340002a3u}, 136 {"rv TPREL_LO12_S", KIT_ARCH_RV64, R_RV_TPREL_LO12_S, 0x00000023u, 4, 137 0x12345, 0, 0, 0x340002a3u}, 138 {"rv BRANCH", KIT_ARCH_RV64, R_RV_BRANCH, 0x00000063u, 4, 0x1100, 0, 0x1000, 139 0x10000063u}, 140 {"rv JAL", KIT_ARCH_RV64, R_RV_JAL, 0x0000006fu, 4, 0x5100, 0, 0x1000, 141 0x1000406fu}, 142 {"rv CALL", KIT_ARCH_RV64, R_RV_CALL, 0x000080e700000097ull, 8, 0x100000, 0, 143 0x1000, 0x000080e7000ff097ull}, 144 {"rv PLT32", KIT_ARCH_RV64, R_PLT32, 0x000080e700000097ull, 8, 0x100000, 0, 145 0x1000, 0x000080e7000ff097ull}, 146 {"rv RVC_BRANCH", KIT_ARCH_RV64, R_RV_RVC_BRANCH, 0xc001u, 2, 0x1080, 0, 147 0x1000, 0xc041u}, 148 {"rv RVC_JUMP", KIT_ARCH_RV64, R_RV_RVC_JUMP, 0xa001u, 2, 0x1400, 0, 0x1000, 149 0xa101u}, 150 /* ---- RISC-V relaxation markers (no bytes patched) ---- */ 151 {"rv RELAX", KIT_ARCH_RV64, R_RV_RELAX, 0xdeadbeefu, 4, 0x1000, 0, 0x2000, 152 0xdeadbeefu}, 153 {"rv TPREL_ADD", KIT_ARCH_RV64, R_RV_TPREL_ADD, 0xdeadbeefu, 4, 0x1000, 0, 154 0x2000, 0xdeadbeefu}, 155 /* ---- RISC-V neutral data-word arms (kept in obj core) ---- */ 156 {"rv ADD32", KIT_ARCH_RV64, R_ADD32, 0x00000010u, 4, 0x20, 0, 0, 157 0x00000030u}, 158 {"rv SUB32", KIT_ARCH_RV64, R_SUB32, 0x00000030u, 4, 0x10, 0, 0, 159 0x00000020u}, 160 {"rv SET8", KIT_ARCH_RV64, R_ABS8, 0x00u, 1, 0x2a, 0, 0, 0x2au}, 161 }; 162 163 static KitCompiler* compiler_for(KitArchKind arch) { 164 static KitCompiler* aa64 = NULL; 165 static KitCompiler* x64 = NULL; 166 static KitCompiler* rv64 = NULL; 167 KitCompiler** slot = arch == KIT_ARCH_ARM_64 ? &aa64 168 : arch == KIT_ARCH_X86_64 ? &x64 169 : &rv64; 170 if (!*slot) { 171 KitTargetSpec t = kit_unit_target(arch, KIT_OS_LINUX, KIT_OBJ_ELF); 172 if (kit_unit_compiler_new(&g_u, t, slot) != KIT_OK || !*slot) { 173 fprintf(stderr, "compiler_new failed for arch=%d\n", (int)arch); 174 exit(2); 175 } 176 } 177 return *slot; 178 } 179 180 int main(void) { 181 size_t i; 182 int capture = getenv("KIT_RELOC_APPLY_CAPTURE") != NULL; 183 184 kit_unit_init(&g_u); 185 186 for (i = 0; i < sizeof kCases / sizeof kCases[0]; ++i) { 187 const ApplyCase* tc = &kCases[i]; 188 u8 buf[8] = {0}; 189 u64 got = 0; 190 u32 b; 191 memcpy(buf, &tc->in, tc->nbytes); 192 link_reloc_apply(compiler_for(tc->arch), tc->kind, buf, tc->S, tc->A, 193 tc->P); 194 for (b = 0; b < tc->nbytes; ++b) got |= (u64)buf[b] << (8u * b); 195 196 if (capture) { 197 printf(" /* %-32s */ 0x%016llxull,\n", tc->name, 198 (unsigned long long)got); 199 continue; 200 } 201 EXPECT(got == tc->want, "%s: got=0x%016llx want=0x%016llx", tc->name, 202 (unsigned long long)got, (unsigned long long)tc->want); 203 } 204 205 if (capture) return 0; 206 kit_unit_summary(&g_u, "reloc_apply_test"); 207 return kit_unit_status(&g_u); 208 }