[U-Boot] [PATCH] avr32: fix relocation address calculation

Albert ARIBAUD
2013-05-10T15:09:24Z

Hi Andreas,

On Fri, 10 May 2013 12:57:21 +0200, "Andreas Bie?mann"
<andreas.devel@googlemail.com> wrote:

> Hi Albert,
>
> On 05/10/2013 11:24 AM, Albert ARIBAUD wrote:
> > Hi Andreas,
> >
> > On Wed, 8 May 2013 11:25:17 +0200, Andreas Bie?mann
> > <andreas.devel@googlemail.com> wrote:
> >
> >> Commit 1865286466a5d0c7f2e3c37632da56556c838e9e (Introduce generic link
> >> section.h symbol files) changed the __bss_end symbol type from char[] to
> >> ulong. This led to wrong relocation parameters which ended up in a not working
> >> u-boot. Unfortunately this is not clear to see cause due to RAM aliasing we
> >> may get a 'half-working' u-boot then.
> >>
> >> Fix this by dereferencing the __bss_end symbol where needed.
> >
> > (cc:ing Simon and Tom)
> >
> > The dereferencing is correct, so this patch seems good per se (it could
> > actually have applied when __bss_end was still a char[]).
>
> well, as I understood this the __bss_end being a char[] did implicitly
> take the address when accessing __bss_end (as we do when we have a
> definition of char foo[2] and we take just 'foo'). But you say here we
> should reference the address of __bss_end while it was still of type
> char[]. Sorry, I do not understand that, can you please clarify?

There are several concepts here, some pertaining to the compiler, some
to the linker.

From the linker viewpoint, a symbol is *always* and *only* an address,
the first address of the object corresponding to the symbol, and an
object is just some area in the addressable space.

From the compiler viewpoint, an object has a C type, possibly with an
initial value, and a name, which is the symbol. The compiler considers
the name/symbol to be value, not the address of the corresponding
object... at least most of the time: as you indicate, when the symbol
denotes a C array, then the C compiler understand the symbol as the
address of the array.

The __bss_end symbol does not actually correspond to an object in the
usual sense, since the BSS contains all sorts of data: any C global,
either uninitialized or initialized with zeroes, whatever its type,
ends up in BSS. The most general way one can assign a type to BSS
itself is by considering it as a shapeless array of bytes -- hence the
char[] definition.

Thus, the C compiler considered the name __bss_end to denote the
address of the BSS "object", and the C code for AVR32 was correct as it
was actually referring to the BSS "object"'s address.

When the __bss_end symbol's C type was changed to 'ulong', this changed
the way the compiler understood the symbol: it now thinks __bss_end is
the BSS' "value", which has no true sense, and certainly does not mean
'the first 4 bytes of BSS considered as a 32-bit value'.

To compensate this, the AVR32 code has to add an & to find the address
of __bss_end, but the original error is to have changed the "type" of
the BSS.

IOW, we should *always* take the address of __bss_end, since this is
the only thing it was defined for. We should never give it a chance to
even *have* a value at the C level, because we don't want to read, or
worse, write, the BSS itself; we only want to access C globals in the
BSS.

HTH,

> Best regards
>
> Andreas Bie?mann

Amicalement,
--
Albert.