Commit cc0f2f23 authored by Tomasz Buchert's avatar Tomasz Buchert

New upstream version 1.14

parent d2c13fc3
......@@ -26,7 +26,7 @@ OBJS = $(CFILES:.c=.o)
LIB_NAME = $(LIBX86).so.$(VERSION)
LIB_SONAME = $(LIBX86).so.$(MAJOR_VERSION)
.PHONY: all shared install test clean
.PHONY: all shared install test demo clean
%.o: %.c
$(CC) -c $(CFLAGS) $<
......@@ -50,6 +50,9 @@ $(LIB_NAME): .depend $(OBJS)
test:
make -C test
demo:
make -C demo
archive: changelog
@if [ ! -d .git ] ; then echo no git repo ; false ; fi
mkdir -p package
......@@ -59,6 +62,7 @@ archive: changelog
clean:
make -C test clean
make -C demo clean
rm -f *.o *~ include/*~ *.so.* .depend
rm -rf package
......
# x86 emulation library
libx86emu is a dependency for [hwinfo](https://github.com/openSUSE/hwinfo).
libx86emu is a small library to emulate x86 instructions. The focus here is not a complete emulation (go for qemu for this) but to cover enough for typical firmware blobs.
At the moment 'regular' 32-bit instructions are covered together with basic protected mode support.
Not done are fpu, mmx, or any of the other instruction set extensions.
The library lets you
- intercept any memory access or directly map real memory ranges
- intercept any i/o access, map real i/o ports, or block any real i/o
- intercept any interrupt
- provides hook to run after each instruction
- recognizes a special x86 instruction that can trigger logging
- has integrated logging to
- trace code execution, including register content and decoded instruction
- trace memory and i/o accesses
- provide statistics about accessed memory locations, i/o ports, and interrupts
## Downloads
Get the latest version from the [openSUSE Build Service](https://software.opensuse.org/package/libx86emu).
## Examples
Have a look at this minimalistic [demo](demo/x86emu-demo.c) program.
The library is used by [hwinfo](https://github.com/openSUSE/hwinfo) to emulate Video BIOS (VBE) calls.
## API functions
......@@ -298,10 +324,26 @@ Reset memory access stats. See `x86emu_reset_access_stats()`.
## openSUSE Development
The package is automatically submitted from the `master` branch to
[system:install:head](https://build.opensuse.org/package/show/system:install:head/libx86emu)
OBS project. From that place it is forwarded to
[openSUSE Factory](https://build.opensuse.org/project/show/openSUSE:Factory).
To build, simply run `make`. Install with `make install`.
Basically every new commit into the master branch of the repository will be auto-submitted
to all current SUSE products. No further action is needed except accepting the pull request.
Submissions are managed by a SUSE internal [jenkins](https://jenkins.io) node in the InstallTools tab.
Each time a new commit is integrated into the master branch of the repository,
a new submit request is created to the openSUSE Build Service. The devel project
is [system:install:head](https://build.opensuse.org/package/show/system:install:head/libx86emu).
`*.changes` and version numbers are auto-generated from git commits, you don't have to worry about this.
The spec file is maintained in the Build Service only. If you need to change it for the `master` branch,
submit to the
[devel project](https://build.opensuse.org/package/show/system:install:head/libx86emu)
in the build service directly.
Development happens exclusively in the `master` branch. The branch is used for all current products.
You can find more information about this workflow in the [linuxrc-devtools
You can find more information about the changes auto-generation and the
tools used for jenkis submissions in the [linuxrc-devtools
documentation](https://github.com/openSUSE/linuxrc-devtools#opensuse-development).
CC = gcc
CFLAGS = -g -Wall -fomit-frame-pointer -O2
.PHONY: clean
x86emu-demo: x86emu-demo.c
$(CC) $(CFLAGS) $< -lx86emu -o $@
clean:
rm -f *~ *.o x86emu-demo
/*
* This is a simple program demonstrating the libx86emu usage.
*
* It lets you load a binary blob at some address and run the emulation.The
* emulation trace is logged to the console to show what it is doing.
*/
#include <stdio.h>
#include <stdlib.h>
#include <getopt.h>
#include <x86emu.h>
void help(void);
void flush_log(x86emu_t *emu, char *buf, unsigned size);
x86emu_t *emu_new(void);
int emu_init(x86emu_t *emu, char *file);
void emu_run(char *file);
struct option options[] = {
{ "help", 0, NULL, 'h' },
{ "load", 1, NULL, 'l' },
{ "start", 1, NULL, 's' },
{ "max", 1, NULL, 'm' },
{ }
};
struct {
struct {
unsigned segment;
unsigned offset;
} start;
unsigned load;
unsigned max_instructions;
char *file;
} opt;
/*
* Parse options, then run emulation.
*/
int main(int argc, char **argv)
{
int i;
char *str;
opt.start.segment = 0;
opt.start.offset = opt.load = 0x7c00;
opt.max_instructions = 10000000;
opterr = 0;
while((i = getopt_long(argc, argv, "hm:l:s:", options, NULL)) != -1) {
switch(i) {
case 'm':
opt.max_instructions = strtoul(optarg, NULL, 0);
break;
case 'l':
opt.load = strtoul(optarg, NULL, 0);
break;
case 's':
opt.start.offset = strtoul(optarg, &str, 0);
if(*str == ':') {
opt.start.segment = opt.start.offset;
opt.start.offset = strtoul(str + 1, NULL, 0);
}
break;
default:
help();
return i == 'h' ? 0 : 1;
}
}
if(argc == optind + 1) {
opt.file = argv[optind];
}
else {
help();
return 1;
}
emu_run(opt.file);
return 0;
}
/*
* Display short usage message.
*/
void help()
{
printf(
"Usage: x86emu-demo [OPTIONS] FILE\n"
"\n"
"Load FILE and run x86 emulation.\n"
"\n"
"Options:\n"
" -l, --load ADDRESS\n"
" load FILE at ADDRESS into memory (default: 0x7c00).\n"
" -s, --start ADDRESS\n"
" start emulation at ADDRESS (default 0:0x7c00).\n"
" Note: ADDRESS may contain a colon (':') to separate segment and offset values;\n"
" if not, segment = 0 is assumed.\n"
" -m, --max N\n"
" stop after emulating N instructions.\n"
" -h, --help\n"
" show this text\n"
);
}
/*
* Write emulation log to console.
*/
void flush_log(x86emu_t *emu, char *buf, unsigned size)
{
if(!buf || !size) return;
fwrite(buf, size, 1, stdout);
}
/*
* Create new emulation object.
*/
x86emu_t *emu_new()
{
x86emu_t *emu = x86emu_new(X86EMU_PERM_R | X86EMU_PERM_W | X86EMU_PERM_X, 0);
/* log buf size of 1000000 is purely arbitrary */
x86emu_set_log(emu, 1000000, flush_log);
emu->log.trace = X86EMU_TRACE_DEFAULT;
return emu;
}
/*
* Setup registers and memory.
*/
int emu_init(x86emu_t *emu, char *file)
{
FILE *f;
unsigned addr;
int i;
addr = opt.load;
x86emu_set_seg_register(emu, emu->x86.R_CS_SEL, opt.start.segment);
emu->x86.R_EIP = opt.start.offset;
if(!(f = fopen(file, "r"))) return 0;
while((i = fgetc(f)) != EOF) {
x86emu_write_byte(emu, addr++, i);
}
fclose(f);
return 1;
}
/*
* Run emulation.
*/
void emu_run(char *file)
{
x86emu_t *emu = emu_new();
unsigned flags = X86EMU_RUN_MAX_INSTR | X86EMU_RUN_NO_EXEC | X86EMU_RUN_NO_CODE | X86EMU_RUN_LOOP;
int ok = 0;
if(!file) return;
ok = emu_init(emu, file);
if(ok) {
printf("*** running %s ***\n\n", file);
x86emu_dump(emu, X86EMU_DUMP_MEM | X86EMU_DUMP_ASCII);
x86emu_reset_access_stats(emu);
emu->max_instr = opt.max_instructions;
x86emu_run(emu, flags);
x86emu_dump(emu, X86EMU_DUMP_DEFAULT | X86EMU_DUMP_ACC_MEM);
x86emu_clear_log(emu, 1);
}
x86emu_done(emu);
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment