Toon posts:

[C++] ondanks library toch 'undeclared reference'

Pagina: 1
Acties:

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Dit is waarschijnlijk een heel triviaal iets.

Ik heb een bestand waaraan bepaalde functies (opzettelijk) ontbreken. Het is de bedoeling dat ik die zelf implementeer. Dit bestand is een ELF relocatable binary.

Stel dat de code in dat bestand gebruik maakt van de functie foo().

Als ik 'm dan gewoon ga compilen krijg ik uiteraard de melding 'undeclared reference to foo'. Dat is logisch.

Dus wil ik een library maken waar de functie 'foo' in zit.

code:
1
2
void foo () {
}


Goed.. van dat bestand maak ik een library.. ik heb zowel statisch (.a) als dynamisch (.so.1) geprobeerd. Dat gaat an sich allemaal goed.

Laten we er even vanuitgaan dat die library libdummy.so.1 heet.

Nu geef ik de door mij gemaakte library mee:

gcc -Wall -ldl -L\pad\naar\library -ldummy inputfile.elf

Ik zou dan verwachten dat 'het probleem' opgelost is, maar helaas.. ik krijg nog steeds 'undefined reference'.

wat doe ik fout?

Nog vermeldenswaardig: de declaratie van foo() komt in de library overeen met de functiecall zoals gedaan in de elf file.

[ Voor 6% gewijzigd door Verwijderd op 10-02-2009 15:51 ]


Acties:
  • 0 Henk 'm!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
De declaratie van foo() zou als het goed is in een header moeten staan, die zowel in je library als de gebruiker van die library wordt geinclude.

De volgende vraag is of je misschien C en C++ mixt. Ondanks het feit dat die twee talen op nogal eens op een hoop worden gegoodi zijn het toch twee talen. Wil je een C functie in C++ gebruiken, dan moet die met
C++:
1
 extern "C" { /*****/ } 
gedeclareerd zijn.

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Het 2e deel: beiden zijn C++, er wordt niet gemixt.

Het 1e deel.. ik heb aangeleverd gekregen een .elf file wat een 'relocatable binary' is. Geen header files, wel een .elf.map. Ik kan dus in die .elf file geen includes meer opnemen en voor wat ik er van begrijp, zou dat ook niet nodig moeten zijn..

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

C++ doet aan name mangling, en compilers zijn vziw vrij om te kiezen hoe. Dus het kan dat je met twee verschillende compilers compiled die er een andere decorated name van maken.

Het beste is om je export list te bekijken: nm - o libxxx.so | grep foo

[ Voor 17% gewijzigd door Zoijar op 10-02-2009 16:15 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ok.. dat helpt inderdaad al een stuk.. ik zie dan inderdaad dat de functienaam mangled is. Nu nog uitzoeken hoe ik 'm dat kan afleren.

Helaas.. het is niet de oplossing. Als ik 'm als extern "C" neerzet, komt hij uit nm wel correct tevoorschijn.. maar still no go..

[ Voor 33% gewijzigd door Verwijderd op 10-02-2009 16:28 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-09 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

Welke is mangled? Als ie in je eigen code gemangled is dan helpt het definieren als extern "C" al een hoop. Als hij in de library gemangled is en die mangling komt niet overeen met die van je huidige compiler dan heb je een groter probleem :)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
m'n eigen code, maar extern "C" lost het probleem dus niet op. De functie komt dan wel goed in de exportlist voor, maar de foutmelding blijft ongewijzigt.

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Vreemd. dus jij export hem unmangled (ie. extern "C"), en de andere heeft ook een unmangled versie nodig? Geen idee. Je kan nog "objdump" gebruiken voor wat info. -t voor de symbol table. Je export de functie ook wel op een manier dat hij toegankelijk is, i.e. niet static?

Acties:
  • 0 Henk 'm!

  • MLM
  • Registratie: Juli 2004
  • Laatst online: 12-03-2023

MLM

aka Zolo

undeclared reference klinkt meer als een missende header file dan een missend linker symbol. Weet je zeker dat je op de plaatsen waar je je library function gebruikt je ook de header file (met extern C erin) hebt?

-niks-


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Hoe kan ik zien wat de ander nodig heeft? Het is een elf relocatable binary, dus geen leesbare code. De foutmelding van de compiler is 'undeclared reference to..'..

Als ik zelf iets maak wat die library wil gebruiken, werkt het wel.

Daarom denk ik ook dat ik iets triviaals fout doe.. mogelijkerwijs hangt het samen met het .elf bestand..?

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Ik zal het proberen uit te leggen. Ik heb een binary file, een relocatable elf binary. Dat is geen leesbare code, ik kan er dus geen includes aan toevoegen.

De code in die file, gebruikt functies die niet gedeclareerd zijn in die file. Ik moet dus die elf library 'extenden' met eigen code.

Daartoe heb ik een eigen library gemaakt en daarna probeer ik ze te linken.. maar dat gaat dus niet.

Vergelijk het met libstdc++, daar hoef je toch ook geen header van te includen?

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-09 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

Is het een fout van de compiler of van de linker? Krijg je bij de foutmelding een .cpp file of een .o file te zien?

.edit: ah wacht, er begint al wat te dagen. Compile je je eigen code als een library? Dan moet je je eigen lib op de commandline van gcc/ld nog een keer opgeven na de elf lib. De linker linkt als ik me niet vergis namelijk in een enkele pass. Als een library dus references introduceert dan gaat ie niet nog een keer kijken of die references toevallig in een eerder opgegeven library staan

[ Voor 70% gewijzigd door .oisyn op 10-02-2009 17:12 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

klopt, headers doen ook feitelijk niets. Dat zijn alleen instructies voor je compiler dat een functie bestaat, en hoe hij eruit ziet.

Je kan op je library doen:

objdump -t xxx

als het goed is staat daar dan iets als:

0000000000000000 *UND* 0000000000000000 foo

Dat is het symbol wat hij nog zoekt. Als je het dan op je andere bestand doet moet je niet zoiets krijgen:

0000000000000000 g F .text 000000000000000c _Z3fooi

maar ook:
0000000000000000 g F .text 000000000000000c foo

Als het C linkage is. (maw: objdump -t test.o | grep *UND* geeft alle undefined symbols in test.o die hij nog nodig heeft)

Nog iets, hebben beide bestanden ook hetzelfde formaat? Is er niet toevallig eentje 64-bit en de andere 32-bit?

[ Voor 16% gewijzigd door Zoijar op 10-02-2009 17:13 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Als ik op de .elf objdump -t doe:

code:
1
00000000         *UND*  00000000 FOO


Als ik het op mijn libdummy.so.1 doe:
code:
1
00001680 g     F .text  0000003c              FOO


Heb ik misschien een heel runderige fout gemaakt met hoe ik het probeer te compilen?

code:
1
gcc -ldl -L\pad\naar\lib\ -ldummy  inputfile.elf


note dat ik even geswitched ben naar C voor de voorbeelden, de daadwerkelijke bestanden en functies heten uiteraard anders, dus dat is een beetje arbitrair allemaal.

De lib zelf heb ik gemaakt door:
code:
1
2
gcc -Wall dummy.c -c
gcc -shared -Wl,-soname,libdummy.so.1 -o libdummy.so.1.0  dummy.o


en daarna nog een symlink gemaakt tussen libdubby.so.1.0 naar libdummy.so

[ Voor 17% gewijzigd door Verwijderd op 10-02-2009 17:17 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-09 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

Zoals ik al zei, probeer eens je eigen lib op te geven na inputfile.elf.

gcc -L\pad\naar\lib\ inputfile.elf -ldummy -ldl


Omdat ie anders de external references uit inputfile.elf niet nog een keer gaat proberen te resolven met libdummy, want die heeft ie al gehad.

[ Voor 78% gewijzigd door .oisyn op 10-02-2009 17:18 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Helaas.. geen sigaar.. overigens misschien vernoemenswaardig dat jouw syntax niet werkt.. dan vind ie de library niet. Pas als ik de -L met het pad expliciet direct voor de -ldummy zet, vind ie 'm..

[ Voor 80% gewijzigd door Verwijderd op 10-02-2009 17:18 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-09 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

Ah ja dat kan best, ben verder niet zo'n ld guru :)

Kun je eens exact de complete foutmelding hier posten?

[ Voor 33% gewijzigd door .oisyn op 10-02-2009 17:23 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Uiteraard:
code:
1
2
inputfile.elf: In function `somefunction':
: undefined reference to `FOO'


Uiteraard heeft die functie in het echt anders, gaat even om het idee ;)

Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

Heb je geen -fPIC nodig bij je gcc -Wall dummy.c -c? (dat even tussendoor; bij mij werkt het anders niet op een x86_64 platform. Ik probeer het te reproduceren...)

Hier werkt het prima... met deze test files:

C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
lib.cpp:
extern "C" int foo(int x) {
    return x;
}

test.cpp:
extern "C" {
    int foo(int x);
}

int main() {
    foo(42);
    return 0;
}


commandos:
code:
1
2
3
4
5
gcc -c test.cpp
gcc -fPIC -c lib.cpp
gcc -shared -W1,-soname,libtest.so.1 -o libtest.so.1.0 lib.o
ln -s libtest.so.1.0 libtest.so
gcc -L. test.o -ltest -lstdc++

[ Voor 109% gewijzigd door Zoijar op 10-02-2009 17:53 ]


Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Die route had ik inderdaad ook gevolgd en dat werkt hier ook. Dan zal 't 'm toch in het 'elf' zijn van de 1e file zitten, en ik nog iets niet begrijpen van elf relocatable binaries..

de -fPIC was niet nodig, althans, hij heeft er niet om gemekkert, maar dat ga ik straks nog wel even proberen.

Ik werk overigens op een linux platform maar de elf in kwestie is voor de power-pc architectuur, ik gebruik crosstools voor e.e.a.

Acties:
  • 0 Henk 'm!

  • MSalters
  • Registratie: Juni 2001
  • Laatst online: 13-09 00:05
Die name mangling kan nog humor worden. De naam die je linker wil hebben is als ik het goed begrijp al gemangled. Exact diezelfde naam moet jij dus produceren. Dat betekent niet alleen dat je de functienaam goed moet krijgen, maar ook de argumentenlijst, en mogelijk de compiler. Name mangling is namelijk bedoeld om "per ongeluk" linken te voorkomen. void Foo(int); linkt niet met void Foo(float) { }

Man hopes. Genius creates. Ralph Waldo Emerson
Never worry about theory as long as the machinery does what it's supposed to do. R. A. Heinlein


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

MSalters schreef op dinsdag 10 februari 2009 @ 21:32:
Die name mangling kan nog humor worden. De naam die je linker wil hebben is als ik het goed begrijp al gemangled. Exact diezelfde naam moet jij dus produceren. Dat betekent niet alleen dat je de functienaam goed moet krijgen, maar ook de argumentenlijst, en mogelijk de compiler. Name mangling is namelijk bedoeld om "per ongeluk" linken te voorkomen. void Foo(int); linkt niet met void Foo(float) { }
Z'n ELF dump geeft aan dat het om unmangled C-linkage gaat, dus dan is het geen probleem.

Het is toch niet bedoeld om "per ongeluk linken" te voorkomen? Volgens mij is het bedoeld om overloading en namespaces (classes) toe te staan

Acties:
  • 0 Henk 'm!

Verwijderd

Topicstarter
Heb je geen -fPIC nodig bij je gcc -Wall dummy.c -c? (dat even tussendoor; bij mij werkt het anders niet op een x86_64 platform. Ik probeer het te reproduceren
Met het schaamrood op mijn kaken, moet ik zeggen dat ik dit nu pas geprobeerd heb.. en dat dit dus het probleem was.

Dank voor de hulp dus weer! :)

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-09 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

Just out of interest, wat doet -fPIC precies?
.edit: ah nevermind, ik kon al niets vinden op google, maar dat was omdat de - ervoor zorgde dat er NIET werd gezocht op pagina's waar fpic in stond. Er moesten quotes omheen :P

[ Voor 66% gewijzigd door .oisyn op 11-02-2009 01:31 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • Zoijar
  • Registratie: September 2001
  • Niet online

Zoijar

Because he doesn't row...

.oisyn schreef op woensdag 11 februari 2009 @ 01:29:
Just out of interest, wat doet -fPIC precies?
.edit: ah nevermind, ik kon al niets vinden op google, maar dat was omdat de - ervoor zorgde dat er NIET werd gezocht op pagina's waar fpic in stond. Er moesten quotes omheen :P
Haha, dat heb ik al zo vaak gehad. Huh? No results? ;) (-fpic genereert relocatable code; Position-Independent-Code, maar dat had je vast al gevonden)
Verwijderd schreef op woensdag 11 februari 2009 @ 01:11:
Met het schaamrood op mijn kaken, moet ik zeggen dat ik dit nu pas geprobeerd heb.. en dat dit dus het probleem was.

Dank voor de hulp dus weer! :)
Ok, mooi! :) Mijn ideeen waren ook op... :P

[ Voor 24% gewijzigd door Zoijar op 11-02-2009 10:10 ]

Pagina: 1