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

2013-05-13 Thread Andreas Bießmann
Hi Albert,

On 05/10/2013 05:09 PM, Albert ARIBAUD wrote:
 Hi Andreas,
 
 On Fri, 10 May 2013 12:57:21 +0200, Andreas Bießmann
 andreas.de...@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.de...@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.

thank you for your detailed explanation. So now its clear why referring
the address of an object of type char[] will also work.
Another question, wouldn't it make sense to declare these C globals as
const then?

Best regards

Andreas Bießmann
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


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

2013-05-13 Thread Albert ARIBAUD
Hi Andreas,

On Mon, 13 May 2013 10:35:12 +0200, Andreas Bießmann
andreas.de...@googlemail.com wrote:

 Hi Albert,
 
 On 05/10/2013 05:09 PM, Albert ARIBAUD wrote:
  Hi Andreas,
  
  On Fri, 10 May 2013 12:57:21 +0200, Andreas Bießmann
  andreas.de...@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.de...@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.
 
 thank you for your detailed explanation. So now its clear why referring
 the address of an object of type char[] will also work.
 Another question, wouldn't it make sense to declare these C globals as
 const then?

Indeed, const may help prevent these symbols from being accidentally
written into, at least in the most expected cases such as passing
__bss_end to a function expecting a non-const char*.

There is, however, a much better way of preventing this and more:
just give these symbols a C type of 'struct {}' (empty struct).

Since this type has absolutely no field which could be written into or
read from, it is completely protected from direct write but also
from direct read; and a pointer to it has type struct {} * which
is incompatible with any other pointer, so any inconsiderate use of it
is detected at compile time.

I had thought of the 'struct {}' method for linker lists refactoring,
when I needed a zero-size type; I finally turned to char[0] instead
(and comment on this at line 150 of include/linker_lists.h) because the
struct method would cause gcc 4.4 and earlier, such as eldk42, to throw
diagnostics like warning: dereferencing type-punned pointer will break
strict-aliasing rules -- that is the incompatibility I am talking
about.

Note that the diagnostics did not stem from the empty struct variable
declarations as such, but type-casting the address of an empty struct
into a pointer to a known, non-empty, struct; I just checked now, and
doing an intermediate cast to char* or void* prevents the warnings.
Why I failed to find this when I was refactoring linker lists, I'll
never know.

Of 

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

2013-05-13 Thread Albert ARIBAUD
On Fri, 10 May 2013 11:24:44 +0200, Albert ARIBAUD
albert.u.b...@aribaud.net wrote:

 Sorry for not spotting this before it was merged in; but now this must
 be fixed. I'm ok with the wrongly-ulong symbols being changed back to
 char[], though I would prefer their type to be char[0] if possible, as
 this is (admittedly marginally) more likely to help the compiler catch
 accidental dereferencings.

Following the latest exchange with Andreas, and after some tests with
eldk42 and a gcc 4.7 toolchain, I amend the previous paragraph: rather
than 'char[0]', I suggest using 'struct {}'.

Amicalement,
-- 
Albert.
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


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

2013-05-10 Thread Albert ARIBAUD
Hi Andreas,

On Wed,  8 May 2013 11:25:17 +0200, Andreas Bießmann
andreas.de...@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[]).

But the definition of __bss_end to being an ulong, as introduced by
18652864, is plain wrong. Just because it is a linker defined symbol
does not mean the object it represents is a 32-bit quantity -- it is
not. It still is a non-object, a pure address.

Ditto for __data_end, __rel_dyn_start, __rel_dyn_end and pretty much any
symbol in sections.h which is not an offset.

Sorry for not spotting this before it was merged in; but now this must
be fixed. I'm ok with the wrongly-ulong symbols being changed back to
char[], though I would prefer their type to be char[0] if possible, as
this is (admittedly marginally) more likely to help the compiler catch
accidental dereferencings.

Amicalement,
-- 
Albert.
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


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

2013-05-10 Thread Andreas Bießmann
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.de...@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?

Best regards

Andreas Bießmann

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


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

2013-05-10 Thread Albert ARIBAUD
Hi Andreas,

On Fri, 10 May 2013 12:57:21 +0200, Andreas Bießmann
andreas.de...@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.de...@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.
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


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

2013-05-10 Thread Michael Cashwell
On May 10, 2013, at 11:09 AM, Albert ARIBAUD albert.u.b...@aribaud.net wrote:

 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.

I ran into a case one on Codewarrior Mac PPC tools where there was a subtle
different here. In an existing body of code there was originally a global
char[] defined with a matching extern char[] declared in a header.

At some point the definition was changed to char* because the size of the
array grew and we wanted it out of the global section. I traced an obscure
crash to some assembly code that had worked when the definition was char[]
but needed an extra level of indirection when it was char *.

During that debugging I found that the declaration had not been changed to
char * but the C compiler hadn't cared. It handled the mixed forms just fine
despite the clear difference in the code.

I surmised it was some subtle issue around PPC's handling of global data
(or the Codewarrior PPC ABI) but still don't really know.

-Mike

___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot


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

2013-05-10 Thread Albert ARIBAUD
Hi Michael,

On Fri, 10 May 2013 13:02:57 -0400, Michael Cashwell
mboa...@prograde.net wrote:

 On May 10, 2013, at 11:09 AM, Albert ARIBAUD albert.u.b...@aribaud.net 
 wrote:
 
  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.
 
 I ran into a case one on Codewarrior Mac PPC tools where there was a subtle
 different here. In an existing body of code there was originally a global
 char[] defined with a matching extern char[] declared in a header.
 
 At some point the definition was changed to char* because the size of the
 array grew and we wanted it out of the global section. I traced an obscure
 crash to some assembly code that had worked when the definition was char[]
 but needed an extra level of indirection when it was char *.

Well, of course it did! char* is a pointer to char, with syntactic
facilities to use it as a pointer to char array, but char* is not an
array. The value of a pointer to char is a (probably 32-bit) address,
and you need to dereferenc it to get a char.

 During that debugging I found that the declaration had not been changed to
 char * but the C compiler hadn't cared. It handled the mixed forms just fine
 despite the clear difference in the code.

Well, the compiler would not care that one C module would know the
symbol as char* and another one would know it as char[], since the
compiler treats compilation units completely independently. You would
end up using the same address space area for two different objects: an
array of chars, overlapped with a (probably 32-bit) pointer to char.

Where I worked up until recently, we had a 'coding rule' that required
us to always #include a module's .h file (its public interface) from
within its .c file (its implementation) if only to make sure the
compiler saw both the declarations and the definitions in a single
compilation unit, and would thus bark at us for screwing up between
declaration and definition.

 I surmised it was some subtle issue around PPC's handling of global data
 (or the Codewarrior PPC ABI) but still don't really know.

This has nothing to do with PPC or CW; this is just C working as
designed.

 -Mike

Amicalement,
-- 
Albert.
___
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot