- 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
185 lines
5.8 KiB
C
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;
|
|
}
|