Files
scc/libs/format/tests/test_scf_x64.c
zzy 3aaf3a3991 feat: add SCF format library and rename components to SCC prefix
- Introduce new SCF (SCC Format) library with header, implementation, and test files
- SCF is a minimal executable/linkable format focused on internal linking with external symbol import/export abstraction
- Rename lexer and lex_parser packages from 'smcc_' to 'scc_' prefix for consistency
- Update hashmap implementation to use 'scc_' prefix for types and structures
- Add build configuration for new format library with dependencies on libcore and libutils
2025-12-11 17:29:12 +08:00

185 lines
5.8 KiB
C

/**
* @file test_scf_x64.c
* @brief SCF x64 architecture tests
*
* This test creates a simple x64 executable similar to the Rust example
* provided by the user.
*/
#include <scf_impl.h>
#include <stdio.h>
#include <string.h>
int main() {
printf("Testing SCF x64 format implementation...\n");
// Test 1: Initialize SCF for x64 architecture
scf_t scf;
scf_init(&scf);
// Set architecture to x64
scf.header.arch = SCF_ARCH_X64;
scf.header.flags = SCF_FLAG_EXE_RELOC;
printf("Test 1 PASSED: x64 initialization successful\n");
// Test 2: Add .text section with x64 machine code
// x64 machine code for:
// sub rsp, 0x28
// lea rcx, [rip + data_offset] ; will be relocated
// call [rip + printf_iat] ; will be relocated
// add rsp, 0x28
// xor eax, eax
// ret
unsigned char x64_code[] = {
0x48, 0x83, 0xEC, 0x28, // sub rsp, 0x28
0x48, 0x8D, 0x0D, 0x00, 0x00, 0x00,
0x00, // lea rcx, [rip + 0] (to be relocated)
0xFF, 0x15, 0x00, 0x00, 0x00, 0x00, // call [rip + 0] (to be relocated)
0x48, 0x83, 0xC4, 0x28, // add rsp, 0x28
0x33, 0xC0, // xor eax, eax
0xC3 // ret
};
// Add code to .text section
for (usize i = 0; i < sizeof(x64_code); i++) {
scc_vec_push(scf.text, x64_code[i]);
}
scf.header.code_size = (scf_size_t)scf.text.size;
printf("Test 2 PASSED: x64 code added to .text section\n");
// Test 3: Add .data section with string
const char hello_world[] = "Hello, World from SCF x64 Test!\n\0";
for (usize i = 0; i < sizeof(hello_world); i++) {
scc_vec_push(scf.data, hello_world[i]);
}
scf.header.data_size = (scf_size_t)scf.data.size;
printf("Test 3 PASSED: Data string added to .data section\n");
// Test 4: Add symbols
scf_sym_t data_sym = {0};
data_sym.name_offset = 0; // Would need string table for actual names
data_sym.scf_sym_type = SCF_SYM_TYPE_DATA;
data_sym.scf_sym_bind = SCF_SYM_BIND_GLOBAL;
data_sym.scf_sym_vis = SCF_SYM_VIS_DEFAULT;
data_sym.scf_sect_type = SCF_SECT_DATA;
data_sym.scf_sect_offset = 0; // Start of data section
data_sym.scf_sym_size = sizeof(hello_world);
if (!scf_add_sym(&scf, &data_sym)) {
printf("FAIL: Cannot add data symbol\n");
return 1;
}
scf_sym_t code_sym = {0};
code_sym.name_offset = 0;
code_sym.scf_sym_type = SCF_SYM_TYPE_FUNC;
code_sym.scf_sym_bind = SCF_SYM_BIND_GLOBAL;
code_sym.scf_sym_vis = SCF_SYM_VIS_DEFAULT;
code_sym.scf_sect_type = SCF_SECT_CODE;
code_sym.scf_sect_offset = 0; // Start of code section
code_sym.scf_sym_size = sizeof(x64_code);
if (!scf_add_sym(&scf, &code_sym)) {
printf("FAIL: Cannot add code symbol\n");
return 1;
}
printf("Test 4 PASSED: Symbols added\n");
// Test 5: Add relocations
// First relocation: data reference at offset 7 in code (lea rcx, [rip +
// data_offset])
scf_reloc_t data_reloc = {0};
data_reloc.offset = 7; // Offset in code section
data_reloc.sym_idx = 0; // Index of data symbol (first symbol added)
data_reloc.type = SCF_RELOC_PC; // PC-relative relocation
data_reloc.sect_type = SCF_SECT_CODE;
data_reloc.addend = -4; // RIP-relative addressing adjustment
if (!scf_add_reloc(&scf, &data_reloc)) {
printf("FAIL: Cannot add data relocation\n");
return 1;
}
// Second relocation: external function reference at offset 13 in code (call
// [rip + printf_iat])
scf_reloc_t func_reloc = {0};
func_reloc.offset = 13; // Offset in code section
func_reloc.sym_idx =
1; // Index of code symbol (would be external in real case)
func_reloc.type = SCF_RELOC_PC; // PC-relative relocation
func_reloc.sect_type = SCF_SECT_CODE;
func_reloc.addend = -4; // RIP-relative addressing adjustment
if (!scf_add_reloc(&scf, &func_reloc)) {
printf("FAIL: Cannot add function relocation\n");
return 1;
}
printf("Test 5 PASSED: Relocations added\n");
// Test 6: Apply relocations
if (!scf_apply_relocations(&scf)) {
printf("FAIL: Cannot apply relocations\n");
return 1;
}
printf("Test 6 PASSED: Relocations applied\n");
// Test 7: Prepare for writing (internal整理)
if (!scf_write_done(&scf)) {
printf("FAIL: Cannot prepare for writing\n");
return 1;
}
printf("Test 7 PASSED: Prepared for writing\n");
// Test 8: Write to buffer
char buffer[4096];
if (!scf_write(&scf, buffer, sizeof(buffer))) {
printf("FAIL: Cannot write to buffer\n");
return 1;
}
printf("Test 8 PASSED: Written to buffer\n");
// Test 9: Parse from buffer
scf_t scf2;
scf_init(&scf2);
if (!scf_parse(&scf2, buffer, sizeof(buffer))) {
printf("FAIL: Cannot parse from buffer\n");
return 1;
}
// Verify architecture
if (scf2.header.arch != SCF_ARCH_X64) {
printf("FAIL: Architecture not preserved\n");
return 1;
}
printf("Test 9 PASSED: Parsed from buffer, architecture preserved\n");
// Test 10: Verify structure
if (!scf_check_valid(&scf2)) {
printf("FAIL: Parsed structure invalid\n");
return 1;
}
printf("Test 10 PASSED: Parsed structure valid\n");
printf("\nAll x64 tests passed!\n");
printf("Created SCF file with:\n");
printf(" Architecture: x64\n");
printf(" Code size: %u bytes\n", scf.header.code_size);
printf(" Data size: %u bytes\n", scf.header.data_size);
printf(" Symbols: %u\n", scf.header.sym_count);
printf(" Relocations: %u\n", scf.header.reloc_count);
printf(" Flags: 0x%x\n", scf.header.flags);
return 0;
}