Hi!

I'm doing a port of some custom OS to usermode (x86/linux), just as
usermode linux, with one of goals to use valgrind on it. To make some
things simplier and explicit, it doesn't link with host's libc at now, but
have some minimal subset (of libc) builtin.

I've faced a problem when running on valgrind, stack is not original one
and signal arrived: " Can't extend stack during signal delivery for
thread", and it segfaults. What's strange, by simple run or gdb it perfrom
normally.

I reproduced it with small program. I also noticied, when program is linked
with libc, everything goes ok.

Example is attached. It's like so:
$ make # build two versions, with libc and bare one
$ make TARGET=valgrind_test vg # run bare version, it will sleeps until
killed with SIGCHLD (17). On signal it segfaults
$ gbd valgrind_test
(gdb) r
# on SIGCHILD it exits normally
$ make TARGET=valgrind_test_libc vg # run libc version, sleeps until
SIGCHLD and exit ok.

I also attach logs of my run. Valgrind with more debugging info was used
(patch attached)

So, the question is, what mechanism can be used to make bare version act
  like libc one? I've tried to do STACK_REGISTER, but it brought no
success.

I've tried valgrind 3.8.1 and svn r13380, all the same.

With best regards,
Anton

Attachment: debug.patch
Description: Binary data

Attachment: Makefile
Description: Binary data

#include <valgrind/valgrind.h>

#ifdef LIBC
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <stdio.h>

#else

int main(void);

void _start(void) {
	main();
}

int syscall(int eax, int ebx, int ecx, int edx) {
	int ret;

	__asm__ __volatile__ (
		"int $0x80\n\t"
		: "=a"(ret)
		: "a"(eax), "b"(ebx), "c"(ecx), "d"(edx)
	);

	return ret;
}

int pause(void) {
	return syscall(29, 0, 0, 0);
}
 
int exit(int ret) {
	return syscall(1, 0, 0, 0);
}

typedef unsigned long sigset_t;

struct host_sigaction {
	void (*sa_handler)(int);
	sigset_t sa_mask;
	unsigned long sa_flags;
	void (*sa_restorer)(void);
};

#define HOST_SA_NODEFER	0x40000000

int host_sigaction(int signum, const struct host_sigaction *new, 
		struct host_sigaction *old) {
	return syscall(67, signum, (int) new, (int) old);
}

int signal(int signum, void *hnd) {
	struct host_sigaction sigact = {
		.sa_handler = hnd,
		.sa_flags = HOST_SA_NODEFER,
		.sa_mask = 0,
	}, old;

	return host_sigaction(signum, &sigact, &old);

}

int write(int fd, void *buf, int len) {
	return syscall(4, fd, (int) buf, len);
}

#define SIGCHLD 17

#endif

#define STACK_SZ 0x1000

char stack[STACK_SZ];

void noop(int sig) { }

int main(void) {
	int esp = STACK_SZ - 4 + (int) stack;
	int stack_id = VALGRIND_STACK_REGISTER(stack, stack + STACK_SZ);
	
	VALGRIND_PRINTF("stack: id=%d, begin=%p, end=%p\n", 
			stack_id, stack, stack + STACK_SZ); 

	signal(SIGCHLD, noop);

	__asm__ __volatile__ (
		"movl %0, %%esp\n\t"
		"movl %0, %%ebp\n\t"
		:
		: "a"(esp)
		:);

	pause();

	exit(0);

	return 0;
}

Attachment: vg_test.log.gz
Description: GNU Zip compressed data

Attachment: vg_test_libc.log.gz
Description: GNU Zip compressed data

------------------------------------------------------------------------------
Get 100% visibility into Java/.NET code with AppDynamics Lite
It's a free troubleshooting tool designed for production
Get down to code-level detail for bottlenecks, with <2% overhead.
Download for free and get started troubleshooting in minutes.
http://p.sf.net/sfu/appdyn_d2d_ap2
_______________________________________________
Valgrind-users mailing list
Valgrind-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/valgrind-users

Reply via email to