[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