executor: add support for 386 arch (COMPAT syscalls)

This is not fully working now: e.g. prog and sys packages assume
that pointer size is 8. But at least it compiles and works.
This commit is contained in:
Dmitry Vyukov 2016-06-28 14:42:34 +02:00
parent 2ce72987a6
commit 32061a606f
6 changed files with 1157 additions and 34 deletions

View File

@ -34,8 +34,8 @@
#include "syscalls.h"
#define KCOV_INIT_TRACE _IOR('c', 1, unsigned long)
#define KCOV_INIT_TABLE _IOR('c', 2, unsigned long)
#define KCOV_INIT_TRACE _IOR('c', 1, unsigned long long)
#define KCOV_INIT_TABLE _IOR('c', 2, unsigned long long)
#define KCOV_ENABLE _IO('c', 100)
#define KCOV_DISABLE _IO('c', 101)
@ -94,7 +94,7 @@ struct thread_t {
bool created;
int id;
pthread_t th;
uintptr_t* cover_data;
uint64_t* cover_data;
uint64_t* copyout_pos;
int ready;
int done;
@ -103,10 +103,10 @@ struct thread_t {
int call_index;
int call_num;
int num_args;
uint64_t args[kMaxArgs];
uintptr_t args[kMaxArgs];
uint64_t res;
uint64_t reserrno;
uintptr_t cover_size;
uint64_t cover_size;
int cover_fd;
};
@ -137,8 +137,8 @@ uint64_t current_time_ms();
void cover_open();
void cover_enable(thread_t* th);
void cover_reset(thread_t* th);
uintptr_t cover_read(thread_t* th);
uintptr_t cover_dedup(thread_t* th, uintptr_t n);
uint64_t cover_read(thread_t* th);
uint64_t cover_dedup(thread_t* th, uint64_t n);
int main(int argc, char** argv)
{
@ -540,7 +540,7 @@ void handle_completion(thread_t* th)
write_output(th->cover_size);
// Truncate PCs to uint32_t assuming that they fit into 32-bits.
// True for x86_64 and arm64 without KASLR.
for (uint32_t i = 0; i < th->cover_size; i++)
for (uint64_t i = 0; i < th->cover_size; i++)
write_output((uint32_t)th->cover_data[i + 1]);
completed++;
__atomic_store_n((uint32_t*)&output_data[0], completed, __ATOMIC_RELEASE);
@ -651,9 +651,9 @@ void execute_call(thread_t* th)
int fd = open("/dev/fuse", O_RDWR);
if (fd != -1) {
char buf[256];
sprintf(buf, "fd=%d,user_id=%lu,group_id=%lu,rootmode=0%o", fd, uid, gid, (unsigned)mode & ~3u);
sprintf(buf, "fd=%d,user_id=%ld,group_id=%ld,rootmode=0%o", fd, (long)uid, (long)gid, (unsigned)mode & ~3u);
if (maxread != 0)
sprintf(buf + strlen(buf), ",max_read=%lu", maxread);
sprintf(buf + strlen(buf), ",max_read=%ld", (long)maxread);
if (mode & 1)
strcat(buf, ",default_permissions");
if (mode & 2)
@ -679,11 +679,11 @@ void execute_call(thread_t* th)
if (fd != -1) {
if (syscall(SYS_mknodat, AT_FDCWD, blkdev, S_IFBLK, makedev(7, 199)) == 0) {
char buf[256];
sprintf(buf, "fd=%d,user_id=%lu,group_id=%lu,rootmode=0%o", fd, uid, gid, (unsigned)mode & ~3u);
sprintf(buf, "fd=%d,user_id=%ld,group_id=%ld,rootmode=0%o", fd, (long)uid, (long)gid, (unsigned)mode & ~3u);
if (maxread != 0)
sprintf(buf + strlen(buf), ",max_read=%lu", maxread);
sprintf(buf + strlen(buf), ",max_read=%ld", (long)maxread);
if (blksize != 0)
sprintf(buf + strlen(buf), ",blksize=%lu", blksize);
sprintf(buf + strlen(buf), ",blksize=%ld", (long)blksize);
if (mode & 1)
strcat(buf, ",default_permissions");
if (mode & 2)
@ -717,8 +717,8 @@ void cover_open()
if (th->cover_fd == -1)
fail("open of /sys/kernel/debug/kcov failed");
if (ioctl(th->cover_fd, KCOV_INIT_TRACE, kCoverSize))
fail("cover enable write failed");
th->cover_data = (uintptr_t*)mmap(NULL, kCoverSize * sizeof(th->cover_data[0]), PROT_READ | PROT_WRITE, MAP_SHARED, th->cover_fd, 0);
fail("cover init write failed");
th->cover_data = (uint64_t*)mmap(NULL, kCoverSize * sizeof(th->cover_data[0]), PROT_READ | PROT_WRITE, MAP_SHARED, th->cover_fd, 0);
if ((void*)th->cover_data == MAP_FAILED)
fail("cover mmap failed");
}
@ -741,11 +741,11 @@ void cover_reset(thread_t* th)
__atomic_store_n(&th->cover_data[0], 0, __ATOMIC_RELAXED);
}
uintptr_t cover_read(thread_t* th)
uint64_t cover_read(thread_t* th)
{
if (!flag_cover)
return 0;
uintptr_t n = __atomic_load_n(&th->cover_data[0], __ATOMIC_RELAXED);
uint64_t n = __atomic_load_n(&th->cover_data[0], __ATOMIC_RELAXED);
debug("#%d: read cover = %d\n", th->id, n);
if (n >= kCoverSize)
fail("#%d: too much cover %d", th->id, n);
@ -756,14 +756,14 @@ uintptr_t cover_read(thread_t* th)
return n;
}
uintptr_t cover_dedup(thread_t* th, uintptr_t n)
uint64_t cover_dedup(thread_t* th, uint64_t n)
{
uintptr_t* cover_data = th->cover_data + 1;
uint64_t* cover_data = th->cover_data + 1;
std::sort(cover_data, cover_data + n);
uintptr_t w = 0;
uintptr_t last = 0;
for (uintptr_t i = 0; i < n; i++) {
uintptr_t pc = cover_data[i];
uint64_t w = 0;
uint64_t last = 0;
for (uint64_t i = 0; i < n; i++) {
uint64_t pc = cover_data[i];
if (pc == last)
continue;
cover_data[w++] = last = pc;

File diff suppressed because it is too large Load Diff

8
sys/sys_386.go Normal file

File diff suppressed because one or more lines are too long

View File

@ -15,7 +15,7 @@ import (
// fetchValues converts literal constants (e.g. O_APPEND) or any other C expressions
// into their respective numeric values. It does so by builting and executing a C program
// that prints values of the provided expressions.
func fetchValues(arch string, vals []string, includes []string, defines map[string]string) []string {
func fetchValues(arch string, vals []string, includes []string, defines map[string]string, cflags []string) []string {
logf(1, "Use C compiler to fetch constant values for arch=%v", arch)
includeText := ""
for _, inc := range includes {
@ -37,6 +37,7 @@ func fetchValues(arch string, vals []string, includes []string, defines map[stri
logf(2, " Build C program into temp file %v", bin.Name())
args := []string{"-x", "c", "-", "-o", bin.Name()}
args = append(args, cflags...)
args = append(args, []string{
// This would be useful to ensure that we don't include any host headers,
// but kernel includes at least <stdarg.h>

View File

@ -15,13 +15,15 @@ type Arch struct {
CARCH []string
KernelHeaderArch string
KernelInclude string
CFlags []string
Numbers []int
}
var archs = []*Arch{
{"amd64", []string{"__x86_64__"}, "x86", "asm/unistd.h", nil},
{"arm64", []string{"__aarch64__"}, "arm64", "asm/unistd.h", nil},
{"ppc64le", []string{"__ppc64__", "__PPC64__", "__powerpc64__"}, "powerpc", "asm/unistd.h", nil},
{"amd64", []string{"__x86_64__"}, "x86", "asm/unistd.h", []string{"-m64"}, nil},
{"386", []string{"__i386__"}, "x86", "asm/unistd.h", []string{"-D__SYSCALL_COMPAT", "-DCONFIG_COMPAT", "-DCONFIG_X86_32"}, nil},
{"arm64", []string{"__aarch64__"}, "arm64", "asm/unistd.h", []string{}, nil},
{"ppc64le", []string{"__ppc64__", "__PPC64__", "__powerpc64__"}, "powerpc", "asm/unistd.h", []string{}, nil},
}
var syzkalls = map[string]int{
@ -51,7 +53,7 @@ func fetchSyscallsNumbers(arch *Arch, syscalls []Syscall) {
defines[name] = strconv.Itoa(nr)
}
}
for _, s := range fetchValues(arch.KernelHeaderArch, vals, includes, defines) {
for _, s := range fetchValues(arch.KernelHeaderArch, vals, includes, defines, arch.CFlags) {
n, err := strconv.ParseUint(s, 10, 64)
if err != nil {
failf("failed to parse syscall number '%v': %v", s, err)
@ -61,7 +63,7 @@ func fetchSyscallsNumbers(arch *Arch, syscalls []Syscall) {
}
func generateSyscallsNumbersArch(arch *Arch, syscalls []Syscall) {
var archcode string = "sys/sys_"+arch.GOARCH+".go"
var archcode string = "sys/sys_" + arch.GOARCH + ".go"
logf(1, "Generate code with syscall numbers for arch=%v in %v", arch.GOARCH, archcode)
buf := new(bytes.Buffer)
if err := archTempl.Execute(buf, arch); err != nil {

View File

@ -18,9 +18,9 @@ import (
)
var (
flagLinux = flag.String("linux", "", "path to linux kernel source checkout")
flagLinux = flag.String("linux", "", "path to linux kernel source checkout")
flagLinuxBld = flag.String("linuxbld", "", "path to linux kernel build directory")
flagV = flag.Int("v", 0, "verbosity")
flagV = flag.Int("v", 0, "verbosity")
)
func main() {
@ -569,7 +569,7 @@ func compileFlags(includes []string, defines map[string]string, flags map[string
valArray = append(valArray, k)
}
// TODO: should use target arch
flagVals := fetchValues("x86", valArray, includes, defines)
flagVals := fetchValues("x86", valArray, includes, defines, []string{})
for i, f := range valArray {
vals[f] = flagVals[i]
}
@ -649,7 +649,7 @@ func parse(in io.Reader) (includes []string, defines map[string]string, syscalls
} else {
p.SkipWs()
fld := []string{p.Ident()}
logf(3, " Add field %f to struct %v", fld, str.Name)
logf(3, " Add field %v to struct %v", fld, str.Name)
fld = append(fld, parseType(p, unnamed, flags)...)
str.Flds = append(str.Flds, fld)
}
@ -807,4 +807,3 @@ func logf(v int, msg string, args ...interface{}) {
log.Printf(msg, args...)
}
}