Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 17 Feb 2010 09:44:44 -0700 (MST)
From:      "M. Warner Losh" <imp@bsdimp.com>
To:        gjb@semihalf.com
Cc:        freebsd-arm@FreeBSD.org
Subject:   Re: kdump on ARM
Message-ID:  <20100217.094444.4959786828202967.imp@bsdimp.com>
In-Reply-To: <4B7BFAA4.4040607@semihalf.com>
References:  <4B7BFAA4.4040607@semihalf.com>

next in thread | previous in thread | raw e-mail | index | archive | help
In message: <4B7BFAA4.4040607@semihalf.com>
            Grzegorz Bernacki <gjb@semihalf.com> writes:
: Hi,
: 
: I've noticed that kdump on ARM doesn't work properly, it generates bus
: error. The problem is that structures dumped into ktrace.out are not
: aligned. Processing such a structure causes Aligment Fault. One
: solution is to copy structure into local variable and then process it,
: please see patch below. But I am not sure if this is the best solution
: and maybe someone has a better idea.
: 
: grzesiek
: 
: 
: diff --git a/usr.bin/kdump/kdump.c b/usr.bin/kdump/kdump.c
: index 386221e..5a15886 100644
: --- a/usr.bin/kdump/kdump.c
: +++ b/usr.bin/kdump/kdump.c
: @@ -1325,6 +1325,10 @@ ktrstat(struct stat *statp)
:  void
:  ktrstruct(char *buf, size_t buflen)
:  {
: +#if defined(__arm__)
: +       struct stat stat;
: +       struct sockaddr sockaddr;
: +#endif

Lose the ifdefs.  Also, sockaddr is the wrong structure, it should be
sockaddr_storage.

:         char *name, *data;
:         size_t namelen, datalen;
:         int i;
: @@ -1348,12 +1352,22 @@ ktrstruct(char *buf, size_t buflen)
:         if (strcmp(name, "stat") == 0) {
:                 if (datalen != sizeof(struct stat))
:                         goto invalid;
: +#if defined(__arm__)
: +               memcpy(&stat, data, sizeof(struct stat));
: +               ktrstat(&stat);
: +#else
:                 ktrstat((struct stat *)data);
: +#endif

This is needlessly complicated.  Replace with:
		stat = *(struct stat *)data;
		ktrstat(&stat);


:         } else if (strcmp(name, "sockaddr") == 0) {
:                 if (datalen < sizeof(struct sockaddr) ||
:                     datalen != ((struct sockaddr *)(data))->sa_len)
:                         goto invalid;
: +#if defined(__arm__)
: +               memcpy(&sockaddr, data, sizeof(struct sockaddr));
: +               ktrsockaddr(&sockaddr);
: +#else
:                 ktrsockaddr((struct sockaddr *)data);
: +#endif

This is actually wrong.  You're only copying part of the structure and
it will be wrong for IPv6 addresses.  Consider

		memcpy(&sockaddr, data, datalen);
		ktrsockaddr(&sockaddr);

instead.  However, this is already too late.  We've already
dereferenced through data in its unaligned state.

Warner



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20100217.094444.4959786828202967.imp>