Skip to content

Instantly share code, notes, and snippets.

@smx-smx
Created April 27, 2022 23:44
Show Gist options
  • Save smx-smx/a29f3c71ab864bb762c6bfb0da1aae67 to your computer and use it in GitHub Desktop.
Save smx-smx/a29f3c71ab864bb762c6bfb0da1aae67 to your computer and use it in GitHub Desktop.
Binutils GAS file-less frontend
/**
* @file libgas.c
* @author Stefano Moioli <[email protected]>
* @brief use GAS from Binutils as a library, without temporary files
* this example implements a GAS assembler RAPL - Read Assemble Print Loop
* @version 0.1
* @date 2022-04-28
*
* @copyright Copyright (c) Stefano Moioli 2022
*
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <windows.h>
#include <sys/stat.h>
static HMODULE gas;
static void *resolveSymbol(char *sym){
return (void *)GetProcAddress(gas, sym);
}
#define GVAR(T, sym) T sym = (T)resolveSymbol(#sym)
#define GFUNC(ret_type, function, ...) \
ret_type(*function)(__VA_ARGS__) = resolveSymbol(#function)
typedef FILE *(*fopen_fn)(const char *filename, const char *mode);
typedef void (*appender_fn)(int datum);
/**
* @brief
* the hooked frag_append_1_char declared with --wrap in libgas
*/
static appender_fn wrapped_fappend;
static void *iovec_open (void *nbfd, void *open_closure){
return open_closure;
}
static off_t iovec_read(
void *nbfd, void *stream, void *buf,
off_t nbytes, off_t offset
){
unsigned char *mem = (unsigned char *)stream;
memcpy(buf, &mem[offset], nbytes);
return nbytes;
}
static void my_fappend(int datum){
printf(">> %02X\n", datum);
}
int main(int argc, char *argv[]){
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
gas = LoadLibraryA("gas-x86_64-unknown-linux.dll");
if(gas == NULL){
fprintf(stderr, "LoadLibraryA failed\n");
return 1;
}
GFUNC(void, subsegs_begin);
GFUNC(void, symbol_begin);
GFUNC(void, frag_init);
GFUNC(void, elf_begin);
GFUNC(void, write_object_file);
GFUNC(void, output_file_create, const char *name);
GFUNC(void, output_file_close, const char *filename);
GFUNC(void *, subseg_new, const char *segname, int subseg);
GFUNC(void, bfd_set_section_flags, void *, unsigned);
GFUNC(void, subseg_set, void *, int);
GFUNC(void, md_begin);
GFUNC(void, md_assemble, char *line);
GFUNC(void, md_end);
GFUNC(void *, bfd_openr_iovec,
const char *filename, const char *target,
void *(*open) (void *nbfd, void *open_closure),
void *open_closure,
off_t (*pread) (
void *nbfd,
void *stream, void *buf,
off_t nbytes, off_t offset),
int (*close) (void *nbfd, void *stream),
int (*stat) (void *abfd, void *stream, struct stat *sb)
);
GFUNC(int, bfd_default_set_arch_mach, void *abfd, unsigned arch, unsigned long mach);
GFUNC(void, bfd_set_format, void *abfd, int format);
GFUNC(int, bfd_close, void *abfd);
// address of the fopen function pointer
GVAR(fopen_fn *, pfn_fopen);
GVAR(appender_fn *, pfn_fappend);
GVAR(void **, reg_section);
GVAR(void **, expr_section);
GVAR(void **, stdoutput);
wrapped_fappend = *pfn_fappend;
*pfn_fappend = &my_fappend;
symbol_begin();
subsegs_begin();
#define MEM_SIZE 1024 * 1024
unsigned char *mem = calloc(MEM_SIZE, 1);
/**
* create a fake output buffer.
* it's actually in read mode, as signaled by the r in "openr"
* this will conveniently cause all write operations to be ignored
*/
*stdoutput = bfd_openr_iovec(
"dummy", NULL,
iovec_open, mem,
iovec_read, NULL, NULL
);
// set object format
bfd_set_format(*stdoutput, 1);
bfd_default_set_arch_mach(*stdoutput,
8, // bfd_arch_i386
8 // bfd_mach_x86_64
);
/**
* create the .text section
*/
void *textSeg = subseg_new(".text", 0);
bfd_set_section_flags(textSeg, 1 | 2 | 4 | 0x10 |8);
subseg_set(textSeg, 0);
md_begin();
char *line = NULL;
/**
* IMPORTANT: md_assemble modifies the input line
* so we must always make a copy
*/
#define ASM(x) do { \
line = strdup(x); \
md_assemble(line); \
free(line); line = NULL; \
} while(0);
char buffer[128];
while(!feof(stdin)){
fgets(buffer, sizeof(buffer), stdin);
char *p = strrchr(buffer, '\n');
if(p) *p = '\0';
ASM(buffer);
}
//ASM("xorl %ebx, %ebx");
if(md_end != NULL){
md_end();
}
free(mem);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment