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 )