Veka funktioner i GCC
Veka funktioner i GCC
En sån här dag vill man springa runt i korridorerna på jobbet, i hopp om att finna ett kuddrum där man kan gå in, ta en kudde för ansiktet och bara skrika ut sin frustration!
Jag sitter med ett knippe filer som bildar nån sorts modul eller bibliotek.
Jag har ett antal funktioner som skall finnas, men som inte gör speciellt mycket. Vill man ha utökad funktionalitet så är tanken att man själv skriver en ny version av vissa funktioner, och överrider dem. Lite som objektorientering, men ändå inte, här är det helt vanlig C.
Biblioteket innehåller därför ett antal funktioner som försetts med "weak"-attribut.
I MinGW, med GCC 8.2.0 så hittar inte länkaren dessa veka funktioner alls. Märkligt. Utan "weak" länkar den snällt in defaultfunktionen.
Så gör jag ett test i Arduino, med AVR-GCC 5.4.0 (enligt deras changelog). Där länkas den veka funktionen alltid in, även om jag skapat en stark ersättare, utan "weak".
Samtidigt har jag sett detta göras på otaliga ställen av ST i deras HAL, men då kanske projektinställningarna är trimmade på något vis.
Vad är det som händer?
Jag sitter med ett knippe filer som bildar nån sorts modul eller bibliotek.
Jag har ett antal funktioner som skall finnas, men som inte gör speciellt mycket. Vill man ha utökad funktionalitet så är tanken att man själv skriver en ny version av vissa funktioner, och överrider dem. Lite som objektorientering, men ändå inte, här är det helt vanlig C.
Biblioteket innehåller därför ett antal funktioner som försetts med "weak"-attribut.
I MinGW, med GCC 8.2.0 så hittar inte länkaren dessa veka funktioner alls. Märkligt. Utan "weak" länkar den snällt in defaultfunktionen.
Så gör jag ett test i Arduino, med AVR-GCC 5.4.0 (enligt deras changelog). Där länkas den veka funktionen alltid in, även om jag skapat en stark ersättare, utan "weak".
Samtidigt har jag sett detta göras på otaliga ställen av ST i deras HAL, men då kanske projektinställningarna är trimmade på något vis.
Vad är det som händer?
Re: Veka funktioner i GCC
Jag vet inte vad "weak" förväntas göra, men vi all normal länkning
så ersätter man en inbyggd funktion genom att ange en egan före
den inbyggda i biblioteks och objekt referenserna. De flesta länkare
tar första träffen som de hittar.
så ersätter man en inbyggd funktion genom att ange en egan före
den inbyggda i biblioteks och objekt referenserna. De flesta länkare
tar första träffen som de hittar.
- Krille Krokodil
- Inlägg: 4062
- Blev medlem: 9 december 2005, 22:33:11
- Ort: Helsingborg
Re: Veka funktioner i GCC
Synd att man inte utökar C-standarden med de explicita deklarationerna från C++ av sådant.
Jag har verkligen börjat gilla C# nu, de striktare kraven på explicit deklaration, begränsningarna och
minneskontrollerna gör att man tvingas avlusa sin kod ganska väl redan under utvecklingen. Känns
som att man ganska väl har spärrat det som medelmåttiga till svaga C/C++-programmerare ofta gått
vilse i pannkakan på.
I C# gnäller vi åt andra hållet, där vill vi att deklarationen "unsafe" ska ge oss möjligheter till C/C++
strösslad med inline assembler. Man blir aldrig nöjd...
Jag har verkligen börjat gilla C# nu, de striktare kraven på explicit deklaration, begränsningarna och
minneskontrollerna gör att man tvingas avlusa sin kod ganska väl redan under utvecklingen. Känns
som att man ganska väl har spärrat det som medelmåttiga till svaga C/C++-programmerare ofta gått
vilse i pannkakan på.
I C# gnäller vi åt andra hållet, där vill vi att deklarationen "unsafe" ska ge oss möjligheter till C/C++
strösslad med inline assembler. Man blir aldrig nöjd...
Re: Veka funktioner i GCC
Ja ibland är det frustrerande. Kan det vara något problem med/förväxling mellan användningen av weak-attributet i funktionsdeklarationen vs funktionsdefinitionen? Jag gissar bara, men jag läste någonstans att attribut är "sticky" i gcc, så är funktionen deklarerad som weak i headerfilen så kanske det hänger med även till den nya "hårda" definitionen? Vad händer om man deklarerar funktionen utan weak och bara använder attributet i definitionen av den svagt länkade varianten?Wedge skrev:En sån här dag vill man springa runt i korridorerna på jobbet, i hopp om att finna ett kuddrum där man kan gå in, ta en kudde för ansiktet och bara skrika ut sin frustration!
Du har inte behörighet att öppna de filer som bifogats till detta inlägg.
Re: Veka funktioner i GCC
I avr-gcc fungerar naturligtvis __attribute__((weak)). Alla avbrottsvektorer har denna egenskap från början, och du skulle inte kunna ha några egna avbrottsrutiner om inte detta fungerade.
Ett enkelt exempel på weak: En fil foobar.c
Anropar man foo så anropas bar som gör ingenting. En fil main.c som anropar foo():
Kompilera och kör
Ingenting, som väntat. Om vi nu ändrar main.c till
och kompilerar
Gick inte så bra. Så första bästa funkar inte när samma symbol är definierad flera gånger.
Men nu lägger vi in weak på bar i foobar.ckompilerar och kör
så tar bar() i main.c över bar() i foobar.c.
(deklarera man båda bar() som weak så tas däremot "första bästa" utan felmeddelande).
Ett enkelt exempel på weak: En fil foobar.c
Kod: Markera allt
void bar(void)
{
}
void foo(void)
{
bar();
}
Kod: Markera allt
void foo(void);
int main(void)
{
foo();
}
Kod: Markera allt
$ gcc -c foobar.c
$ gcc -o main main.c foobar.o
$ ./main
$
Kod: Markera allt
#include <stdio.h>
void foo(void);
void bar(void)
{
printf("This bar is stonger than foobar's bar\n");
}
int main(void)
{
foo();
}
Kod: Markera allt
$ gcc -o main main.c foobar.o
foobar.o: In function `bar':
foobar.c:(.text+0x0): multiple definition of `bar'
/tmp/cc9I3mmY.o:main.c:(.text+0x0): first defined here
collect2: error: ld returned 1 exit status
Men nu lägger vi in weak på bar i foobar.c
Kod: Markera allt
void __attribute__((weak)) bar(void)
{
}
void foo(void)
{
bar();
}
Kod: Markera allt
$ gcc -c foobar.c
$ gcc -o main main.c foobar.o
$ ./main
This bar is stonger than foobar's bar
(deklarera man båda bar() som weak så tas däremot "första bästa" utan felmeddelande).
-
- Inlägg: 1404
- Blev medlem: 29 januari 2011, 21:06:30
- Ort: Lapplandet
Re: Veka funktioner i GCC
Det stämmer. Har man weak-attributet i en headerfil blir även den nya funktionen weak om man inkluderar headerfilen i den TU:n, och vilken funktion som används bestäms av i vilken ordning man länkar objektfilerna.arvidb skrev:Jag gissar bara, men jag läste någonstans att attribut är "sticky" i gcc, så är funktionen deklarerad som weak i headerfilen så kanske det hänger med även till den nya "hårda" definitionen? Vad händer om man deklarerar funktionen utan weak och bara använder attributet i definitionen av den svagt länkade varianten?
Re: Veka funktioner i GCC
Exempel där konstigheterna visar sig:
Vekhetsattributet gör nånting väldigt mystiskt här. Länkningsfel i "blaj()", funktionen my_func() är odefinerad när jag kör MinGW-projektet.
Funktionen my_func skall ersättas av nånting seriöst i verkligt användande, medan en annan version av funktionen skall användas av Unit-tester.
I övrigt verkar det vara som nämnts i tråden, länkningen tar in första bästa definition. Det sägs kunna kringgås med "--whole-archive", så att en inlänkad vekling kan kastas ut när en stark symbol dyker upp. Jag har inte provat detta.
Får jag inte ordning på detta med weak så får det väl bli funktionspekare istället, men det känns lite... meeh...!
Eller skippa standardbeteendet och weak-attribut, och tvinga slutanvändaren att implementera ALLA alternativfunktioner själv. Ännu mer MEH!
Kod: Markera allt
__attribute__((weak)) void my_func( unsigned char *rnd )
{
memcpy( rnd, (unsigned char*) "\xB0\xB1\xB2\xB3\xB4\xB5\xB6\xB7", 8 );
}
void blaj()
{
unsigned char * foo;
my_func( foo );
}
Funktionen my_func skall ersättas av nånting seriöst i verkligt användande, medan en annan version av funktionen skall användas av Unit-tester.
I övrigt verkar det vara som nämnts i tråden, länkningen tar in första bästa definition. Det sägs kunna kringgås med "--whole-archive", så att en inlänkad vekling kan kastas ut när en stark symbol dyker upp. Jag har inte provat detta.
Får jag inte ordning på detta med weak så får det väl bli funktionspekare istället, men det känns lite... meeh...!
Eller skippa standardbeteendet och weak-attribut, och tvinga slutanvändaren att implementera ALLA alternativfunktioner själv. Ännu mer MEH!
Re: Veka funktioner i GCC
En liten seger, kanske tillfällig...
Jag samlade ihop alla "weak"-funktioner (definitionerna), och lade dem i en separat headerfil (!), som inkluderas där åtkomst till funktionerna behövdes (internt). Doesn't make sense, som de säger over därborta, men om det funkar så inte mig emot...
Deklarationerna, utan weak, hamnade som sig bör i en vanlig headerfil som inkluderas där den behövs, även i slutanvändarens kod.
Sen hade jag kanske tur med länkningsordningen, men en stark funktion kunde ersätta sin veka namne bara genom att finnas! Whee!
MinGW hittade veka funktioner, och även de starka definitionerna, vad kan en hacker mer begära?
Mindre tur i Arduinokoden, men där såg jag att länkningsordningen var sådan att projektfilen, .ino-filen, länkades först. Så ett par starka funktioner fick flytta in dit. Fult, men fungerande, och då jag bara kör en Mega2560 som tillfällig målmiljö och flugsmälla/debugginghjälpmedel fick det duga så.
Jag samlade ihop alla "weak"-funktioner (definitionerna), och lade dem i en separat headerfil (!), som inkluderas där åtkomst till funktionerna behövdes (internt). Doesn't make sense, som de säger over därborta, men om det funkar så inte mig emot...
Deklarationerna, utan weak, hamnade som sig bör i en vanlig headerfil som inkluderas där den behövs, även i slutanvändarens kod.
Sen hade jag kanske tur med länkningsordningen, men en stark funktion kunde ersätta sin veka namne bara genom att finnas! Whee!
MinGW hittade veka funktioner, och även de starka definitionerna, vad kan en hacker mer begära?
Mindre tur i Arduinokoden, men där såg jag att länkningsordningen var sådan att projektfilen, .ino-filen, länkades först. Så ett par starka funktioner fick flytta in dit. Fult, men fungerande, och då jag bara kör en Mega2560 som tillfällig målmiljö och flugsmälla/debugginghjälpmedel fick det duga så.
Re: Veka funktioner i GCC
Jag brukar skriva
Vet inte om det gör någon skillnad.
Man kan i åtminstone GCC även skriva
weak är inte standardiserat så olika kompilatorer kan kanske hantera det lite olika, även olika implementationer av samma kompilator.
Kod: Markera allt
void __attribute__((weak)) foo();
Man kan i åtminstone GCC även skriva
Kod: Markera allt
#pragma weak foo
void foo();