Sida 1 av 1

Veka funktioner i GCC

Postat: 11 oktober 2019, 13:36:51
av Wedge
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?

Re: Veka funktioner i GCC

Postat: 11 oktober 2019, 14:10:27
av sodjan
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.

Re: Veka funktioner i GCC

Postat: 11 oktober 2019, 20:14:17
av Krille Krokodil
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... :D

Re: Veka funktioner i GCC

Postat: 11 oktober 2019, 21:11:43
av arvidb
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!
Ja ibland är det frustrerande.
a_bad_day_in_office.gif
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?

Re: Veka funktioner i GCC

Postat: 11 oktober 2019, 21:29:06
av snigelen
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

Kod: Markera allt

void bar(void) 
{
}

void foo(void)
{
    bar();
}
Anropar man foo så anropas bar som gör ingenting. En fil main.c som anropar foo():

Kod: Markera allt

void foo(void);

int main(void)
{
    foo();
}
Kompilera och kör

Kod: Markera allt

$ gcc -c foobar.c 
$ gcc -o main main.c foobar.o
$ ./main
$ 
Ingenting, som väntat. Om vi nu ändrar main.c till

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();
}
och kompilerar

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
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.c

Kod: Markera allt

void __attribute__((weak)) bar(void) 
{
}

void foo(void)
{
    bar();
}
kompilerar och kör

Kod: Markera allt

$ gcc -c foobar.c 
$ gcc -o main main.c foobar.o
$ ./main
This bar is stonger than foobar's bar
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).

Re: Veka funktioner i GCC

Postat: 12 oktober 2019, 19:49:05
av Mr Andersson
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?
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.

Re: Veka funktioner i GCC

Postat: 14 oktober 2019, 10:25:11
av Wedge
Exempel där konstigheterna visar sig:

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 );
}
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!

Re: Veka funktioner i GCC

Postat: 14 oktober 2019, 12:53:16
av Wedge
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å.

Re: Veka funktioner i GCC

Postat: 6 november 2019, 17:49:32
av Jax
Jag brukar skriva

Kod: Markera allt

void __attribute__((weak)) foo();
Vet inte om det gör någon skillnad.

Man kan i åtminstone GCC även skriva

Kod: Markera allt

#pragma weak foo

void foo();
weak är inte standardiserat så olika kompilatorer kan kanske hantera det lite olika, även olika implementationer av samma kompilator.