feat(ast2ir): 添加左值标识支持以改善表达式处理

- 在 scc_ast2ir_expr 函数中添加 is_lvalue 参数来区分左值和右值表达式
- 更新二元表达式处理逻辑,特别是赋值操作符的处理
- 改进标识符表达式的处理,根据是否为左值决定返回存储位置还是加载值
- 修复哈希比较函数的实现
- 移除调试相关的注释代码

refactor(parser): 优化语法分析器错误处理和控制流

- 移除不必要的错误恢复辅助注释
- 修改表达式解析的控制流程,将直接返回改为使用 break 语句
- 添加语义分析回调,在解析完成后进行标识符查找和验证

refactor(sema): 增强语义分析阶段的符号表管理

- 改进标识符查找逻辑,增加对非变量标识符的检查
- 扩展声明处理范围,包括变量和参数声明的符号表注册
- 为函数声明添加作用域管理

fix(parser): 修正单元测试中的类型定义

- 将 long long 类型定义改为 int 类型,解决测试兼容性问题

refactor(sccf): 重构文件格式定义和构建器实现

- 重命名符号类型枚举值 OBJECT 为 EXTERN
- 重命名段类型枚举值 RELOC 为 RELOCS
- 修正结构体字段命名的一致性问题
- 重新设计 SCCF 构建器的数据结构和API
- 添加符号表、字符串表和重定位表的构建支持

refactor(target): 重命名Windows PE相关类型定义

- 将 scc_winpe_* 类型重命名为 scc_pe_* 以保持命名一致性

chore: 添加 sccf2target 模块用于格式转换

- 创建新的库模块用于 SCCF 到目标格式的转换
- 实现 PE 格式转换的基本功能
- 添加示例程序演示格式转换过程
This commit is contained in:
zzy
2026-03-19 12:11:57 +08:00
parent 5f915ba8d3
commit 02a6c684f1
18 changed files with 575 additions and 101 deletions

View File

@@ -18,7 +18,8 @@ void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_type_abi_t *abi);
void scc_ast2ir_translation_unit(scc_ast2ir_ctx_t *ctx, void scc_ast2ir_translation_unit(scc_ast2ir_ctx_t *ctx,
scc_ast_translation_unit_t *tu); scc_ast_translation_unit_t *tu);
void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl); void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl);
scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr); scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
cbool is_lvalue);
void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt); void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt);
scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx, scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
scc_ast_type_t *ast_type); scc_ast_type_t *ast_type);

View File

@@ -92,7 +92,8 @@ scc_ir_type_ref_t scc_ast2ir_type(scc_ast2ir_ctx_t *ctx,
* @param expr * @param expr
* @return scc_ir_node_ref_t * @return scc_ir_node_ref_t
*/ */
scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr) { scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr,
cbool is_lvalue) {
if (ctx == null || expr == null) { if (ctx == null || expr == null) {
LOG_ERROR("args is null"); LOG_ERROR("args is null");
return 0; return 0;
@@ -101,8 +102,27 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr) {
switch (expr->base.type) { switch (expr->base.type) {
case SCC_AST_EXPR_BINARY: { case SCC_AST_EXPR_BINARY: {
scc_ir_node_ref_t lhs, rhs; scc_ir_node_ref_t lhs, rhs;
lhs = scc_ast2ir_expr(ctx, expr->binary.lhs); cbool is_assign = false;
rhs = scc_ast2ir_expr(ctx, expr->binary.rhs); switch (expr->binary.op) {
case SCC_AST_OP_ASSIGN: // =
case SCC_AST_OP_ASSIGN_ADD: // +=
case SCC_AST_OP_ASSIGN_SUB: // -=
case SCC_AST_OP_ASSIGN_MUL: // *=
case SCC_AST_OP_ASSIGN_DIV: // /=
case SCC_AST_OP_ASSIGN_MOD: // %=
case SCC_AST_OP_ASSIGN_AND: // &=
case SCC_AST_OP_ASSIGN_XOR: // ^=
case SCC_AST_OP_ASSIGN_OR: // |=
case SCC_AST_OP_ASSIGN_LSHIFT: // <<=
case SCC_AST_OP_ASSIGN_RSHIFT: // >>=
is_assign = true;
break;
default:
is_assign = false;
break;
}
lhs = scc_ast2ir_expr(ctx, expr->binary.lhs, is_assign);
rhs = scc_ast2ir_expr(ctx, expr->binary.rhs, false);
// 映射操作符 // 映射操作符
scc_ir_op_type_t op; scc_ir_op_type_t op;
@@ -124,17 +144,6 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr) {
case SCC_AST_OP_LESS_EQUAL: op = SCC_IR_OP_LE; break; case SCC_AST_OP_LESS_EQUAL: op = SCC_IR_OP_LE; break;
case SCC_AST_OP_GREATER: op = SCC_IR_OP_GT; break; case SCC_AST_OP_GREATER: op = SCC_IR_OP_GT; break;
case SCC_AST_OP_GREATER_EQUAL: op = SCC_IR_OP_GE; break; case SCC_AST_OP_GREATER_EQUAL: op = SCC_IR_OP_GE; break;
// SCC_AST_OP_ASSIGN, // =
// SCC_AST_OP_ASSIGN_ADD, // +=
// SCC_AST_OP_ASSIGN_SUB, // -=
// SCC_AST_OP_ASSIGN_MUL, // *=
// SCC_AST_OP_ASSIGN_DIV, // /=
// SCC_AST_OP_ASSIGN_MOD, // %=
// SCC_AST_OP_ASSIGN_AND, // &=
// SCC_AST_OP_ASSIGN_XOR, // ^=
// SCC_AST_OP_ASSIGN_OR, // |=
// SCC_AST_OP_ASSIGN_LSHIFT, // <<=
// SCC_AST_OP_ASSIGN_RSHIFT, // >>=
case SCC_AST_OP_ASSIGN: { case SCC_AST_OP_ASSIGN: {
return scc_ir_builder_store(&ctx->builder, lhs, rhs); return scc_ir_builder_store(&ctx->builder, lhs, rhs);
} }
@@ -194,7 +203,8 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr) {
} }
case SCC_AST_EXPR_UNARY: { case SCC_AST_EXPR_UNARY: {
scc_ir_node_ref_t operand = scc_ast2ir_expr(ctx, expr->unary.operand); scc_ir_node_ref_t operand =
scc_ast2ir_expr(ctx, expr->unary.operand, is_lvalue);
// 映射一元操作符 // 映射一元操作符
switch (expr->unary.op) { switch (expr->unary.op) {
@@ -235,7 +245,7 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr) {
scc_vec_foreach(expr->call.args, i) { scc_vec_foreach(expr->call.args, i) {
scc_ast_expr_t *arg_expr = scc_vec_at(expr->call.args, i); scc_ast_expr_t *arg_expr = scc_vec_at(expr->call.args, i);
scc_ir_node_ref_t arg_node; scc_ir_node_ref_t arg_node;
arg_node = scc_ast2ir_expr(ctx, arg_expr); arg_node = scc_ast2ir_expr(ctx, arg_expr, false);
scc_vec_push(args, arg_node); scc_vec_push(args, arg_node);
} }
} }
@@ -273,10 +283,17 @@ scc_ir_node_ref_t scc_ast2ir_expr(scc_ast2ir_ctx_t *ctx, scc_ast_expr_t *expr) {
// SCC_AST_EXPR_STRING_LITERAL, // 字符串字面量 // SCC_AST_EXPR_STRING_LITERAL, // 字符串字面量
case SCC_AST_EXPR_IDENTIFIER: { case SCC_AST_EXPR_IDENTIFIER: {
if (expr->identifier._target == null) {
LOG_ERROR("unknown identifier");
}
// FIXME hack hashtable // FIXME hack hashtable
scc_ir_node_ref_t in = (scc_ir_node_ref_t)(usize)scc_hashtable_get( scc_ir_node_ref_t in = (scc_ir_node_ref_t)(usize)scc_hashtable_get(
&ctx->node2ir, expr->identifier._target); &ctx->node2ir, expr->identifier._target);
return scc_ir_builder_load(&ctx->builder, in); if (is_lvalue) {
return in;
} else {
return scc_ir_builder_load(&ctx->builder, in);
}
} }
default: default:
@@ -315,7 +332,7 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
} }
case SCC_AST_STMT_EXPR: { case SCC_AST_STMT_EXPR: {
scc_ast2ir_expr(ctx, stmt->expr.expr); scc_ast2ir_expr(ctx, stmt->expr.expr, false);
break; break;
} }
@@ -336,7 +353,8 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
scc_ir_bblock_ref_t merge_block = scc_ir_bblock_ref_t merge_block =
scc_ir_builder_bblock(&ctx->builder, "if_merge"); scc_ir_builder_bblock(&ctx->builder, "if_merge");
scc_ir_node_ref_t cond_node = scc_ast2ir_expr(ctx, stmt->if_stmt.cond); scc_ir_node_ref_t cond_node =
scc_ast2ir_expr(ctx, stmt->if_stmt.cond, false);
scc_ir_builder_branch(&ctx->builder, cond_node, true_block, scc_ir_builder_branch(&ctx->builder, cond_node, true_block,
false_block); false_block);
@@ -368,7 +386,7 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
scc_ir_builder_set_current_bblock(&ctx->builder, cond_block); scc_ir_builder_set_current_bblock(&ctx->builder, cond_block);
scc_ir_node_ref_t cond_node = scc_ir_node_ref_t cond_node =
scc_ast2ir_expr(ctx, stmt->while_stmt.cond); scc_ast2ir_expr(ctx, stmt->while_stmt.cond, false);
scc_ir_builder_branch(&ctx->builder, cond_node, body_block, exit_block); scc_ir_builder_branch(&ctx->builder, cond_node, body_block, exit_block);
scc_ir_builder_set_current_bblock(&ctx->builder, body_block); scc_ir_builder_set_current_bblock(&ctx->builder, body_block);
@@ -395,7 +413,7 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
scc_ir_builder_set_current_bblock(&ctx->builder, cond_block); scc_ir_builder_set_current_bblock(&ctx->builder, cond_block);
scc_ir_node_ref_t cond_node = scc_ir_node_ref_t cond_node =
scc_ast2ir_expr(ctx, stmt->while_stmt.cond); scc_ast2ir_expr(ctx, stmt->while_stmt.cond, false);
scc_ir_builder_branch(&ctx->builder, cond_node, body_block, exit_block); scc_ir_builder_branch(&ctx->builder, cond_node, body_block, exit_block);
scc_ir_builder_set_current_bblock(&ctx->builder, exit_block); scc_ir_builder_set_current_bblock(&ctx->builder, exit_block);
@@ -421,7 +439,7 @@ void scc_ast2ir_stmt(scc_ast2ir_ctx_t *ctx, scc_ast_stmt_t *stmt) {
case SCC_AST_STMT_RETURN: { case SCC_AST_STMT_RETURN: {
if (stmt->return_stmt.expr) { if (stmt->return_stmt.expr) {
scc_ir_node_ref_t ret_val_node = scc_ir_node_ref_t ret_val_node =
scc_ast2ir_expr(ctx, stmt->return_stmt.expr); scc_ast2ir_expr(ctx, stmt->return_stmt.expr, false);
scc_ir_builder_ret(&ctx->builder, ret_val_node); scc_ir_builder_ret(&ctx->builder, ret_val_node);
} else { } else {
scc_ir_builder_ret_void(&ctx->builder); scc_ir_builder_ret_void(&ctx->builder);
@@ -457,11 +475,14 @@ void scc_ast2ir_decl(scc_ast2ir_ctx_t *ctx, scc_ast_decl_t *decl) {
scc_ir_node_ref_t alloc_val_node = scc_ir_node_ref_t alloc_val_node =
scc_ir_builder_alloca(&ctx->builder, ir_type, decl->name); scc_ir_builder_alloca(&ctx->builder, ir_type, decl->name);
scc_hashtable_set(&ctx->node2ir, decl, (void *)(usize)alloc_val_node);
// 如果有初始化表达式 // 如果有初始化表达式
if (!decl->var.init) { if (!decl->var.init) {
break; break;
} }
scc_ir_node_ref_t init_val_node = scc_ast2ir_expr(ctx, decl->var.init); scc_ir_node_ref_t init_val_node =
scc_ast2ir_expr(ctx, decl->var.init, false);
scc_ir_builder_store(&ctx->builder, alloc_val_node, init_val_node); scc_ir_builder_store(&ctx->builder, alloc_val_node, init_val_node);
break; break;
} }
@@ -518,7 +539,7 @@ void scc_ast2ir_translation_unit(scc_ast2ir_ctx_t *ctx,
static u32 scc_hash_node(const void *key) { return (u32)(usize)key; } static u32 scc_hash_node(const void *key) { return (u32)(usize)key; }
static int scc_cmp_node(const void *key1, const void *key2) { static int scc_cmp_node(const void *key1, const void *key2) {
return key1 == key2; return (u32)(usize)key1 - (u32)(usize)key2;
} }
void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_type_abi_t *abi) { void scc_ast2ir_ctx_init(scc_ast2ir_ctx_t *ctx, const scc_type_abi_t *abi) {

View File

@@ -610,14 +610,14 @@ void scc_ir_dump_node_linear(scc_ir_dump_ctx_t *ctx,
remaining = sizeof(buff) - (p - buff); remaining = sizeof(buff) - (p - buff);
if (node->type != 0) { // if (node->type != 0) {
p += scc_snprintf(p, remaining, " `"); // p += scc_snprintf(p, remaining, " `");
remaining = sizeof(buff) - (p - buff); // remaining = sizeof(buff) - (p - buff);
// p += dump_type_to_buf(ctx, p, remaining, node->type); // // p += dump_type_to_buf(ctx, p, remaining, node->type);
// remaining = sizeof(buff) - (p - buff); // // remaining = sizeof(buff) - (p - buff);
p += scc_snprintf(p, remaining, "`"); // p += scc_snprintf(p, remaining, "`");
remaining = sizeof(buff) - (p - buff); // remaining = sizeof(buff) - (p - buff);
} // }
p += scc_snprintf(p, remaining, " = "); p += scc_snprintf(p, remaining, " = ");
remaining = sizeof(buff) - (p - buff); remaining = sizeof(buff) - (p - buff);

View File

@@ -321,7 +321,6 @@ static scc_ast_expr_op_t map_token_to_assign_op(scc_tok_type_t type) {
} }
} }
/* ---------------------------- 错误恢复辅助 ---------------------------- */
// 跳过直到遇到同步 token分号、右括号、逗号、EOF // 跳过直到遇到同步 token分号、右括号、逗号、EOF
static void parser_sync(scc_parser_t *parser) { static void parser_sync(scc_parser_t *parser) {
const scc_lexer_tok_t *tok_ptr; const scc_lexer_tok_t *tok_ptr;
@@ -340,7 +339,6 @@ static void parser_sync(scc_parser_t *parser) {
} }
} }
/* ---------------------------- 通用二元解析器 ---------------------------- */
static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser, static scc_ast_expr_t *parse_expression_with_precedence(scc_parser_t *parser,
int min_prec) { int min_prec) {
// 从最底层cast-expression开始 // 从最底层cast-expression开始
@@ -790,7 +788,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
Assert(expr != null); Assert(expr != null);
scc_ast_expr_identifier_init(expr, scc_cstring_as_cstr(&tok.lexeme), scc_ast_expr_identifier_init(expr, scc_cstring_as_cstr(&tok.lexeme),
tok.loc); tok.loc);
return expr; break;
} }
case SCC_TOK_INT_LITERAL: { case SCC_TOK_INT_LITERAL: {
if (!scc_parser_next_consume(parser, &tok)) if (!scc_parser_next_consume(parser, &tok))
@@ -799,7 +797,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
Assert(expr != null); Assert(expr != null);
scc_ast_expr_literal_int_init(expr, scc_cstring_as_cstr(&tok.lexeme), scc_ast_expr_literal_int_init(expr, scc_cstring_as_cstr(&tok.lexeme),
false, tok.loc); false, tok.loc);
return expr; break;
} }
case SCC_TOK_FLOAT_LITERAL: { case SCC_TOK_FLOAT_LITERAL: {
if (!scc_parser_next_consume(parser, &tok)) if (!scc_parser_next_consume(parser, &tok))
@@ -808,7 +806,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
Assert(expr != null); Assert(expr != null);
scc_ast_expr_literal_float_init(expr, scc_cstring_as_cstr(&tok.lexeme), scc_ast_expr_literal_float_init(expr, scc_cstring_as_cstr(&tok.lexeme),
false, tok.loc); false, tok.loc);
return expr; break;
} }
case SCC_TOK_CHAR_LITERAL: { case SCC_TOK_CHAR_LITERAL: {
if (!scc_parser_next_consume(parser, &tok)) if (!scc_parser_next_consume(parser, &tok))
@@ -817,7 +815,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
Assert(expr != null); Assert(expr != null);
scc_ast_expr_literal_char_init(expr, scc_cstring_as_cstr(&tok.lexeme), scc_ast_expr_literal_char_init(expr, scc_cstring_as_cstr(&tok.lexeme),
false, tok.loc); false, tok.loc);
return expr; break;
} }
case SCC_TOK_STRING_LITERAL: { case SCC_TOK_STRING_LITERAL: {
scc_cstring_t string = scc_cstring_create(); scc_cstring_t string = scc_cstring_create();
@@ -841,7 +839,7 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
// FIXME loc // FIXME loc
scc_ast_expr_literal_string_init(expr, scc_cstring_as_cstr(&string), scc_ast_expr_literal_string_init(expr, scc_cstring_as_cstr(&string),
true, tok.loc); true, tok.loc);
return expr; break;
} }
case SCC_TOK_L_PAREN: case SCC_TOK_L_PAREN:
scc_parser_next_consume(parser, null); scc_parser_next_consume(parser, null);
@@ -850,10 +848,16 @@ static scc_ast_expr_t *parse_primary_expression(scc_parser_t *parser) {
SCC_ERROR(scc_parser_got_current_pos(parser), SCC_ERROR(scc_parser_got_current_pos(parser),
"Expected ')' after expression"); "Expected ')' after expression");
} }
return expr; break;
default: default:
break;
}
if (expr == null) {
return null; return null;
} }
scc_parse_expr_sema(parser, expr);
return expr;
} }
scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) { scc_ast_expr_t *scc_parse_expression(scc_parser_t *parser) {

View File

@@ -18,15 +18,21 @@ static void expr_callback(void *context, scc_ast_node_type_t node_type,
if (node_type == SCC_AST_UNKNOWN || node == null) { if (node_type == SCC_AST_UNKNOWN || node == null) {
return; return;
} }
scc_ast_expr_t *decl = SCC_AST_CAST_TO(scc_ast_expr_t, node); scc_ast_expr_t *expr = SCC_AST_CAST_TO(scc_ast_expr_t, node);
if (node_type == SCC_AST_EXPR_IDENTIFIER) { if (node_type == SCC_AST_EXPR_IDENTIFIER) {
scc_ast_node_t *node = scc_ast_node_t *node =
scc_sema_symtab_lookup_symbol(sema_symtab, decl->identifier.name); scc_sema_symtab_lookup_symbol(sema_symtab, expr->identifier.name);
if (node == null) { if (node == null) {
SCC_ERROR(decl->base.loc, "Identifier '%s' not found", SCC_ERROR(expr->base.loc, "Identifier '%s' not found",
decl->identifier.name); expr->identifier.name);
} else if (!SCC_AST_IS_A(scc_ast_decl_t, node)) {
SCC_ERROR(expr->base.loc, "Identifier '%s' is not a variable",
expr->identifier.name);
} else {
expr->identifier._target = SCC_AST_CAST_TO(scc_ast_decl_t, node);
} }
} }
return; return;
} }
@@ -50,6 +56,8 @@ static void stmt_callback(void *context, scc_ast_node_type_t node_type,
static void decl_callback(void *context, scc_ast_node_type_t node_type, static void decl_callback(void *context, scc_ast_node_type_t node_type,
void *node) { void *node) {
scc_sema_symtab_t *sema_symtab = context; scc_sema_symtab_t *sema_symtab = context;
// Function declaration scope
if (node_type == scc_ast_decl_t_BEGIN) { if (node_type == scc_ast_decl_t_BEGIN) {
scc_sema_symtab_enter_scope(sema_symtab); scc_sema_symtab_enter_scope(sema_symtab);
return; return;
@@ -67,27 +75,31 @@ static void decl_callback(void *context, scc_ast_node_type_t node_type,
if (decl->name == null) { if (decl->name == null) {
return; return;
} }
if (decl->base.type == SCC_AST_DECL_STRUCT) { if (node_type == SCC_AST_DECL_STRUCT) {
scc_ast_type_struct_init(type, decl->name, decl, decl->base.loc); scc_ast_type_struct_init(type, decl->name, decl, decl->base.loc);
scc_cstring_t name = scc_cstring_from_cstr("$S_"); scc_cstring_t name = scc_cstring_from_cstr("$S_");
scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name)); scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name));
scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name), scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name),
&type->base); &type->base);
} else if (decl->base.type == SCC_AST_DECL_UNION) { } else if (node_type == SCC_AST_DECL_UNION) {
scc_ast_type_union_init(type, decl->name, decl, decl->base.loc); scc_ast_type_union_init(type, decl->name, decl, decl->base.loc);
scc_cstring_t name = scc_cstring_from_cstr("$U_"); scc_cstring_t name = scc_cstring_from_cstr("$U_");
scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name)); scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name));
scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name), scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name),
&type->base); &type->base);
} else if (decl->base.type == SCC_AST_DECL_ENUM) { } else if (node_type == SCC_AST_DECL_ENUM) {
scc_ast_type_enum_init(type, decl->name, decl, decl->base.loc); scc_ast_type_enum_init(type, decl->name, decl, decl->base.loc);
scc_cstring_t name = scc_cstring_from_cstr("$E_"); scc_cstring_t name = scc_cstring_from_cstr("$E_");
scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name)); scc_cstring_append_cstr(&name, decl->name, scc_strlen(decl->name));
scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name), scc_sema_symtab_add_symbol(sema_symtab, scc_cstring_as_cstr(&name),
&type->base); &type->base);
} else if (decl->base.type == SCC_AST_DECL_TYPEDEF) { } else if (node_type == SCC_AST_DECL_TYPEDEF) {
scc_ast_type_typedef_init(type, decl->name, decl, decl->base.loc); scc_ast_type_typedef_init(type, decl->name, decl, decl->base.loc);
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base); scc_sema_symtab_add_symbol(sema_symtab, decl->name, &type->base);
} else if (node_type == SCC_AST_DECL_VAR) {
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &decl->base);
} else if (node_type == SCC_AST_DECL_PARAM) {
scc_sema_symtab_add_symbol(sema_symtab, decl->name, &decl->base);
} }
return; return;
} }

View File

@@ -467,7 +467,7 @@ static void test_parser_unit(void) {
scc_ast_translation_unit_init(&tu, &decls, scc_pos_create()); scc_ast_translation_unit_init(&tu, &decls, scc_pos_create());
SCC_CHECK_AST_WITH_SEMA( SCC_CHECK_AST_WITH_SEMA(
&tu.base, &tu.base,
"typedef long long size_t;" "typedef int size_t;"
"typedef void *(*func_t)(size_t a, int b, ...);", "typedef void *(*func_t)(size_t a, int b, ...);",
scc_parse_translation_unit); scc_parse_translation_unit);
} }

View File

@@ -16,10 +16,6 @@
#define sccf_size_t uint64_t #define sccf_size_t uint64_t
#define sccf_isize_t int64_t #define sccf_isize_t int64_t
#ifdef __cplusplus
extern "C" {
#endif
/** SCCF魔数 */ /** SCCF魔数 */
#define SCCF_MAGIC "SCCFmt\0\0" #define SCCF_MAGIC "SCCFmt\0\0"
@@ -47,7 +43,7 @@ typedef enum {
SCCF_SYM_TYPE_UNDEF = 0, ///< 未定义 SCCF_SYM_TYPE_UNDEF = 0, ///< 未定义
SCCF_SYM_TYPE_FUNC = 1, ///< 函数 SCCF_SYM_TYPE_FUNC = 1, ///< 函数
SCCF_SYM_TYPE_DATA = 2, ///< 数据 SCCF_SYM_TYPE_DATA = 2, ///< 数据
SCCF_SYM_TYPE_OBJECT = 3, ///< 对象 SCCF_SYM_TYPE_EXTERN = 3, ///< 外部符号
} sccf_sym_type_t; } sccf_sym_type_t;
/** 符号绑定类型 */ /** 符号绑定类型 */
@@ -73,7 +69,7 @@ typedef enum {
SCCF_SECT_UNINIT_DATA = 4, ///< BSS段(未初始化数据) SCCF_SECT_UNINIT_DATA = 4, ///< BSS段(未初始化数据)
SCCF_SECT_SYMTAB = 5, ///< 符号表 SCCF_SECT_SYMTAB = 5, ///< 符号表
SCCF_SECT_STRTAB = 6, ///< 字符串表 SCCF_SECT_STRTAB = 6, ///< 字符串表
SCCF_SECT_RELOC = 7, ///< 重定位表 SCCF_SECT_RELOCS = 7, ///< 重定位表
} sccf_sect_type_t; } sccf_sect_type_t;
/** 重定位类型 */ /** 重定位类型 */
@@ -99,37 +95,37 @@ typedef struct sccf_header {
* @brief SCCF段 * @brief SCCF段
*/ */
typedef struct { typedef struct {
sccf_byte_t name[8]; ///< 段名称 仅供展示 eg. emoji or ".text" sccf_byte_t name[8]; ///< 段名称 仅供展示 eg. emoji or ".text"
sccf_enum_t scf_sect_type; ///< 段类型 (内部实际区分的方式) sccf_enum_t sccf_sect_type; ///< 段类型 (内部实际区分的方式)
sccf_size_t size; ///< 段数据实际的大小 sccf_size_t size; ///< 段数据实际的大小
sccf_size_t data_size; ///< 段数据的有效数据大小 sccf_size_t data_size; ///< 段数据的有效数据大小
sccf_size_t addralign; ///< 内存对齐要求 (字节对齐, 如 1,2,4,8,...) sccf_size_t addralign; ///< 内存对齐要求 (字节对齐, 如 1,2,4,8,...)
sccf_size_t info; ///< 段信息 (如条目数,链接索引等) sccf_size_t info; ///< 段信息 (如条目数,链接索引等)
sccf_size_t reserved[2]; ///< 保留 sccf_size_t reserved[2]; ///< 保留
} sccf_sect_header_t; } sccf_sect_header_t;
/** /**
* @brief SCCF符号表 * @brief SCCF符号表
*/ */
typedef struct { typedef struct {
sccf_size_t name_offset; ///< 符号名称在字符串表中的偏移量 sccf_size_t name_offset; ///< 符号名称在字符串表中的偏移量
sccf_enum_t scf_sym_type; ///< 符号类型 sccf_enum_t sccf_sym_type; ///< 符号类型
sccf_enum_t scf_sym_bind; ///< 符号绑定类型 sccf_enum_t sccf_sym_bind; ///< 符号绑定类型
sccf_enum_t scf_sym_vis; ///< 符号可见性 sccf_enum_t sccf_sym_vis; ///< 符号可见性
sccf_enum_t scf_sect_type; ///< 该符号的段类型 sccf_enum_t sccf_sect_type; ///< 该符号的段类型
sccf_size_t scf_sect_offset; ///< 该符号在段中的偏移量 sccf_size_t sccf_sect_offset; ///< 该符号在段中的偏移量
sccf_size_t scf_sym_size; ///< 该符号符号选中的大小 sccf_size_t sccf_sym_size; ///< 该符号选中的大小
} sccf_sym_t; } sccf_sym_t;
/** /**
* @brief SCCF重定向条目 * @brief SCCF重定向条目
*/ */
typedef struct { typedef struct {
sccf_size_t offset; ///< 在数据段中的偏移量
sccf_size_t sym_idx; ///< 符号索引
sccf_enum_t type; ///< 重定位类型 sccf_enum_t type; ///< 重定位类型
sccf_enum_t sect_type; ///< 段类型(代码段/数据段) sccf_enum_t sect_type; ///< 需要重定位的段类型(代码段/数据段)
sccf_isize_t addend; ///< 加数 sccf_size_t sym_idx; ///< 符号索引(重定向指向的符号)
sccf_size_t offset; ///< 在段中的偏移量(用于重定向的地址)
sccf_isize_t addend; ///< 加数(用于获取相对位置时PC的额外值)
} sccf_reloc_t; } sccf_reloc_t;
/** /**
@@ -158,8 +154,4 @@ typedef struct {
* }; * };
*/ */
#ifdef __cplusplus
}
#endif
#endif /* __SCC_FORMAT_H__ */ #endif /* __SCC_FORMAT_H__ */

View File

@@ -4,24 +4,66 @@
#include "sccf_utils.h" #include "sccf_utils.h"
#include <scc_utils.h> #include <scc_utils.h>
typedef SCC_VEC(sccf_sym_t) sccf_sym_vec_t;
typedef SCC_VEC(sccf_reloc_t) sccf_reloc_vec_t;
typedef struct { typedef struct {
sccf_t sccf; sccf_t sccf;
int aligned; int aligned;
scc_strpool_t strpool; sccf_strtab_t strtab;
scc_hashtable_t str2offset;
sccf_sym_vec_t syms;
sccf_reloc_vec_t relocs; sccf_reloc_vec_t relocs;
sccf_sym_vec_t symtab;
scc_hashtable_t str2sym;
scc_hashtable_t str2offset;
} sccf_builder_t; } sccf_builder_t;
void sccf_builder_init(sccf_builder_t *builder); void sccf_builder_init(sccf_builder_t *builder);
usize sccf_builder_add_symbol(sccf_builder_t *builder, const char *name,
sccf_sym_t *sym);
usize sccf_builder_get_symbol_idx(sccf_builder_t *builder, const char *name);
static inline sccf_sym_t *
sccf_builder_get_symbol_unsafe(sccf_builder_t *builder, usize idx) {
return &scc_vec_at(builder->symtab, idx);
}
void sccf_builder_add_reloc(sccf_builder_t *builder, sccf_reloc_t reloc);
/**
* @brief 必须确保参数合法
*
* @param builder
* @param sect_header
* @param sect_data
*/
void sccf_builder_add_section(sccf_builder_t *builder, void sccf_builder_add_section(sccf_builder_t *builder,
sccf_sect_header_t *sect_header, sccf_sect_header_t *sect_header,
sccf_sect_data_t *sect_data); sccf_sect_data_t *sect_data);
static inline void sccf_builder_add_text_section(sccf_builder_t *builder,
sccf_sect_data_t *sect_data) {
sccf_sect_header_t text_header = {
.name = ".text",
.addralign = 1,
.data_size = scc_vec_size(*sect_data),
.sccf_sect_type = SCCF_SECT_CODE,
.size = scc_vec_size(*sect_data),
.info = 0,
.reserved = {0},
};
sccf_builder_add_section(builder, &text_header, sect_data);
}
static inline void sccf_builder_add_data_section(sccf_builder_t *builder,
sccf_sect_data_t *sect_data) {
sccf_sect_header_t text_header = {
.name = ".data",
.addralign = 1,
.data_size = scc_vec_size(*sect_data),
.sccf_sect_type = SCCF_SECT_DATA,
.size = scc_vec_size(*sect_data),
.info = 0,
.reserved = {0},
};
sccf_builder_add_section(builder, &text_header, sect_data);
}
const sccf_t *sccf_builder_to_sccf(sccf_builder_t *builder);
void sccf_builder_to_buffer(sccf_builder_t *builder, sccf_buffer_t *buffer); void sccf_builder_to_buffer(sccf_builder_t *builder, sccf_buffer_t *buffer);
void sccf_builder_to_file(sccf_builder_t *builder, const char *file_path); void sccf_builder_to_file(sccf_builder_t *builder, const char *file_path);

View File

@@ -11,7 +11,7 @@ typedef struct {
sccf_vec_t link_sccfs; sccf_vec_t link_sccfs;
scc_strpool_t strpool; scc_strpool_t strpool;
scc_hashtable_t str2offset; scc_hashtable_t str2offset;
sccf_sym_vec_t syms; sccf_sym_vec_t symtab;
sccf_reloc_vec_t relocs; sccf_reloc_vec_t relocs;
} sccf_linker_t; } sccf_linker_t;

View File

@@ -100,7 +100,7 @@ static inline usize sccf_find_sect_by_type(u8 *base, sccf_enum_t type) {
const sccf_header_t *hdr = (const sccf_header_t *)base; const sccf_header_t *hdr = (const sccf_header_t *)base;
for (usize i = 0; i < (usize)hdr->sect_header_num; ++i) { for (usize i = 0; i < (usize)hdr->sect_header_num; ++i) {
sccf_sect_header_t *sh = sccf_sect_header(base, i); sccf_sect_header_t *sh = sccf_sect_header(base, i);
if (sh->scf_sect_type == type) if (sh->sccf_sect_type == type)
return i; return i;
} }
return (usize)hdr->sect_header_num; return (usize)hdr->sect_header_num;
@@ -167,6 +167,9 @@ typedef SCC_VEC(u8) sccf_buffer_t;
typedef SCC_VEC(u8) sccf_sect_data_t; typedef SCC_VEC(u8) sccf_sect_data_t;
typedef SCC_VEC(sccf_sect_data_t) sccf_sect_data_vec_t; typedef SCC_VEC(sccf_sect_data_t) sccf_sect_data_vec_t;
typedef SCC_VEC(sccf_sect_header_t) sccf_sect_header_vec_t; typedef SCC_VEC(sccf_sect_header_t) sccf_sect_header_vec_t;
typedef SCC_VEC(sccf_sym_t) sccf_sym_vec_t;
typedef SCC_VEC(sccf_reloc_t) sccf_reloc_vec_t;
typedef SCC_VEC(char) sccf_strtab_t;
typedef struct { typedef struct {
sccf_header_t header; sccf_header_t header;
@@ -241,7 +244,7 @@ static inline void sccf_parse(sccf_t *sccf, sccf_buffer_t *buffer, int copied) {
* @param[in] sccf * @param[in] sccf
* @return usize * @return usize
*/ */
static inline usize sccf_size(sccf_t *sccf) { static inline usize sccf_size(const sccf_t *sccf) {
if (scc_vec_size(sccf->sect_datas) != scc_vec_size(sccf->sect_headers) || if (scc_vec_size(sccf->sect_datas) != scc_vec_size(sccf->sect_headers) ||
scc_vec_size(sccf->sect_headers) != sccf->header.sect_header_num) { scc_vec_size(sccf->sect_headers) != sccf->header.sect_header_num) {
Panic(); Panic();
@@ -265,7 +268,7 @@ static inline usize sccf_size(sccf_t *sccf) {
* @param[in] sccf * @param[in] sccf
* @param[out] buffer * @param[out] buffer
*/ */
static inline void sccf_write(sccf_t *sccf, sccf_buffer_t *buffer) { static inline void sccf_write(const sccf_t *sccf, sccf_buffer_t *buffer) {
usize size = sccf_size(sccf); usize size = sccf_size(sccf);
if (scc_vec_size(*buffer) < size) { if (scc_vec_size(*buffer) < size) {
scc_vec_realloc(*buffer, size); scc_vec_realloc(*buffer, size);

View File

@@ -3,12 +3,53 @@
void sccf_builder_init(sccf_builder_t *builder) { void sccf_builder_init(sccf_builder_t *builder) {
builder->aligned = 64; builder->aligned = 64;
sccf_init(&builder->sccf); sccf_init(&builder->sccf);
scc_strpool_init(&builder->strpool);
scc_hashtable_init(&builder->str2offset, scc_hashtable_init(&builder->str2offset,
(scc_hashtable_hash_func_t)scc_strhash32, (scc_hashtable_hash_func_t)scc_strhash32,
(scc_hashtable_equal_func_t)scc_strcmp); (scc_hashtable_equal_func_t)scc_strcmp);
scc_hashtable_init(&builder->str2sym,
(scc_hashtable_hash_func_t)scc_strhash32,
(scc_hashtable_equal_func_t)scc_strcmp);
scc_vec_init(builder->strtab);
scc_vec_init(builder->relocs); scc_vec_init(builder->relocs);
scc_vec_init(builder->syms); scc_vec_init(builder->symtab);
///< Push null
scc_vec_push(builder->strtab, (char)'\0');
///< Push null
scc_vec_push(builder->symtab, (sccf_sym_t){0});
}
usize sccf_builder_add_symbol(sccf_builder_t *builder, const char *name,
sccf_sym_t *sym) {
usize offset = 0;
offset = (usize)scc_hashtable_get(&builder->str2offset, name);
if (offset == 0) {
offset = scc_vec_size(builder->strtab);
scc_hashtable_set(&builder->str2offset, name, (void *)offset);
while (*name) {
scc_vec_push(builder->strtab, *name);
name++;
}
scc_vec_push(builder->strtab, '\0');
}
sym->name_offset = offset;
usize sym_idx = scc_vec_size(builder->symtab);
offset = (usize)scc_hashtable_get(&builder->str2sym, name);
if (offset == 0) {
scc_hashtable_set(&builder->str2sym, name, (void *)sym_idx);
}
scc_vec_push(builder->symtab, *sym);
return sym_idx;
}
usize sccf_builder_get_symbol_idx(sccf_builder_t *builder, const char *name) {
usize offset = (usize)scc_hashtable_get(&builder->str2sym, name);
return offset;
}
void sccf_builder_add_reloc(sccf_builder_t *builder, sccf_reloc_t reloc) {
scc_vec_push(builder->relocs, reloc);
} }
void sccf_builder_add_section(sccf_builder_t *builder, void sccf_builder_add_section(sccf_builder_t *builder,
@@ -20,14 +61,58 @@ void sccf_builder_add_section(sccf_builder_t *builder,
scc_vec_push(builder->sccf.sect_datas, *sect_data); scc_vec_push(builder->sccf.sect_datas, *sect_data);
} }
void sccf_builder_to_buffer(sccf_builder_t *builder, sccf_buffer_t *buffer) { const sccf_t *sccf_builder_to_sccf(sccf_builder_t *builder) {
Assert(builder != null && buffer != null);
// TODO symtab strtab reloc // TODO symtab strtab reloc
// sccf_sect_header_t symtab_header; // sccf_sect_header_t symtab_header;
// sccf_sect_data_t symtab_data; // sccf_sect_data_t symtab_data;
// sccf_builder_add_section(builder, &symtab_header, &symtab_data); sccf_sect_header_t sect_header;
if (scc_vec_size(builder->strtab)) {
sect_header = (sccf_sect_header_t){
.name = ".strtab",
.info = 0,
.data_size = scc_vec_size(builder->strtab),
.addralign = 1,
.size = scc_vec_size(builder->strtab),
.sccf_sect_type = SCCF_SECT_STRTAB,
};
// TODO 转换成 u8[]
sccf_builder_add_section(builder, &sect_header,
(void *)&builder->strtab);
}
sccf_write(&builder->sccf, buffer); if (scc_vec_size(builder->symtab)) {
sect_header = (sccf_sect_header_t){
.name = ".symtab",
.info = 0,
.data_size = scc_vec_size(builder->symtab),
.addralign = 1,
.size = scc_vec_size(builder->symtab),
.sccf_sect_type = SCCF_SECT_SYMTAB,
};
// TODO 转换成 u8[]
sccf_builder_add_section(builder, &sect_header,
(void *)&builder->symtab);
}
if (scc_vec_size(builder->relocs)) {
sect_header = (sccf_sect_header_t){
.name = ".relocs",
.info = 0,
.data_size = scc_vec_size(builder->relocs),
.addralign = 1,
.size = scc_vec_size(builder->relocs),
.sccf_sect_type = SCCF_SECT_RELOCS,
};
// TODO 转换成 u8[]
sccf_builder_add_section(builder, &sect_header,
(void *)&builder->relocs);
}
return &builder->sccf;
}
void sccf_builder_to_buffer(sccf_builder_t *builder, sccf_buffer_t *buffer) {
Assert(builder != null && buffer != null);
sccf_write(sccf_builder_to_sccf(builder), buffer);
} }
void sccf_builder_to_file(sccf_builder_t *builder, const char *file_path) { void sccf_builder_to_file(sccf_builder_t *builder, const char *file_path) {

View File

@@ -12,12 +12,12 @@ typedef struct {
u32 section_offset; ///< 在idata中的偏移 u32 section_offset; ///< 在idata中的偏移
} scc_pe_hnt_builder_t; } scc_pe_hnt_builder_t;
typedef SCC_VEC(const char *) scc_winpe_name_vec_t; typedef SCC_VEC(const char *) scc_pe_name_vec_t;
typedef struct { typedef struct {
const char *name; const char *name;
scc_winpe_name_vec_t symbol_names; scc_pe_name_vec_t symbol_names;
} scc_winpe_idata_lib_t; } scc_pe_idata_lib_t;
typedef SCC_VEC(scc_winpe_idata_lib_t) scc_pe_idata_lib_vec_t; typedef SCC_VEC(scc_pe_idata_lib_t) scc_pe_idata_lib_vec_t;
typedef struct { typedef struct {
scc_pe_buffer_t buffer; ///< 导入表数据 scc_pe_buffer_t buffer; ///< 导入表数据

View File

@@ -71,7 +71,7 @@ u32 scc_pe_reserve_idata(scc_pe_idata_builder_t *builder) {
sizeof(IMAGE_IMPORT_DESCRIPTOR); sizeof(IMAGE_IMPORT_DESCRIPTOR);
scc_vec_foreach(builder->idata_libs, i) { scc_vec_foreach(builder->idata_libs, i) {
scc_winpe_idata_lib_t *lib = &scc_vec_at(builder->idata_libs, i); scc_pe_idata_lib_t *lib = &scc_vec_at(builder->idata_libs, i);
idata_size += (scc_vec_size(lib->symbol_names) + 1) * 2 * idata_size += (scc_vec_size(lib->symbol_names) + 1) * 2 *
sizeof(IMAGE_THUNK_DATA64); sizeof(IMAGE_THUNK_DATA64);
scc_winpe_hnt_builder_push(&builder->hnt_builder, lib->name, 0); scc_winpe_hnt_builder_push(&builder->hnt_builder, lib->name, 0);
@@ -98,7 +98,7 @@ scc_pe_buffer_t scc_pe_construct_idata(scc_pe_idata_builder_t *builder,
usize current_offset = usize current_offset =
(import_file_count + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR); (import_file_count + 1) * sizeof(IMAGE_IMPORT_DESCRIPTOR);
scc_vec_foreach(builder->idata_libs, i) { scc_vec_foreach(builder->idata_libs, i) {
scc_winpe_idata_lib_t *lib = &scc_vec_at(builder->idata_libs, i); scc_pe_idata_lib_t *lib = &scc_vec_at(builder->idata_libs, i);
scc_winpe_lookup_table_vec_t lookup_table; scc_winpe_lookup_table_vec_t lookup_table;
scc_vec_init(lookup_table); scc_vec_init(lookup_table);

View File

@@ -33,7 +33,7 @@ int main() {
scc_pe_idata_builder_t idata_builder; scc_pe_idata_builder_t idata_builder;
scc_pe_idata_lib_vec_t idata_libs; scc_pe_idata_lib_vec_t idata_libs;
scc_vec_init(idata_libs); scc_vec_init(idata_libs);
scc_winpe_idata_lib_t ucrtbase; scc_pe_idata_lib_t ucrtbase;
ucrtbase.name = "ucrtbase.dll"; ucrtbase.name = "ucrtbase.dll";
scc_vec_init(ucrtbase.symbol_names); scc_vec_init(ucrtbase.symbol_names);
scc_vec_push(ucrtbase.symbol_names, "puts"); scc_vec_push(ucrtbase.symbol_names, "puts");

View File

@@ -0,0 +1,12 @@
[package]
name = "sccf2target"
version = "0.1.0"
authors = []
description = ""
dependencies = [
{ name = "sccf", path = "../../sccf" },
{ name = "pe", path = "../pe" },
]
# features = {}
# default_features = []

View File

@@ -0,0 +1,4 @@
#include <scc_pe_builder.h>
#include <sccf_builder.h>
void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf);

View File

@@ -0,0 +1,69 @@
#include <sccf.h>
#include <sccf2pe.h>
#include <sccf_builder.h>
#include <stdio.h>
int main() {
char data[] = "Hello, World from SCC PE Builder!\n\0";
/* clang-format off */
char code[] = {
// sub rsp, 0x28 ; 为函数调用分配栈空间
0x48, 0x83, 0xEC, 0x28,
// lea rcx, [rip + data_offset] ; 将字符串地址加载到RCX第一个参数
0x48, 0x8D, 0x0D, 0x00, 0x00, 0x00, 0x00,
// call qword ptr [rip + puts_iat] ; 通过IAT调用puts
0xFF, 0x15, 0x00, 0x00, 0x00, 0x00,
// add rsp, 0x28 ; 恢复栈空间
0x48, 0x83, 0xC4, 0x28,
// xor eax, eax ; 设置返回值为0
0x33, 0xC0,
// ret ; 返回
0xC3,
};
/* clang-format on */
sccf_builder_t builder;
sccf_builder_init(&builder);
sccf_sect_data_t text_section = {
.data = (u8 *)code, .size = sizeof(code), .cap = sizeof(code)};
sccf_sect_data_t data_section = {
.data = (u8 *)data, .size = sizeof(data), .cap = sizeof(data)};
sccf_builder_add_text_section(&builder, &text_section);
sccf_builder_add_data_section(&builder, &data_section);
usize str_idx =
sccf_builder_add_symbol(&builder, "str_data",
&(sccf_sym_t){
.sccf_sect_offset = 0,
.sccf_sect_type = SCCF_SECT_DATA,
.sccf_sym_bind = SCCF_SYM_BIND_GLOBAL,
.sccf_sym_size = sizeof(data),
.sccf_sym_type = SCCF_SYM_TYPE_DATA,
.sccf_sym_vis = SCCF_SYM_VIS_DEFAULT,
});
usize puts_idx =
sccf_builder_add_symbol(&builder, "puts",
&(sccf_sym_t){
.sccf_sect_offset = 0,
.sccf_sect_type = SCCF_SECT_NONE,
.sccf_sym_bind = SCCF_SYM_BIND_GLOBAL,
.sccf_sym_size = 8,
.sccf_sym_type = SCCF_SYM_TYPE_EXTERN,
.sccf_sym_vis = SCCF_SYM_VIS_DEFAULT,
});
sccf_builder_add_reloc(&builder, (sccf_reloc_t){.addend = 4,
.offset = 7,
.sect_type = SCCF_SECT_CODE,
.sym_idx = str_idx,
.type = SCCF_RELOC_REL});
sccf_builder_add_reloc(&builder, (sccf_reloc_t){.addend = 4,
.offset = 13,
.sect_type = SCCF_SECT_CODE,
.sym_idx = puts_idx,
.type = SCCF_RELOC_REL});
const sccf_t *sccf = sccf_builder_to_sccf(&builder);
scc_pe_builder_t pe_builder;
sccf2pe(&pe_builder, sccf);
scc_pe_dump_to_file(&pe_builder, __FILE__ "/../../test.exe");
}

View File

@@ -0,0 +1,229 @@
#include <scc_pe_idata.h>
#include <sccf2pe.h>
#include <sccf_utils.h>
typedef struct {
scc_hashtable_t str2libsym;
scc_pe_idata_lib_vec_t idata_libs;
} pe_idata_lib_ctx_t;
static void load_from_def(pe_idata_lib_ctx_t *ctx, const char *file_path,
const char *dll_name) {
/*
LIBRARY <path name>
EXPORTS
name @number
...
*/
scc_cstring_t fpath = scc_cstring_from_cstr(file_path);
scc_cstring_append_ch(&fpath, '/');
scc_cstring_append_cstr(&fpath, dll_name, scc_strlen(dll_name));
scc_cstring_append_cstr(&fpath, ".def", 4);
const char *fname = scc_cstring_as_cstr(&fpath);
scc_file_t fp = scc_fopen(fname, SCC_FILE_READ);
if (fp == null) {
LOG_ERROR("load_from_def file read error: %s", fname);
return;
}
usize fsize = scc_fsize(fp);
char *buffer = scc_malloc(fsize);
Assert(buffer != null);
usize read_size = scc_fread(fp, buffer, fsize);
Assert(read_size == fsize);
scc_fclose(fp);
scc_pe_name_vec_t symbol_names;
usize line = 0;
for (usize i = 0; i < fsize; i += 1) {
if (buffer[i] == '\n') {
line += 1;
}
if (line < 2) {
continue;
}
if (buffer[i] == ' ') {
continue;
}
for (usize j = i; j < fsize; j += 1) {
if (buffer[j] == ' ') {
buffer[j] = '\0';
break;
}
}
// FIXME memory leak
scc_hashtable_set(&ctx->str2libsym, buffer + i, (void *)dll_name);
}
}
static void pe_idata_lib_init(pe_idata_lib_ctx_t *ctx) {
// Got .dll.def
scc_hashtable_init(&ctx->str2libsym,
(scc_hashtable_hash_func_t)scc_strhash32,
(scc_hashtable_equal_func_t)scc_strcmp);
scc_vec_init(ctx->idata_libs);
load_from_def(ctx, "./.dll_def", "ucrtbase.dll");
}
static cbool pe_idata_get(pe_idata_lib_ctx_t *ctx, const char *name) {
const char *lib_name = scc_hashtable_get(&ctx->str2libsym, name);
if (lib_name == null) {
return false;
}
scc_pe_idata_lib_t *lib = null;
scc_vec_foreach(ctx->idata_libs, i) {
scc_pe_idata_lib_t *idata_lib = &scc_vec_at(ctx->idata_libs, i);
if (scc_strcmp(lib_name, idata_lib->name) == 0) {
lib = idata_lib;
break;
}
}
if (lib == null) {
scc_pe_idata_lib_t new_lib;
new_lib.name = lib_name;
scc_vec_init(new_lib.symbol_names);
scc_vec_push(ctx->idata_libs, new_lib);
lib = &scc_vec_at(ctx->idata_libs, scc_vec_size(ctx->idata_libs) - 1);
}
scc_vec_push(lib->symbol_names, name);
return true;
}
void sccf2pe(scc_pe_builder_t *builder, const sccf_t *sccf) {
scc_pe_builder_init(builder, true, 4096, 512);
sccf_strtab_t strtab;
scc_vec_init(strtab);
sccf_reloc_vec_t relocs;
scc_vec_init(relocs);
sccf_sym_vec_t symtab;
scc_vec_init(symtab);
sccf_sect_data_t *text_data = null;
scc_pe_reserve_header(builder, 3);
scc_pe_section_range code_range = {0};
scc_pe_section_range data_range = {0};
scc_pe_section_range idata_range = {0};
scc_vec_foreach(sccf->sect_headers, i) {
sccf_sect_header_t *sect_header = &scc_vec_at(sccf->sect_headers, i);
sccf_sect_data_t *sect_data = &scc_vec_at(sccf->sect_datas, i);
if (sect_header->sccf_sect_type == SCCF_SECT_CODE) {
text_data = sect_data;
code_range = scc_pe_reserve_text_section_header(
builder, scc_vec_size(*sect_data));
} else if (sect_header->sccf_sect_type == SCCF_SECT_DATA) {
data_range = scc_pe_reserve_data_section_header(
builder, scc_vec_size(*sect_data));
} else if (sect_header->sccf_sect_type == SCCF_SECT_STRTAB) {
scc_vec_unsafe_from_buffer(
strtab, (char *)scc_vec_unsafe_get_data(*sect_data),
scc_vec_size(*sect_data));
} else if (sect_header->sccf_sect_type == SCCF_SECT_RELOCS) {
scc_vec_unsafe_from_buffer(
relocs, (sccf_reloc_t *)scc_vec_unsafe_get_data(*sect_data),
scc_vec_size(*sect_data));
} else if (sect_header->sccf_sect_type == SCCF_SECT_SYMTAB) {
scc_vec_unsafe_from_buffer(
symtab, (sccf_sym_t *)scc_vec_unsafe_get_data(*sect_data),
scc_vec_size(*sect_data));
}
}
pe_idata_lib_ctx_t idata_lib_ctx;
pe_idata_lib_init(&idata_lib_ctx);
scc_vec_foreach(symtab, i) {
sccf_sym_t *sym = &scc_vec_at(symtab, i);
if (sym->sccf_sym_type == SCCF_SYM_TYPE_EXTERN) {
const char *name =
(const char *)&scc_vec_at(strtab, sym->name_offset);
if (pe_idata_get(&idata_lib_ctx, name) == false) {
LOG_ERROR("link error: symbol [%s] not found", name);
}
}
}
scc_pe_idata_builder_t idata_builder;
scc_pe_idata_builder_init(&idata_builder, &idata_lib_ctx.idata_libs);
u32 idata_size = scc_pe_reserve_idata(&idata_builder);
idata_range = scc_pe_reserve_idata_section_header(builder, idata_size);
scc_pe_buffer_t idata_buffer =
scc_pe_construct_idata(&idata_builder, &idata_range);
u32 entry_point_offset = 0;
u64 base_address = 0x140000000;
u32 entry_point = code_range.virual_address + entry_point_offset;
scc_pe_config_t config = (scc_pe_config_t){
.machine = IMAGE_FILE_MACHINE_AMD64,
.time_date_stamp = 0,
.characteristics =
IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_LARGE_ADDRESS_AWARE,
.major_linker_version = 14,
.minor_linker_version = 0,
.address_of_entry_point = entry_point,
.image_base = base_address,
.major_operating_system_version = 6,
.minor_operating_system_version = 0,
.major_image_version = 0,
.minor_image_version = 0,
.major_subsystem_version = 6,
.minor_subsystem_version = 0,
.subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI,
.dll_characteristics = IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA |
IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE |
IMAGE_DLLCHARACTERISTICS_NX_COMPAT,
.size_of_stack_reserve = 0x100000,
.size_of_stack_commit = 0x1000,
.size_of_heap_reserve = 0x100000,
.size_of_heap_commit = 0x1000,
};
scc_vec_foreach(relocs, i) {
sccf_reloc_t *reloc = &scc_vec_at(relocs, i);
sccf_sym_t *sym = &scc_vec_at(symtab, reloc->sym_idx);
const char *name = &scc_vec_at(strtab, sym->name_offset);
u32 rva = 0;
if (sym->sccf_sym_type == SCCF_SYM_TYPE_EXTERN) {
rva = scc_pe_idata_get_symbol_rva(&idata_builder, name);
} else if (sym->sccf_sect_type == SCCF_SECT_DATA) {
rva = data_range.virual_address + sym->sccf_sect_offset;
} else if (sym->sccf_sect_type == SCCF_SECT_CODE) {
rva = code_range.virual_address + sym->sccf_sect_offset;
} else {
Panic("unsupported reloc symbol type");
}
Assert(rva != 0);
if (reloc->type == SCCF_RELOC_ABS) {
TODO();
}
Assert(reloc->sect_type == SCCF_SECT_CODE);
rva -= code_range.virual_address + reloc->offset + reloc->addend;
Assert(text_data != null);
// FIXME 需要确保宿主机与目标机器大小端一致
*(u32 *)(scc_vec_unsafe_get_data(*text_data) + reloc->offset) = rva;
}
scc_pe_write_header(builder, &config);
scc_vec_foreach(sccf->sect_headers, i) {
sccf_sect_header_t *sect_header = &scc_vec_at(sccf->sect_headers, i);
sccf_sect_data_t *sect_data = &scc_vec_at(sccf->sect_datas, i);
if (sect_header->sccf_sect_type == SCCF_SECT_CODE) {
scc_pe_write_section(builder, &code_range,
(u8 *)scc_vec_unsafe_get_data(*sect_data),
scc_vec_size(*sect_data));
} else if (sect_header->sccf_sect_type == SCCF_SECT_DATA) {
scc_pe_write_section(builder, &data_range,
(u8 *)scc_vec_unsafe_get_data(*sect_data),
scc_vec_size(*sect_data));
}
}
scc_pe_write_section(builder, &idata_range,
scc_vec_unsafe_get_data(idata_buffer),
scc_vec_size(idata_buffer));
}