[arm-gnu] Static template member in assigned section -- section type conflict

Gene Smith gds at chartertn.net
Sat Jan 28 20:01:32 UTC 2012


On 01/27/2012 01:45 PM, Carlos O'Donell wrote:
> On 1/27/2012 12:19 AM, Gene Smith wrote:
>>> You will never have *all* of priv in the same place because
>>> the `static' clause makes that impossible for>   1 instances
>>> of the object (given the current implementation for static).
>>>
>>> Cheers,
>>> Carlos.
>>
>> Thanks for the detailed explanation. However, I am not sure
>> I follow it all and will look up the concept of "common"
>> you refer to. While waiting for a response I found a solution
>> by breaking up the code into 3 separate files and I get the
>> result I expect.
>>
>> // temp.h
>> template<class t1, class t2>
>> class outer
>> {
>> public:
>>      t1        a;
>>      static t2    b;
>> };
>>
>> // temp.cpp
>> #include "temp.h"
>>
>> template<class t1, class t2>
>> t2 outer<t1, t2>::b
>>          __attribute__((section(".s1")));
>>
>> // Explicit instantiation (NEW!)
>> template class outer<int,int>;
>>
>> //main.c
>> #include "temp.h"
>> int main (void)
>> {
>>      static outer<int, int>  priv __attribute__((section(".s1")));
>>
>>      priv.a = 10;
>>      priv.b = 10;
>> }
>>
>> arm-none-eabi-g++ -c temp.cpp
>> arm-none-eabi-g++ -c main.cpp
>> arm-none-eabi-g++ main.o temo.o
>> Produces a.out with only a warning about lack of _start. An objdump shows all
>> objects/variables in the expected section.
>>
>> Why does this work but having it all in a single file doesn't
>
> It doesn't work.
>
> Use -save-temps and -Wl,-Map,linkermap.txt to see where everything goes (I
> suggest also printing &priv, &priv.a and &priv.b).
>
> You will see that priv.a goes into .s1 because of the section attribute in main.cpp.
>
> However, because of the explicit instantiation priv.b goes into .bss, it's a
> specialization, and isn't shared amongst other uses of the template so it's not common
> data anymore (which is the normal way in which static data is handled).
>
> e.g.
>
> 6009d8 &priv
> 6009d8 &priv.a
>
> .s1             0x00000000006009d8        0x4
>   .s1            0x00000000006009d8        0x4 priv2.o
>
> 6009f0 &priv.b
>
> .bss            0x00000000006009e0       0x18
>   ...
>   .bss           0x00000000006009f0        0x0 priv2-temp.o
>   .bss._ZN5outerIiiE1bE
>                  0x00000000006009f0        0x4 priv2-temp.o
>                  0x00000000006009f0                _ZN5outerIiiE1bE
>
> You are perilously poking under the hood of a complex system :-)
>
> Cheers,
> Carlos.

Don't know why but it works for me with all g++. In the previous example,
I see priv.a, priv.b and priv *all* in section .s1 (translated mangled names
with c++-filt in parens):

$ ./a.out
0x600c20 &priv
0x600c20 &priv.a
0x600c1c &priv.b

.s1             0x0000000000600c1c        0x8
  .s1            0x0000000000600c1c        0x4 temp.o
                 0x0000000000600c1c                _ZN5outerIiiE1bE 
(outer<int, int>::b)
  .s1            0x0000000000600c20        0x4 main.o

Double check location with objdump:
24 .s1          00000008  0000000000600c1c  0000000000600c1c  00000c1c  2**2
                 CONTENTS, ALLOC, LOAD, DATA
25 .bss         00000128  0000000000600c40  0000000000600c40  00000c24  2**5
                 ALLOC

None of the "priv" elements appear in .bss!

Here's a more general example that works for me with arm-none-eabi-g++ 
(from CS)
and generic g++ on linux. This is somewhat closer to my actually 
application where
some elements in template class are static and assigned to the containing
object's section (.b), others are static and not assigned a section 
(.c[]) and some
are nether static nor assigned an explicit section (.a):

// temp.h
template<class t1, class t2>
class outer
{
public:
	int             c[3];   // goes to .mysec -- where containing object is 
assigned
	static t2	b;      // goes to .mysec -- explicitly assigned independently
	static t1	a;      // goes to .bss   -- always to default section: 
unassigned static
};

// temp.cpp
#include "temp.h"

template<class t1, class t2>
t2 outer<t1, t2>::b
	__attribute__((section(".mysect")));

template<class t1, class t2>
t1 outer<t1, t2>::a;

template class outer<int, int>;

// main.cpp
#include "temp.h"

int main (void)
{
	static outer<int,int> priv __attribute__((section(".mysect")));  // li:31

	priv.a = 10;
	priv.b = 10;

	priv.c[0] = 144;
	priv.c[1] = 145;
	priv.c[2] = 146;

	cout << &priv << " &priv\n";
	cout << &priv.a << " &priv.a\n";
	cout << &priv.b << " &priv.b\n";
	cout << &priv.c[0] << " &priv.c[0]\n";
}

I build with linux g++ like this (as you suggested):

g++  -save-temps -c -g  main.cpp
g++  -save-temps -c -g  temp.cpp
g++  -save-temps -g -Wl,-Map,linkermap.txt  temp.o main.o

.mysect         0x0000000000600c6c       0x10
  .mysect        0x0000000000600c6c        0x4 temp.o
                 0x0000000000600c6c                _ZN5outerIiiE1bE 
(outer<int,int>::b)
  .mysect        0x0000000000600c70        0xc main.o

  .bss           0x0000000000600da0        0x0 temp.o
  .bss._ZN5outerIiiE1aE (outer<int,int>::a)
                 0x0000000000600da0        0x4 temp.o
                 0x0000000000600da0                _ZN5outerIiiE1aE

Program output:
$ ./a.out
0x600c70 &priv           <---in .mysect
0x600da0 &priv.a         <---in .bss
0x600c6c &priv.b         <---in .mysect
0x600c70 &priv.c[0]      <---in .mysect

Exactly what I want!

-gene









More information about the arm-gnu mailing list