Ket apro, valojaban nem eletbevago de (talan) erdekes kerdes merult fel, GCC toolchainnel valo jatszadozas soran.
Az egyik a reszleges linkelessel kapcsolatos. Tegyuk fel hogy van egy forras, van benne nehany fuggveny, pl igy:
int funct1(int x)
{
return(2*x);
}
int funct2(int y)
{
return(y+10);
}
int entry(int z)
{
int c;
c=0;
while ( 1 )
{ sleep(1);
printf("%d\n",funct2(c));
c++;
}
}
Ezt leforditjuk `gcc -ffunction-sections -fdata-sections` modon. A *.o-ban igy lesz a fentieknek megfeleloen harom .text jellegu section (.text.funct1, .text.funct2, .text.entry). Ebbol `ld -r|--relocatable` modon csinalnek egy masok objectet, ugy hogy a
SECTIONS
{
.text :
{ *(.text.* .text)
}
}
linker scriptnek megfeleloen osszevonom a .text.* section-okat egyetlenegy darab .text section-ba. Ez szuper, el is keszul a *.o/*.elf, minden oke. Viszont a fenti peldaban a funct1()-et nem hivja meg senki, igy szeretnek egy olyan *.o-t (is) amben ez nincs benne. Ha a sima teljes erteku linkelesnek megszokott modon megadom a --gc-sections opciot, akkor az hianyol egy entry-t, ertheto okokbol. Megadon --entry-nek az entry()-t. Igy lefut a reszleges linkeles, lesz is egy darab .text section, de a funct1 az meg mindig benne marad. Probalkoztam KEEP()-ekkel meg ENTRY()-kel a *.lds linker szkriptben is, de az sem segit. Barmi otlet? (( A fenti eljaras nem csak veletlenul hasonlit arra, ahogy a linux kernel modulok, a *.ko-k keszulnek. ))
A masik kerdes meg arrol szol(na), hogyha van egy nagyobb forras, van benne egy fuggveny, amit nehanyszor meghivnak akkor az a teljes forditas + linkeles soran elfordul(hat) hogy a vegso *.elf-bol eltunik, mert az optimalizcio mindenfele inline-ositas miatt a garbage collector a vegen egyszeruen kiszedi azt a section-t. Az teljesen oke. Van-e valami __attribute__ vagy barmi hasonlo amit meg lehet adni hogy ez a fuggveny az legyen "exportalva", azaz kesobbiekben hivhato legyen? A noinline az talan jo is lehetne, de valojaban nem azt akarom (es ugy latom hogy az nem is oldja meg ezt a problemat). Szoval felolem lehet inline ha az ugy jobb/gyrosabb/kisebb (-Ox-tol fuggoen), de maradjon meg a fuggveny a vegso ELF-ben (aztan meg emiatt a vegso binary/hex image-ben).
Thx, A.
- 661 megtekintés
Hozzászólások
A 2-esre esetleg ez? https://stackoverflow.com/a/2164853/182474
Gondolom, ha van rajta visibility, akkor nem szedi ki.
- A hozzászóláshoz be kell jelentkezni
Nem, sajna ez nem segitett, marmint ez a __attribute__((visibility("default"))). A tobbit (hidden, internal, protected) meg sem probaltam, legalabbis ezek neve nagyon nem arra utal hogy exportalgassuk a szimbolumokat kifele :)
Most az lett a "workaround", vagyis a projektnek tkp a resze ugy nez ki hogy maguk a kiexportalando fuggvenyek/szimbolumok igyisugyis ossze vannak gyujtve egy tombben. Ez lenyegeben megoldja ezt a kerdest most a gyarkolatban, es igy a vegso linkelt (relokaciot mar nem tartalmazo) ELF-ben is benne marad a fuggveny, a disassembly-nek megfelelo modon. Ettol fuggetlenul azert erdekel a kerdes mert lehet hogy a jovoben mashogy allitanam elo ezt a tombot, nem ennyire kezzel mint most.
- A hozzászóláshoz be kell jelentkezni
Bocsi, akkor sajnos nem tudom. Egy ideje élvezettel olvasgatom a különböző kalandjaidat a linkelés világágában, ez berémlett régről, amikor még Gentoo-n szívtam dolgokkal, hogy ennek a visibility-s cuccnak pont utánaolvastam mert láttam valami alkalmazásnak a kódjában. Ezen felül azonban a linkelés már nagyon nem az én világom, ez nekem már túl hardverközeli... :D
- A hozzászóláshoz be kell jelentkezni
Hm... most az __attribute__((retain)) dolgot nezem, az joesellyel pont az/olyasmi amit keresek.
- A hozzászóláshoz be kell jelentkezni
Hm... most valami olyasmibe futottam bele hogy az `ld` megeszi szepen az --entry ... opciot, de ha a -T./*.ld-be teszem bele az ENTRY(...)-t akkor azt figyelmen kivul hagyja... :/ Neha kicsit tenyleg fekete magia ez az egesz :)
- A hozzászóláshoz be kell jelentkezni
Lehet, hogy ezen a ponton kezdenék el olcsó kecskéket nézegetni az eBayen. :P
- A hozzászóláshoz be kell jelentkezni
Nem maradt ki itt valami kis részlet, hogy mondjuk mikrokontrollerhez lesz?
Mert boldogult útfi koromban én is linkeltem egyet-s-mást, de nem fordító/linkerspecifikus mágiákkal, hanem a libtool nevű eszközzel, annak például meg lehet mondani, hogy mit exportáljon a linkelendő DSO (regex vagy lista).
- A hozzászóláshoz be kell jelentkezni
Most ez a konkret alapproblema mikrokontrolleres esetekhez kapcsolodik, igen. De a kerdeses folyamat "megall" a teljes linkelesnel (*.elf), amiben mar nincs relokacio, igy (szerintem) ezek altalanosabb, mikrokontroller-fuggetlen kerdesek...
A libtool-t nem ismerem ilyen melysegekben, de akkor megnezem azt is, hatha az is hasznos lesz majd ezekhez, koszi :)
- A hozzászóláshoz be kell jelentkezni
Ezt leforditjuk `gcc -ffunction-sections -fdata-sections` modon.
Ez csak arra jó, hogy külön section-be pakolja, sem láthatóságot, sem használtságot nem kezel önmagában.
igy szeretnek egy olyan *.o-t (is) amben ez nincs benne.
Tudtommal ez nem megoldható, ellenben a végső programból kihagyható, ha
-Wl,--gc-sections
kapcsolót adsz meg. De ezt ugye a linker kapja és a szekciószanálást is az végzi, nem a gcc, szóval csak a legutolsó végeredmény ELFből fog kimaradni a funct1() sectionje, az .o fájlból nem.
most valami olyasmibe futottam bele hogy az `ld` megeszi szepen az --entry ... opciot, de ha a -T./*.ld-be teszem bele az ENTRY(...)-t akkor azt figyelmen kivul hagyja...
Ebbe én is belefutottam pár éve, de nem emlékszem már, hogy melyik linker volt, mindenesetre ugyanaz a forrás és linkerszkript az egyik gcc+ld-vel ment, Clang+lld-vel meg nem (vagy fordítva, rég volt). A lényeg, hogy ez egyértelműen linker bug. Ha jól tévedek, akkor az architektúrát és kimenet formátumát kellett megadni a linkerszriptben, hogy megjavuljon. Valami ilyesmi:
OUTPUT_FORMAT("elf64-x86-64", "elf64-x86-64", "elf64-x86-64") OUTPUT_ARCH(i386:x86-64) ENTRY(_start)
Ettől azért javult meg, mert ha nem adtad meg a formátumot pontosan, akkor a linker a végén berántott valami default szkriptet is, és abban meg volt egy sor, ami meg jól felülcsapta az általad megadott ENTRY()-t... Persze lehet, hogy nálad tök más probléma miatt nem eszi meg az ENTRY()-t.
- A hozzászóláshoz be kell jelentkezni
Ebbe én is belefutottam pár éve, de nem emlékszem már, hogy melyik linker volt, [...]
Koszi, ez lehet hogy jo irany! Most kiegeszitettem a cuccmanyt igy:
OUTPUT_FORMAT("elf32-msp430")
OUTPUT_ARCH(msp430)
ENTRY(init)
De ettol nem javult meg, ugyanugy kell neki az `--entry init` argumentum. Most ezt ld-vel linkeltem kozvetlenul, de ha gcc-vel linkelem akkor is kell neki a -Wl,--entry=init. Ugy mukodik, enelkul nem, hiaba van ott a linker script-ben. Elso kozelitesben ebbol a leirasbol indultam ki.
akkor a linker a végén berántott valami default szkriptet is,
Ezt megnezem akkor strace-szel, hatha kidobja mit is rant be... Lehet hogy tenyleg berant egy default linker scriptet ami viszont "hatastalanitja" a korabbi ENTRY()-t, nem tudom... Szerk: nem, nem tolt be semmit... Akkor tenyleg marad a bug...
- A hozzászóláshoz be kell jelentkezni
Hm... a linker script meg tovabbra sem tudja atadni az ENTRY()-t. Kicsit nezegettem ilyen "hatha" jelleggel, de semmi.
Ugyanakkor az felmerult bennem hogy akar C forrasbol, valahogy a *.o-kon keresztul nem adhato-e at hogy ki/mi legyen az entry point? Nyilvan nem (annyira) egyertelmu hogy ez megteheto, de... ki tudja...
- A hozzászóláshoz be kell jelentkezni
Nem nyitok ennek uj temat, es csak lazan kapcsolodik az eredeti temahoz... de vegulis azert kapcsolodik.
Ugye ha azt mondom hogy
static uint8_t array[128];
akkor ez a tomb (array[]) az bekerul a .bss-be (vagy .bss.*-ba). Ez oke. Ha azt mondom hogy:
static __attribute__ ((section(".valami"))) uint8_t array[128];
majd kesobb a linker scriptben valami ilyesmit:
.bss : { *(.bss .bss.* .valami) }
akkor a (teljesen es/vagy reszlegesen) linkelt .bss section-ja az mar nem NOBITS lesz hanem PROGBITS. Hogy ez nyilvanvalo-e vagy nem az jo kerdes, de a .valami-rol nem mondtam semmit. A dolog megoldhato linker script szinten is:
.bss (NOLOAD) : { *(.bss .bss.* .valami) }
Es igy okes lesz, minden szuper. Node kerdes hogy van-e ennel kulturaltabb megoldas erre. A gond az az hogy ha veletlenul azt mondom hogy:
static __attribute__ ((section(".valami"))) uint8_t array[128] = { 1, 2, 3, 4, ... };
Akkor a .valami az mar nem a .bss-be kellene hogy menjen hanem a .data-ba (es ha meg a const-ot is odairnam akkor a .rodata-ba), es a NOBITS-et sem kaphatja meg. Nyilvan vigyazni kell. A kerdes hogy ilyenkor mit lehet tenni hogy ezt a problemakort (a korulmenyekhez kepest) kulturaltan kezeljuk. Lehet ilyen .valami,"aw",@nobits jellegu section-okkal is trukkozni? De ugye az hogy egy section az @nobits vagy @progbits lesz az pont attol fugg hogy en csinalok-e ertekadast a mezei C kodban vagy nem, tehat nekem kezzel nem kene beleszolnom. Szoval vallojaban az a kerdes hogy a .valami az miert is lesz @progbits amikor a deklaracio (legelso pelda fent, a sima static uint, meg a masodik, az __attribute__-s) is egyertelmuen azt mondja hogy ez @nobits jellegu kell hogy legyen. A .valami section-t ezen kivul masra nem hasznalom itten, csak ez az egyetlen elofordulasa. Vagy ezek a tulajdonsagok az "aw"-n keresztul oroklodnek...?
- A hozzászóláshoz be kell jelentkezni