Affix
view release on metacpan or search on metacpan
infix/src/emit/emit.c view on Meta::CPAN
#define EMIT_DEFAULT_SECTION_CAPACITY 4096
#define EMIT_SECTION_GROWTH_FACTOR 2
void _emit_context_init(emit_context_t * ctx, emit_architecture_t arch, emit_format_t format) {
ctx->arch = arch;
ctx->format = format;
ctx->state = EMIT_STATE_IDLE;
ctx->sections = NULL;
ctx->current_section = NULL;
ctx->symbols = NULL;
ctx->relocations = NULL;
ctx->binary_spec = NULL;
ctx->current_block_name = NULL;
ctx->section_count = 0;
}
void _emit_context_free(emit_context_t * ctx) {
if (!ctx)
return;
emit_section_t * sec = ctx->sections;
infix/src/emit/emit.c view on Meta::CPAN
}
emit_symbol_t * sym = ctx->symbols;
while (sym) {
emit_symbol_t * next = sym->next;
free(sym->name);
free(sym);
sym = next;
}
emit_relocation_t * rel = ctx->relocations;
while (rel) {
emit_relocation_t * next = rel->next;
free(rel->symbol_name);
free(rel->section_name);
free(rel);
rel = next;
}
free(ctx->current_block_name);
}
static emit_section_t * _create_section(const char * name, emit_section_flags_t flags) {
infix/src/emit/emit.c view on Meta::CPAN
for (uint64_t i = 0; i < padding; i++) {
infix_status status = emit_emit_u8(ctx, 0x90);
if (status != INFIX_SUCCESS)
return status;
}
return INFIX_SUCCESS;
}
INFIX_API INFIX_NODISCARD infix_status
emit_add_relocation(emit_context_t * ctx, const char * name, uint64_t offset, uint8_t size, uint8_t inst_size) {
_infix_clear_error();
if (!ctx || !name) {
_infix_set_error(INFIX_CATEGORY_PARSER, INFIX_CODE_INVALID_KEYWORD, 0);
return INFIX_ERROR_INVALID_ARGUMENT;
}
emit_relocation_t * rel = calloc(1, sizeof(emit_relocation_t));
if (!rel)
return INFIX_ERROR_ALLOCATION_FAILED;
rel->symbol_name = strdup(name);
rel->section_name = ctx->current_section ? strdup(ctx->current_section->name) : NULL;
rel->offset = offset;
rel->size = size;
rel->inst_size = inst_size;
rel->is_pc_relative = true;
rel->next = ctx->relocations;
ctx->relocations = rel;
return INFIX_SUCCESS;
}
static void write_raw_binary(emit_context_t * ctx, uint8_t * buffer, c23_maybe_unused uint64_t total_size) {
emit_section_t ** secs = malloc(ctx->section_count * sizeof(emit_section_t *));
if (!secs)
return;
emit_section_t * sec = ctx->sections;
infix/src/emit/emit.c view on Meta::CPAN
uint64_t offset = 0;
for (int j = i + 1; j < count; j++)
offset += secs[j]->size;
memcpy(buffer + offset, secs[i]->data, secs[i]->size);
}
free(secs);
}
infix_status _emit_resolve_relocations(emit_context_t * ctx) {
if (!ctx)
return INFIX_SUCCESS;
emit_section_t ** secs = malloc(ctx->section_count * sizeof(emit_section_t *));
if (!secs)
return INFIX_ERROR_ALLOCATION_FAILED;
emit_section_t * sec = ctx->sections;
int count = 0;
while (sec) {
infix/src/emit/emit.c view on Meta::CPAN
sec = sec->next;
}
uint64_t section_offsets[32] = {0};
for (int i = 0; i < count; i++) {
section_offsets[i] = 0;
for (int j = i + 1; j < count; j++)
section_offsets[i] += secs[j]->size;
}
for (emit_relocation_t * rel = ctx->relocations; rel != NULL; rel = rel->next) {
emit_symbol_t * sym = _emit_lookup_symbol(ctx, rel->symbol_name);
if (!sym || !sym->is_defined)
continue;
emit_section_t * target_sec = sym->section;
if (!target_sec)
continue;
emit_section_t * reloc_sec = NULL;
if (rel->section_name)
infix/src/emit/emit.c view on Meta::CPAN
}
return INFIX_SUCCESS;
}
INFIX_API infix_status emit_get_binary(const emit_context_t * ctx, const uint8_t ** out_data, size_t * out_size) {
_infix_clear_error();
if (!ctx || !out_data || !out_size)
return INFIX_ERROR_INVALID_ARGUMENT;
emit_context_t * mutable_ctx = (emit_context_t *)ctx;
infix_status status = _emit_resolve_relocations(mutable_ctx);
if (status != INFIX_SUCCESS)
return status;
uint64_t total_size = 0;
for (emit_section_t * sec = ctx->sections; sec != NULL; sec = sec->next)
total_size += sec->size;
uint8_t * buffer = malloc(total_size);
if (!buffer)
return INFIX_ERROR_ALLOCATION_FAILED;
infix/src/emit/emit_internals.h view on Meta::CPAN
typedef struct emit_symbol {
char * name;
bool is_defined;
bool is_function;
emit_section_t * section;
uint64_t value;
struct emit_symbol * next;
} emit_symbol_t;
typedef struct emit_relocation {
char * symbol_name;
char * section_name;
uint64_t offset;
uint8_t size;
uint8_t inst_size;
bool is_pc_relative;
struct emit_relocation * next;
} emit_relocation_t;
typedef struct emit_context {
emit_architecture_t arch;
emit_format_t format;
emit_state_t state;
emit_section_t * sections;
emit_section_t * current_section;
emit_symbol_t * symbols;
emit_relocation_t * relocations;
void * binary_spec;
char * current_block_name;
int section_count;
} emit_context_t;
void _emit_context_init(emit_context_t * ctx, emit_architecture_t arch, emit_format_t format);
void _emit_context_free(emit_context_t * ctx);
emit_section_t * _emit_lookup_section(emit_context_t * ctx, const char * name);
emit_symbol_t * _emit_lookup_symbol(emit_context_t * ctx, const char * name);
infix_status _emit_resolve_relocations(emit_context_t * ctx);
#endif /* INFIX_EMIT_INTERNALS_H */
infix/src/emit/emit_math.c view on Meta::CPAN
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F};
INFIX_API infix_status emit_math_jmp(emit_context_t * ctx, const char * label) {
_infix_clear_error();
if (!ctx)
return INFIX_ERROR_INVALID_ARGUMENT;
if (ctx->arch == EMIT_ARCH_X86_64) {
uint64_t jump_offset = ctx->current_section->size;
EMIT_CHECK(emit_emit_u8(ctx, 0xE9));
EMIT_CHECK(emit_emit_u32(ctx, 0));
EMIT_CHECK(emit_add_relocation(ctx, label, jump_offset + 1, 4, 5));
}
return INFIX_SUCCESS;
}
INFIX_API infix_status emit_math_jmp_cc(emit_context_t * ctx, emit_cc_t cc, const char * label) {
_infix_clear_error();
if (!ctx)
return INFIX_ERROR_INVALID_ARGUMENT;
if (ctx->arch == EMIT_ARCH_X86_64) {
uint64_t jump_offset = ctx->current_section->size;
EMIT_CHECK(emit_emit_u8(ctx, 0x0F));
EMIT_CHECK(emit_emit_u8(ctx, x86_jcc_opcodes[cc]));
EMIT_CHECK(emit_emit_u32(ctx, 0));
EMIT_CHECK(emit_add_relocation(ctx, label, jump_offset + 2, 4, 6));
}
return INFIX_SUCCESS;
}
INFIX_API infix_status emit_math_call(emit_context_t * ctx, const char * name) {
_infix_clear_error();
if (!ctx)
return INFIX_ERROR_INVALID_ARGUMENT;
if (ctx->arch == EMIT_ARCH_X86_64) {
uint64_t call_offset = ctx->current_section->size;
EMIT_CHECK(emit_emit_u8(ctx, 0xE8));
EMIT_CHECK(emit_emit_u32(ctx, 0));
EMIT_CHECK(emit_add_relocation(ctx, name, call_offset + 1, 4, 5));
}
return INFIX_SUCCESS;
}
INFIX_API infix_status emit_math_prologue(emit_context_t * ctx) {
if (ctx->arch == EMIT_ARCH_X86_64) {
EMIT_CHECK(emit_emit_u8(ctx, 0x55));
EMIT_CHECK(emit_emit_u8(ctx, 0x48));
EMIT_CHECK(emit_emit_u8(ctx, 0x8B));
EMIT_CHECK(emit_emit_u8(ctx, 0xEC));
infix/src/emit/emit_math.c view on Meta::CPAN
return INFIX_SUCCESS;
}
INFIX_API infix_status emit_math_load_sym(emit_context_t * ctx, emit_register_t dest, const char * sym) {
if (ctx->arch == EMIT_ARCH_X86_64) {
uint64_t load_offset = ctx->current_section->size;
EMIT_CHECK(emit_x86_rex(ctx, true, EMIT_REG_NEEDS_REX(dest), false, false));
EMIT_CHECK(emit_emit_u8(ctx, 0x8B));
EMIT_CHECK(emit_emit_u8(ctx, 0x05 | ((dest & 0x07) << 3)));
EMIT_CHECK(emit_emit_u32(ctx, 0));
EMIT_CHECK(emit_add_relocation(ctx, sym, load_offset + 3, 4, 7));
}
return INFIX_SUCCESS;
}
INFIX_API infix_status emit_math_store_sym(emit_context_t * ctx, const char * sym, emit_register_t src) {
if (ctx->arch == EMIT_ARCH_X86_64) {
uint64_t store_offset = ctx->current_section->size;
EMIT_CHECK(emit_x86_rex(ctx, true, EMIT_REG_NEEDS_REX(src), false, false));
EMIT_CHECK(emit_emit_u8(ctx, 0x89));
EMIT_CHECK(emit_emit_u8(ctx, 0x05 | ((src & 0x07) << 3)));
EMIT_CHECK(emit_emit_u32(ctx, 0));
EMIT_CHECK(emit_add_relocation(ctx, sym, store_offset + 3, 4, 7));
}
return INFIX_SUCCESS;
}
/* Floating Point Operations */
INFIX_API infix_status emit_math_movsd_reg(emit_context_t * ctx, emit_register_t dest, emit_register_t src) {
if (ctx->arch == EMIT_ARCH_X86_64) {
EMIT_CHECK(emit_emit_u8(ctx, 0xF2));
EMIT_CHECK(emit_x86_rex(ctx, false, EMIT_REG_NEEDS_REX(dest), false, EMIT_REG_NEEDS_REX(src)));
EMIT_CHECK(emit_emit_u8(ctx, 0x0F));
lib/Affix/Build.pm view on Meta::CPAN
}
else {
my $lib = $build_dir->child( $self->_base($file) . $Config{_a} );
my @cmd = ( $rc, '--crate-type=staticlib', '--emit=link', '-C', 'panic=abort', @local, "$file", '-o', "$lib" );
# Force GNU target on MinGW to ensure compatibility with Perl's linker
if ( $os eq 'MSWin32' && $Config{cc} =~ /gcc/ ) {
push @cmd, '--target', 'x86_64-pc-windows-gnu';
}
elsif ( $os ne 'MSWin32' ) {
push @cmd, '-C', 'relocation-model=pic';
}
$self->_run(@cmd);
my @deps = $os eq 'MSWin32' ? qw(ws2_32 userenv bcrypt advapi32 ntdll) : qw(dl pthread m);
return { file => $lib, libs => \@deps };
}
}
#~ https://medium.com/@walkert/fun-building-shared-libraries-in-go-639500a6a669
#~ https://github.com/vladimirvivien/go-cshared-examples
method _build_go ( $src, $out, $mode ) {
( run in 2.672 seconds using v1.01-cache-2.11-cpan-941387dca55 )