- 314 megtekintés
Hozzászólások
Mit lehetne itten tenni? Hogyan tudnam eroltetni az linkert (pl a megfelelo -Wl,... kapcsoloval) hogy marpedig a _start az legyen a 0x20000000 cimen es/vagy a .text legelejen?Nem kapcsoló, linker script kell neked.
Maga a szerkesztes egyebkent olyan hogy a text is a RAM-ba (a 0x20000000-s cimre) van eroltetveLinker script esetén kierőszakolható a konkrét RAM cím is, de szerintem ne szopj ezzel. Helyette add meg a linking address-t, és szépen sorjában tedd bele a text segment-be a text section-öket. Pl:
.text : {
. = 0x20000000;
KEEP(start.o(.text))
*(.text .text.*)
}
Ez bepakolja a .text és .text.akármi section-öket a text segment-be úgy, hogy a start.o-ból származó .text section kerüljön a segment legelejére (a "KEEP" elvileg nem kell, csak túlbiztosítás, az csak annyit jelent, hogy még az optimalizáló se mozgassa át, ha eseteg valamiért át akarná mégis mozgatni. Nem szokta akarni egyébként).
Ha csak a _start függvényt akarod előrerakni, és nem akarsz a fájlnevekkel bajlódni, vagy a start.o-ban több függvény is van és az _start nem a legeslegelső, akkor meg megoldás ez is:
.text : {
. = 0x20000000;
KEEP(*(.text.start))
*(.text .text.*)
}
A forrásba meg:
void __attribute__((section(".text.start"))) _start(void);
beagyazott rendszer jelleg ellenere ez most egy teljesen "von Neumann" linkeles: azaz mind a text, mind a data meg a bss (meg a heap) az a 0x20000000 cimtartomanyban vanEz meg .text : { . = 0x20000000; KEEP(*(.text.start)) *(.text .text.*) *(.rodata .rodata.*) *(.data .data.*) } .bss (NOLOAD) : { . = ALIGN(16); *(.bss .bss.*) *(COMMON) } :text Itt a turpisság annyi, hogy a bss segment, ami NOLOAD jelzőt kap, azt meg hozzácsapjuk a text segment-hez (lásd a legvégén a blokkbezáró utánni ":text"-et). Rakhattuk volna eleve a bss section-öket is a text segmentbe, de akkor annak a mérete pont annyi lenne, mint a memóriakép mérete, a végén egy valag nullával. Így viszont a text segment mérete továbbra is annyi, de a lementett memóriakép végéről hiányoznak a nullák. (ELF esetén ez úgy mondanám, hogy első esetben filesz = memsz, második esetben filesz + bss = memsz).
- A hozzászóláshoz be kell jelentkezni
- A hozzászóláshoz be kell jelentkezni
De az a baj hogy sajat linker script eseten is modositani kellene a gyari crt0.o-t mert szemmel lathatolag pont ez az altalad is emlitett __attribute__((section(".text.start"))) maradt kiNem kell, ilyenkor használd a
KEEP(crt0.o(.text)) formát (az nem derül ki a kimenetből, hogy vannak-e más függvények is benne, de ha megfelel a szabványnak, akkor nem kéne, hogy a crt0.o-ban bármi más legyen).
Ja, és legyél biztos, hogy megfelelőek a linker kapcsolóid, mert statikus címre linkelés esetén nem szabadna, hogy a végeredményben "rela" rekordjaid legyenek. Mivel a kódod rom-ból fut, ezeket ugyanis senki sem fogja feloldani neked.
Mig picolibc eseten ez rendbenlevonek tunikEz nem C, hanem C++ szabvány. Ott előírás, hogy a global constructor-oknak a ".text.init" section-be kell kerülniük, a global destructor-oknak meg a ".text.fini" section-be. A picolibc-t gondolom úgy írták, hogy kompatíbilis legyen a C++-al is, míg a newlib-nél ez nem volt szempont. (Megjegyzés, Darwin alatt egy tök másik szabvány terjedt el, de ez is előjöhet libc-k esetén: ott a global constructor-ok és global destructor-ok címei két tömbbe kerülnek, és a crt0.o-ban van kötelezően két ciklus, ami végigiterál ezeken, az első a main hívása előtt, a második utánna.)
ARM eseten pedig nem baj ha a _start nem .text elejen van mert a vektortablat igyisugyis letre kell hoznod (olyannyira hogy ugye az kerul a .text elejere), es majd azt linkeled be a vektortabla[1]-be ahova kerul a _start).Ez nem így van. Erősen chipgyártó függő, nincs olyan, hogy ARM szabvány. RPi alatt például a _start-nak kell a text legelején lennie, és a vektortábla kezdőcíme egyébként meg a VBAR rendszerregiszterben található, és bárhol lehet.
- A hozzászóláshoz be kell jelentkezni
Nem kell, ilyenkor használd a
KEEP(crt0.o(.text))formát
Ezt hol? A sajat linker scriptben is feluldefinialhatom hogy a crt0.o legyen egy masik szegmensben? De akkor pont nem a "keep" mint szakkifejezes lenne logikus :)
(az nem derül ki a kimenetből, hogy vannak-e más függvények is benne, de ha megfelel a szabványnak, akkor nem kéne, hogy a crt0.o-ban bármi más legyen).
Nem, halistennek nincs benne mas. Ez oke.
Ja, és legyél biztos, hogy megfelelőek a linker kapcsolóid, mert statikus címre linkelés esetén nem szabadna, hogy a végeredményben "rela" rekordjaid legyenek.
Ezzel nincs gond, a vegeredmenyben (main.elf) nincsenek mar .rela.* szegmensek. Amit fentebb bemasoltam az a crt0.o-k felepitese.
(Megjegyzés, Darwin alatt egy tök másik szabvány terjedt el, de ez is előjöhet libc-k esetén: ott a global constructor-ok és global destructor-ok címei két tömbbe kerülnek, és a crt0.o-ban van kötelezően két ciklus, ami végigiterál ezeken, az első a main hívása előtt, a második utánna.)
Ez viszont itt is igy van: itt is vegigszalad a _start a __libc_init_array-n a main() elott es a __libc_fini_array-n a main() utan. Ez newlib-ben is, meg picolibc-ben is van mar. Szoval C-ben is tudok csinalni global konstruktorokat, azzal nincs gond (pl feluldefinialni az stdout-ot majd igy probalom meg, hogy pl a printf() egy eloredefinialt UART-ra irjon, ha ugy hozza a sors).
Ez nem így van. Erősen chipgyártó függő, nincs olyan, hogy ARM szabvány. RPi alatt például a _start-nak kell a text legelején lennie, és a vektortábla kezdőcíme egyébként meg a VBAR rendszerregiszterben található, és bárhol lehet.
Igen, jogos, akkor azt mondom hogy Cortex-M architekturakon :) Cortex-A az valoban lehet teljesen mas, de azt nem ismerem bare metal szinten. Cortex-M-nel alapesetben a 0-s cimen mindig a vektortabla van, es akkor azt implementaciofuggoen vagy atmappeled mashova (Cortex-M0), vagy VTOR-ral atirod ha szukseges es/vagy letezik egyatalan a VTOR.
- A hozzászóláshoz be kell jelentkezni
Ezt hol? A sajat linker scriptben is feluldefinialhatom hogy a crt0.o legyen egy masik szegmensben?Hát a saját linker scriptedben. Nem definiálsz felül semmit, egyszerűen csak megadod, hogy milyen sorrendben pakolássza be a section-öket a segment-be. De igen, akár rakhatod egy tök másik szegmensbe is, szabad kezed van. (Ha ELF kimenetet generálsz például, akkor ezek virtuális szegmensek csak, és akárhány lehet belőlük, és csak a PHDRS blokkban sorolod be őket tényleges szegmensekké.) Ja, jut eszembe, olyan is szokott lenni, hogy amikor csak .text van a crt0.o-ban, akkor mellette van még több más crtX.o fájl is. Ekkor az összeszerkesztés sorrendje crt0.o, crti.o, crtbegin.o, (minden más .o), crtend.o, crtn.o. Ilyenkor ha csak a crt0.o-t szerepelteted a linker scriptedben, vagy nem ezt a sorrendet használod, akkor nem lesz jó.
De akkor pont nem a "keep" mint szakkifejezes lenne logikus :)Mondom, azt értsd úgy, hogy a section relatív pozíciója a segment-en belül. A segment-en belüli címe az, ami "keep", szóval az nem változhat. De csak a biztonság kedvéért raktam bele, valószínűleg nem kell (de megéri berakni, mert abban a nagyon ritka esetben, ha mégis kéne, de nincs, na az szívás).
- A hozzászóláshoz be kell jelentkezni
Ja, jut eszembe, olyan is szokott lenni, hogy amikor csak .text van a crt0.o-ban, akkor mellette van még több más crtX.o fájl is. Ekkor az összeszerkesztés sorrendje crt0.o, crti.o, crtbegin.o, (minden más .o), crtend.o, crtn.o. Ilyenkor ha csak a crt0.o-t szerepelteted a linker scriptedben, vagy nem ezt a sorrendet használod, akkor nem lesz jó.
Ah, koszi, igen, ez hasznos. Ha jol latom ezeket (crti, crtbegin ...) a libgcc tudja beletenni, ha epp, es csak a crtbegin-ben van "erdemi" tartalom. De aztan persze lehet a barmi masban is, mas architekturakon.
- A hozzászóláshoz be kell jelentkezni
Kozben meg a ((section(...))) trukkozessel sikerult egy ilyesmit kifundalni:
void __attribute__((section(".text.unlikely"), naked, used, retain)) _startup(void);
void _start(void);
void _startup(void)
{
/* __asm__ ("j _start\n"); */
_start();
}
Hogy miert unlikely, na az is egy jo dilemma, de az xPack eseten a gyari linker script (elf32lriscv.xn) az ilyen:
.text :
{
*(.text.unlikely .text.*_unlikely .text.unlikely.*)
*(.text.exit .text.exit.*)
*(.text.startup .text.startup.*)
*(.text.hot .text.hot.*)
*(SORT(.text.sorted.*))
*(.text .stub .text.* .gnu.linkonce.t.*)
/* .gnu.warning sections are handled specially by elf.em. */
*(.gnu.warning)
}
Az osszes tobbi (.startup, .start, .init) az nem jott be, maradt az unlikely...
Az mas kerdes hogy ez sem jo megoldas, mert pl ez a newlib-es libc szereti hasznalni az ecall-okat ugy bele a vakvilagba, ami meg szinten tobb egyeb kerdest vet fel :/ de az mar (kicsit) mas tema.
- A hozzászóláshoz be kell jelentkezni
void __attribute__((noreturn)) _startup(void) {
/* inline assembly-vel kezelve a vermet és a _start hívást meg a visszatérést */
asm volatile(...);
__builtin_unreachable();
}
Iszonyat csúnya, de mivel híváskor nincs még verem, így az inline assembly rész az, ahol a vermet beállítom, emiatt pedig ugye nem lehet function prologue, mert az már használni akarná.- A hozzászóláshoz be kell jelentkezni
Na ez tök kafa, ha jól értem, így maradtál a gyári linker scriptnél, ami jó, mert kevesebb szívás.
Igenigen, alapjaraton szeret(n)ek maradni a gyari dolgoknal - mert aztan meg ha a sajat herkelmeny mukodik is, nehogy kesobb ebbol legyen a meglepetes :) C-nel meg csakcsak de C++ eseten... na, azt nehez kinyomozni egy headless rendszer eseten :]
Iszonyat csúnya, de mivel híváskor nincs még verem, így az inline assembly rész az, ahol a vermet beállítom, emiatt pedig ugye nem lehet function prologue, mert az már használni akarná.
Uh, de jo hogy mondod ezt, koszi! Merthogy most ezalapjan szurtam ki most hogy ez az xPack-os newlib/nano/nosys-ben levo crt0.so az _nem_ inicializalja az sp-t. Ami ugye feltetelezhetoen onnan jon hogy a newlib (eredetileg?) ARM Cortex-M-ekhez keszult - es ott ugye ezt nem kell mert a vektortabla[0] tartalmazza es az ARM core az onnan be kell hogy rantsa megmielott a vektortabla[1]-re ugrik. De RISC-V eseten az sp (x2) az inicializalatlan bekapcsolas utan (definicio szerint) es csak a pc vesz fel egy (egyebkent implementaciofuggo, azaz a processzorba vasalt) erteket.
- A hozzászóláshoz be kell jelentkezni