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
This commit is contained in:
469
libs/format/src/scf.c
Normal file
469
libs/format/src/scf.c
Normal file
@@ -0,0 +1,469 @@
|
||||
/**
|
||||
* @file scf.c
|
||||
* @brief SCF 格式实现
|
||||
*/
|
||||
|
||||
#include <scf_impl.h>
|
||||
|
||||
/**
|
||||
* @brief 初始化 SCF 结构
|
||||
* @param scf 指向 scf_t 结构的指针
|
||||
*/
|
||||
void scf_init(scf_t *scf) {
|
||||
if (!scf) {
|
||||
return;
|
||||
}
|
||||
|
||||
scc_memset(&scf->header, 0, sizeof(scf->header));
|
||||
scc_memcpy(scf->header.magic, SCF_MAGIC, 4);
|
||||
scf->header.version = SCF_VERSION;
|
||||
scf->header.arch = SCF_ARCH_UNKNOWN;
|
||||
scf->header.flags = 0;
|
||||
scf->header.entry_point = 0;
|
||||
scf->header.data_size = 0;
|
||||
scf->header.code_size = 0;
|
||||
scf->header.strtab_size = 0;
|
||||
scf->header.sym_count = 0;
|
||||
scf->header.reloc_count = 0;
|
||||
|
||||
scc_vec_init(scf->text);
|
||||
scc_vec_init(scf->data);
|
||||
scc_vec_init(scf->symtab);
|
||||
scc_vec_init(scf->reloc);
|
||||
scc_vec_init(scf->strtab);
|
||||
|
||||
scc_strpool_init(&scf->strpool);
|
||||
scf->str2idx.hash_func = (void *)scc_strhash32;
|
||||
scf->str2idx.key_cmp = (void *)scc_strcmp;
|
||||
scc_hashtable_init(&scf->str2idx);
|
||||
|
||||
scc_vec_init(scf->syms);
|
||||
scc_vec_init(scf->relocs);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 从缓冲区读取并解析 SCF 数据
|
||||
* @param scf 指向 scf_t 结构的指针
|
||||
* @param buffer 输入缓冲区
|
||||
* @param size 缓冲区大小
|
||||
* @return 成功返回 true,失败返回 false
|
||||
*/
|
||||
cbool scf_parse(scf_t *scf, const char *buffer, usize size) {
|
||||
if (!scf || !buffer || size < sizeof(scf_header_t)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 读取头部
|
||||
const scf_header_t *header = (const scf_header_t *)buffer;
|
||||
if (scc_memcmp(header->magic, SCF_MAGIC, 4) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
scf->header = *header;
|
||||
|
||||
// 计算各段偏移
|
||||
usize offset = sizeof(scf_header_t);
|
||||
|
||||
// 读取 text 段
|
||||
if (scf->header.code_size > 0) {
|
||||
if (offset + scf->header.code_size > size) {
|
||||
return false;
|
||||
}
|
||||
// 调整 text 向量大小
|
||||
while (scf->text.size < scf->header.code_size) {
|
||||
scc_vec_push(scf->text, 0);
|
||||
}
|
||||
scc_memcpy(scf->text.data, buffer + offset, scf->header.code_size);
|
||||
offset += scf->header.code_size;
|
||||
}
|
||||
|
||||
// 读取 data 段
|
||||
if (scf->header.data_size > 0) {
|
||||
if (offset + scf->header.data_size > size) {
|
||||
return false;
|
||||
}
|
||||
// 调整 data 向量大小
|
||||
while (scf->data.size < scf->header.data_size) {
|
||||
scc_vec_push(scf->data, 0);
|
||||
}
|
||||
scc_memcpy(scf->data.data, buffer + offset, scf->header.data_size);
|
||||
offset += scf->header.data_size;
|
||||
}
|
||||
|
||||
// 读取符号表
|
||||
if (scf->header.sym_count > 0) {
|
||||
usize symtab_size = scf->header.sym_count * sizeof(scf_sym_t);
|
||||
if (offset + symtab_size > size) {
|
||||
return false;
|
||||
}
|
||||
// 调整 syms 向量大小
|
||||
while (scf->syms.size < scf->header.sym_count) {
|
||||
scf_sym_t sym = {0};
|
||||
scc_vec_push(scf->syms, sym);
|
||||
}
|
||||
scc_memcpy(scf->syms.data, buffer + offset, symtab_size);
|
||||
offset += symtab_size;
|
||||
}
|
||||
|
||||
// 读取重定位表
|
||||
if (scf->header.reloc_count > 0) {
|
||||
usize reloc_size = scf->header.reloc_count * sizeof(scf_reloc_t);
|
||||
if (offset + reloc_size > size) {
|
||||
return false;
|
||||
}
|
||||
// 调整 relocs 向量大小
|
||||
while (scf->relocs.size < scf->header.reloc_count) {
|
||||
scf_reloc_t reloc = {0};
|
||||
scc_vec_push(scf->relocs, reloc);
|
||||
}
|
||||
scc_memcpy(scf->relocs.data, buffer + offset, reloc_size);
|
||||
offset += reloc_size;
|
||||
}
|
||||
|
||||
// 读取字符串表
|
||||
if (scf->header.strtab_size > 0) {
|
||||
if (offset + scf->header.strtab_size > size) {
|
||||
return false;
|
||||
}
|
||||
// 调整 strtab 向量大小
|
||||
while (scf->strtab.size < scf->header.strtab_size) {
|
||||
scc_vec_push(scf->strtab, 0);
|
||||
}
|
||||
scc_memcpy(scf->strtab.data, buffer + offset, scf->header.strtab_size);
|
||||
offset += scf->header.strtab_size;
|
||||
}
|
||||
// 允许 offset <= size,因为缓冲区可能比实际数据大
|
||||
if (offset > size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 将 SCF 数据写入缓冲区
|
||||
* @param scf 指向 scf_t 结构的指针
|
||||
* @param buffer 输出缓冲区
|
||||
* @param size 缓冲区大小
|
||||
* @return 成功返回 true,失败返回 false
|
||||
*/
|
||||
cbool scf_write(scf_t *scf, char *buffer, usize size) {
|
||||
if (!scf || !buffer) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 计算所需大小
|
||||
usize needed = sizeof(scf_header_t);
|
||||
needed += scf->header.code_size; // text 段
|
||||
needed += scf->header.data_size; // data 段
|
||||
needed += scf->header.sym_count * sizeof(scf_sym_t);
|
||||
needed += scf->header.reloc_count * sizeof(scf_reloc_t);
|
||||
needed += scf->header.strtab_size;
|
||||
|
||||
if (size < needed) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 写入头部
|
||||
scf_header_t *header = (scf_header_t *)buffer;
|
||||
*header = scf->header;
|
||||
usize offset = sizeof(scf_header_t);
|
||||
|
||||
// 写入 text 段
|
||||
if (scf->header.code_size > 0) {
|
||||
scc_memcpy(buffer + offset, scf->text.data, scf->header.code_size);
|
||||
offset += scf->header.code_size;
|
||||
}
|
||||
|
||||
// 写入 data 段
|
||||
if (scf->header.data_size > 0) {
|
||||
scc_memcpy(buffer + offset, scf->data.data, scf->header.data_size);
|
||||
offset += scf->header.data_size;
|
||||
}
|
||||
|
||||
// 写入符号表
|
||||
if (scf->header.sym_count > 0) {
|
||||
usize symtab_size = scf->header.sym_count * sizeof(scf_sym_t);
|
||||
scc_memcpy(buffer + offset, scf->syms.data, symtab_size);
|
||||
offset += symtab_size;
|
||||
}
|
||||
|
||||
// 写入重定位表
|
||||
if (scf->header.reloc_count > 0) {
|
||||
usize reloc_size = scf->header.reloc_count * sizeof(scf_reloc_t);
|
||||
scc_memcpy(buffer + offset, scf->relocs.data, reloc_size);
|
||||
offset += reloc_size;
|
||||
}
|
||||
|
||||
// 写入字符串表
|
||||
if (scf->header.strtab_size > 0) {
|
||||
scc_memcpy(buffer + offset, scf->strtab.data, scf->header.strtab_size);
|
||||
offset += scf->header.strtab_size;
|
||||
}
|
||||
|
||||
Assert(offset <= size);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 交换段数据
|
||||
* @param scf 指向 scf_t 结构的指针
|
||||
* @param type 段类型
|
||||
* @param section 指向新段数据的指针(双向交换)
|
||||
* @return 成功返回 true,失败返回 false
|
||||
*/
|
||||
cbool scf_exchange_section(scf_t *scf, scf_sect_type_t type,
|
||||
scf_sect_data_t **section) {
|
||||
if (!scf || !section || !*section) {
|
||||
return false;
|
||||
}
|
||||
|
||||
scf_sect_data_t *target_section = NULL;
|
||||
scf_size_t *size_field = NULL;
|
||||
|
||||
// 根据类型选择目标段和大小字段
|
||||
switch (type) {
|
||||
case SCF_SECT_CODE:
|
||||
target_section = &scf->text;
|
||||
size_field = &scf->header.code_size;
|
||||
break;
|
||||
case SCF_SECT_DATA:
|
||||
target_section = &scf->data;
|
||||
size_field = &scf->header.data_size;
|
||||
break;
|
||||
case SCF_SECT_RODATA:
|
||||
// 当前实现中没有单独的rodata段,使用data段
|
||||
target_section = &scf->data;
|
||||
size_field = &scf->header.data_size;
|
||||
break;
|
||||
case SCF_SECT_BSS:
|
||||
// BSS段不存储数据,只记录大小
|
||||
// 这里暂时不支持交换BSS段
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
// 交换段数据
|
||||
scf_sect_data_t temp = *target_section;
|
||||
*target_section = **section;
|
||||
**section = temp;
|
||||
|
||||
// 更新大小字段
|
||||
if (size_field) {
|
||||
// 保存旧大小(如果需要的话)
|
||||
// scf_size_t temp_size = *size_field; // 未使用,注释掉
|
||||
*size_field = (scf_size_t)(*target_section).size;
|
||||
// 如果调用者需要知道新的大小,可以在这里设置
|
||||
// 但当前API没有提供这个功能
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 添加符号到符号表
|
||||
* @param scf 指向 scf_t 结构的指针
|
||||
* @param sym 指向要添加的符号的指针
|
||||
* @return 成功返回 true,失败返回 false
|
||||
*/
|
||||
cbool scf_add_sym(scf_t *scf, scf_sym_t *sym) {
|
||||
if (!scf || !sym) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 添加到符号向量
|
||||
scc_vec_push(scf->syms, *sym);
|
||||
scf->header.sym_count++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 添加重定位条目
|
||||
* @param scf 指向 scf_t 结构的指针
|
||||
* @param reloc 指向要添加的重定位条目的指针
|
||||
* @return 成功返回 true,失败返回 false
|
||||
*/
|
||||
cbool scf_add_reloc(scf_t *scf, scf_reloc_t *reloc) {
|
||||
if (!scf || !reloc) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 添加到重定位向量
|
||||
scc_vec_push(scf->relocs, *reloc);
|
||||
scf->header.reloc_count++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 检查 SCF 结构是否有效
|
||||
* @param scf 指向 scf_t 结构的指针
|
||||
* @return 有效返回 true,无效返回 false
|
||||
*/
|
||||
cbool scf_check_valid(scf_t *scf) {
|
||||
if (!scf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查魔数
|
||||
if (scc_memcmp(scf->header.magic, SCF_MAGIC, 4) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查版本
|
||||
if (scf->header.version != SCF_VERSION) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查架构
|
||||
if (scf->header.arch > SCF_ARCH_X64) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 检查各段大小是否一致
|
||||
if (scf->header.code_size != scf->text.size) {
|
||||
return false;
|
||||
}
|
||||
if (scf->header.data_size != scf->data.size) {
|
||||
return false;
|
||||
}
|
||||
if (scf->header.sym_count != scf->syms.size) {
|
||||
return false;
|
||||
}
|
||||
if (scf->header.reloc_count != scf->relocs.size) {
|
||||
return false;
|
||||
}
|
||||
if (scf->header.strtab_size != scf->strtab.size) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 应用重定位到段数据
|
||||
* @param scf 指向 scf_t 结构的指针
|
||||
* @return 成功返回 true,失败返回 false
|
||||
*/
|
||||
cbool scf_apply_relocations(scf_t *scf) {
|
||||
if (!scf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 遍历所有重定位条目
|
||||
for (usize i = 0; i < scf->relocs.size; i++) {
|
||||
scf_reloc_t *reloc = &scf->relocs.data[i];
|
||||
|
||||
// 根据段类型选择目标段
|
||||
scf_sect_data_t *target_section = NULL;
|
||||
switch (reloc->sect_type) {
|
||||
case SCF_SECT_CODE:
|
||||
target_section = &scf->text;
|
||||
break;
|
||||
case SCF_SECT_DATA:
|
||||
case SCF_SECT_RODATA:
|
||||
target_section = &scf->data;
|
||||
break;
|
||||
default:
|
||||
// 不支持的段类型
|
||||
continue;
|
||||
}
|
||||
|
||||
// 检查偏移量是否有效
|
||||
if (reloc->offset + sizeof(scf_size_t) > target_section->size) {
|
||||
// 偏移量超出段范围
|
||||
return false;
|
||||
}
|
||||
|
||||
// 获取符号地址
|
||||
scf_size_t symbol_address = 0;
|
||||
if (reloc->sym_idx < scf->syms.size) {
|
||||
scf_sym_t *sym = &scf->syms.data[reloc->sym_idx];
|
||||
symbol_address = sym->scf_sect_offset;
|
||||
}
|
||||
|
||||
// 计算重定位值
|
||||
scf_size_t relocation_value = symbol_address + reloc->addend;
|
||||
|
||||
// 根据重定位类型应用
|
||||
scf_size_t *target =
|
||||
(scf_size_t *)(target_section->data + reloc->offset);
|
||||
switch (reloc->type) {
|
||||
case SCF_RELOC_ABS:
|
||||
// 绝对地址:直接替换
|
||||
*target = relocation_value;
|
||||
break;
|
||||
case SCF_RELOC_REL:
|
||||
// 相对地址:计算相对于当前位置的偏移
|
||||
// 使用 uintptr_t 进行安全的指针到整数转换
|
||||
*target = relocation_value - (scf_size_t)(uintptr_t)target;
|
||||
break;
|
||||
case SCF_RELOC_PC:
|
||||
// PC相对:计算相对于PC的偏移
|
||||
// 使用 uintptr_t 进行安全的指针到整数转换
|
||||
*target = relocation_value - (scf_size_t)(uintptr_t)(target + 1);
|
||||
break;
|
||||
default:
|
||||
// 不支持的重定位类型
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 在写入前进行内部整理
|
||||
* @param scf 指向 scf_t 结构的指针
|
||||
* @return 成功返回 true,失败返回 false
|
||||
*/
|
||||
cbool scf_write_done(scf_t *scf) {
|
||||
if (!scf) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 应用所有重定位
|
||||
if (!scf_apply_relocations(scf)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 更新头部中的大小字段
|
||||
scf->header.code_size = (scf_size_t)scf->text.size;
|
||||
scf->header.data_size = (scf_size_t)scf->data.size;
|
||||
scf->header.sym_count = (scf_size_t)scf->syms.size;
|
||||
scf->header.reloc_count = (scf_size_t)scf->relocs.size;
|
||||
scf->header.strtab_size = (scf_size_t)scf->strtab.size;
|
||||
|
||||
// 设置标志位为内部链接后的可执行文件
|
||||
scf->header.flags |= SCF_FLAG_EXE_RELOC;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief 链接多个 SCF 文件
|
||||
* @param scfs 包含多个 SCF 文件的向量
|
||||
* @param outscf 输出链接后的 SCF 文件
|
||||
* @return 成功返回 true,失败返回 false
|
||||
*/
|
||||
cbool scf_link_all(scf_vec_t scfs, scf_t *outscf) {
|
||||
if (!outscf || scfs.size == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// 初始化输出 SCF
|
||||
scf_init(outscf);
|
||||
|
||||
// 简单实现:只链接第一个文件
|
||||
// 实际实现应该合并所有文件的段、解析符号引用、应用重定位等
|
||||
if (scfs.size > 0) {
|
||||
scf_t *first = &scfs.data[0];
|
||||
// 这里应该进行深拷贝,但为了简单起见,我们只复制头部
|
||||
outscf->header = first->header;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
Reference in New Issue
Block a user