kit

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

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 }