From: terry@cs.weber.edu (A Wizard of Earth C)
Subject: Re: linker weird?
Organization: Weber State University  (Ogden, UT)
Date: Sun, 4 Oct 92 21:42:03 GMT

In article <92278.125022TXN102@psuvm.psu.edu> Phaedrus <TXN102@psuvm.psu.edu> writes:
>hello,
>
>i am using pc (pascal compiler) in a mips/ultrix environment and i keep
>getting the message:
>
>Fixed up unaligned data access for pid xxxx (a.out) at pc 0x4017d4
>
>whenever i run the program.  is this an operating system phenomenon,
>and if so, what can i do about it?  i tried setting different data
>segments (-kD option), but that didn't work either.  i should mention
>that the program runs fine, it's just that getting 1000 of these
>un-redirectable messages on a 2400-baud connection is extremely trying.
>
>if this is not the appropriate newsgroup, please point me to one.
>
>any help would be greatly appreciated!

This is really a processor architecture question; since most RISC processers
are stupid on alignments issues and most UNIX compilers are lazy code
generators, you might as well ask here.  You could also have asked in
comp.lang.c, one of the compiler groups, or elsewhere.



The problem is that you are accessing a shortword on a non-shortword boundry
or that you are accessing a longword on a non-longword boundry.

Specifically, I suspect you of doing naughty things to pointers.  8-).

I don't know how smart Pascal's memory allocation routines are on your
Ultrix machine.  C's are smart enough to guarantee any memory returned by
malloc will be longword aligned (by overallocation of 0-3 bytes and returning
an offset 0-3 bytes into the allocated area.


EXCERPT FROM THE BOOK:

"C for Race Car Drivers: A guide to writing fast, portable code"
(C) Copyright 1992	Terry Lambert		All Rights Reserved


--------------------------------------------------------------------------
For instance, if we are allocating from location 0, and a memory chunk
returned to us starts at 1 (instead of 0):

,---.---.---.---.---.---.---.---.---.---.
| 1 | 2 | 3 | 4 | 5 | . | . | . |   |   |
`---'---'---'---'---'---'---'---'---'---'

A pointer is returned to location 4, even though the allocation was started
at 1.  In this case, if we asked for 5 bytes, the "dotted" locations will
be allocated for you (sort of as an appology for lying to you, of the "I
didn't start allocating where I could have, but here's 3 extra bytes so you
can still use 5 of them" (actually, it over allocates the other two bytes as
well to make sure the next allocation doesn't blow up, but it doesn't tell
you about it).


So when do I get an alignment error?

1)	When I set a pointer to a structure or aligned access object (int,
	short, or any >8bit atomic type) to the address of an offset
	into a malloc()'ed buffer and that offset isn't evenly divisible
	by 4.

		main()
		{
			char	*cp;
			int	*ip;
			int	i;

			cp = malloc( 128);	/* allocate 128 bytes*/
			cp = cp + 3;		/* get to right offset*/
			ip = (int *)cp;		/* set int pointer*/
			i = *ip;		/* unaligned dereference*/
			printf( "never gets here: %d\n", i);
		}


2)	When I use a locally declared buffer (allocated from the stack)
	that isn't declared immediately after a "required-to-be-aligned"
	value.  This will result in "random" failures when called, since
	the buffer may or may not start on the appropriate boundry,
	depending on the current stack state.

		foo1()
		{
			char	ca[ 20];	/* [0] might be aligned...*/
			int	*ip;
			int	i;

			ip = (int *)ca;		/* set int pointer*/
			i = *ip;	/* possibly unaligned dereference*/
			printf( "may (1 out of 4 times) get here: %d\n", i);
		}


3)	Some compilers think they are smarter than you (I haven't met one
	that was smarter than me).  This means changing the declaration
	order won't necessarily cause the buffer to be on the stack at an
	alignment boundy, like you'd expect.  This means you might get
	random errors with one compiler and not with another, or get them
	with the optimizer turned on but not if it's turned off.  In effect,
	this would cause the example here to "turn into" the example above.

		foo2()
		{
			int	i;		/* might be on stack after ca*/
			char	ca[ 20];	/* [0] might be aligned...*/
			int	*ip;

			ip = (int *)ca;		/* set int pointer*/
			i = *ip;	/* possibly unaligned dereference*/
			printf( "may (1 out of 4 times) get here: %d\n", i);
		}


So how do I fix it?

1)	Don't code "badly" -- quoted, because the computer's architecture
	is showing through at a very high level because of inadequate
	compiler technology.  I firmly believe 10 minutes of a compiler
	users time is worth 100 hours of a compiler writers time; less
	time will be spent in the long run, because compiler users vastly
	outnumber compiler writers.

2)	Don't depend on the compiler to "do the right thing".  This would
	require much smarter compiler technology, and compiler writers
	either are not up to it or are prevented by their management from
	pursuing it.

3)	Don't depend on the linker to do the right thing.  A special case
	of example 1 might be the following:

		func1()
		{
			char	*cp;
			int	i;

			cp = malloc( 128);	/* allocate 128 bytes*/
			cp = cp + 3;		/* get to right offset*/
			i = getint( cp);
			printf( "never gets here: %d\n", i);
		}

		int
		getint( data)
		char	*data;
		{
			int	*ip;
			int	i;

			ip = (int *)data;	/* set int pointer*/
			i = *ip;		/* unaligned dereference*/
			return( *ip);		/* never gets here*/
		}
	
	Linker technology isn't up to it.  This would require memory
	pseudo-ops be emitted by the compiler to be resolved by the
	linker.  Another way to think of it is as interprocedural path
	validation.  The linker has to do it because "func1" and "getint"
	may not be in the same modules.

4)	Copy.  This is gross, but the following code will eliminate all
	of the problems discussed at the cost of speed:

	Replace every instance of:

			i = *ip;

	with:

			memcpy( (char *)&i, (char *)ip, sizeof(i));
	

Conclusion:

	It *is* possible to eliminate "unaligned data access" errors by:

1)	Using better compilers.

2)	Using better linkers.

3)	Avoiding constructs which lead to the possibility of error.

4)	Copying.

--------------------------------------------------------------------------

					Terry Lambert
					terry@icarus.weber.edu
					terry_lambert@novell.com
---
Any opinions in this posting are my own and not those of my present
or previous employers.
-- 
-------------------------------------------------------------------------------
                                        "I have an 8 user poetic license" - me
 Get the 386bsd FAQ from agate.berkeley.edu:/pub/386BSD/386bsd-0.1/unofficial
-------------------------------------------------------------------------------