[lenyegeben megoldva] local/label szimbolumok es/vagy szimbolum-mintak kiszedese

Fórumok

Sziaztok!

Valamiert bizonyos architekturakon (pl msp430) szeret a GCC ilyen .L* lokalis szimbolumokat beletenni a text szegmensbe. Pelda: 

$ nm main.elf | sort 
[...]
0000cb34 t transmit_get_iface_by_name
0000cb3e t .L8
0000cb58 t .L6
0000cb5e T testled_init
[...]

amik szepen megjelennek az objdump + disassembly kimenetben is:

0000cb34 <transmit_get_iface_by_name>:
    cb34:       2a 15           pushm   #3,     r10     ;16-bit words
    cb36:       08 4c           mov     r12,    r8      ;
    cb38:       39 40 5c 20     mov     #8284,  r9      ;#0x205c
    cb3c:       4a 43           clr.b   r10             ;

0000cb3e <.L8>:
    cb3e:       0d 48           mov     r8,     r13     ;
    cb40:       2c 49           mov     @r9,    r12     ;
    cb42:       b0 12 72 f0     call    #-3982          ;#0xf072
    cb46:       0c 93           cmp     #0,     r12     ;r3 As==00
    cb48:       07 24           jz      $+16            ;abs 0xcb58
    cb4a:       1a 53           inc     r10             ;
    cb4c:       39 50 36 00     add     #54,    r9      ;#0x0036
    cb50:       3a 90 06 00     cmp     #6,     r10     ;
    cb54:       f4 23           jnz     $-22            ;abs 0xcb3e
    cb56:       3a 43           mov     #-1,    r10     ;r3 As==11
 
0000cb58 <.L6>:
    cb58:       0c 4a           mov     r10,    r12     ;
    cb5a:       28 17           popm    #3,     r10     ;16-bit words
    cb5c:       30 41           ret
 
0000cb5e <testled_init>:
    cb5e:       d2 d3 04 02     bis.b   #1,     &0x0204 ;r3 As==01
    cb62:       30 41           ret

Ha meg itten ezeket fel is oldana az ugyan legalabb valamit segithet az ertelmezesben (lasd: 0xcb54-es cimen  az a `jnz $-22` ehelyett mondjuk `jnz .L8` is lehetne), de mivel meg az sem, ezert ez ugy erosen ront a kimenetek (nm, objdump) olvashatosagan mar egy kozepes projektnel is... :( Peldaul itten most ennel a projektnel:

$ nm main.elf | grep " T " | wc -l
103
$ nm main.elf | grep ".L" | wc -l
645

azaz minden valodi text szimbolumra jut valamivel tobb mint 6 ilyen label-szeruseg... aztan talaljunk meg valamit itten a szenakazalban...  Szoval az X problema az hogy hogyan lehetne azt elerni hogy ezek mar bele se keruljenek a *.o/*.elf-be, az Y problema pedig hogy hamar belekerultek, hogyan lehet kiszedni es/vagy megszabadulni? Az objcopy peldaul tud section pattern-ekre szurni (lasd: `objcopy -j '*' -j '!.persist*' -j ...`), de szimbolum patternre lehet? Tulajdonkeppen semmi nem erdekel ami .L* :] Mas embedded/cross architekturakon (avr, rv32, armv6/v7) nem lattam meg ilyet, de msp430-nal ez most kifejezetten nyugos ha valami szitu van :/

thx, A.

Hozzászólások

-Wa,--strip-local-absolute? (Ld. még --keep-locals.)

Köszi! Igy elsőre mintha nem szendé ki, de az irány az vsz jó lesz :) 

szerk: próbálgattam, msp430-nál sajnos nem oldotta meg... de kipróbálom majd a fordítottját is (arm-mal vagy avr-rel, hogy beleteszi-e) 

Szerk-szerk: Igen, kicsit vegyes a kep a -Wa,--keep-locals kapcsan is: az arm-none-eabi-gcc meg az avr-gcc beleteszi a .L* szimbolumokat, pont ugy mint ahogy msp430-elf-gcc-nel automatikusan belekerul. De a riscv64-unknown-elf-gcc viszont mar nem teszi bele... 

Szerk-szerk-szerk: ami meg feltunt hogy mig az architektura specifikus opciokat a gcc-re egeszen jol rendszerezve osszeszedik (pl az msp430 eseten lasd itten), addig hasonlo, az assemblerrel kapcsolatosos architekturas opciokra mar nem talalni ilyen oldalakat. 

Kozben kis jatszadozas utan ujra felszinre jott ez a .L* szimbolumkupac... Azt talaltam kis ELF-turassal (lasd itten, meg bzt kollega leirasai alapjan - ezuton is koszonet) hogy ezek mind relokacios bejegyzesekhez tartoznak kozvetlenul - mert valamiert az MSP430-nal a PC-relativ ugrasok (leginkabb a feltetelesek, meg egy feltetel nelkuli - 10 bites elojeles offsettel, osszesen 8 ilyen utasitas) valamiert nem oldodnak fel a forditasi idoben, csak linkelesi idoben. Hogy miert, az szamomra rejtely (mas hasonlo RISC architekturaknal, RISC-V, ARM, AVR, ahol szinten vannak ezzel analog utasitasok, ott nincs ilyen, ott mar forditasi idoben feloldodnak a PC-relativ ugrasok). Mindenesetre a *.o-kban benne maradnak a 0-k a megfelelo bitek helyen es a .rela.text(.*) relokacios section-ban meg ezekhez mindig tartozik egy-egy R_MSP430X_10_PCREL (0x13) tipusu relokacio. Es mivel a relokacios cim (ahova ugrani kell) az az ELF strukturaja szerint a symbol table-n keresztul erheto el, ezert ott mar tarsit hozza egy nevet is, "miert ne" alapokon. Ezek lesznek ezek az .L* szimbolumok. Amik egyebkent partial linkelesnel valtoznak, szoval a linker at is nevez(het)i ezeket a szimbolumokat minden tovabbi nelkul. 

Erdekes. Avagy ma is tanultam valamit. 

Lehet megprobalok ezekbol NUL szimbolumot csinalni, szinten "miert ne" alapokon. Akkor a disasm-ot se rontja el annyira illetve a vegso linkelt *.o is kisebb lesz.

Szerk: ezutobbi dolog mukodik. Kicsit trukkosebb, de a --redefine-sym az segit. A wildcard pattern nem megy ezekre, meg akkor sem ha egy adott .L*-bol tobb van (sajna a fentebbi atnevezes/ek/ ellenere a vegso, abszolut modon linkelt ELF-ben lehet tobbszor ugyanaz... csak .L1-bol 23 darab van egy pelda-projektben). Igy pici takolassal:

$ nm main.elf | grep " \.L" | awk '{ print $3; }' | sort | uniq > main.lsym
$ for s in `cat main.lsym`; do msp430-elf-objcopy --redefine-sym $s= main.elf; done

Igen... az `nm` kell es az `msp430-elf-objcopy`. Az `msp430-elf-nm` nem listazza ki a .L* szimbolumokat es a sima `objcopy` nem ismeri fel az "msp430" architekturat... meg igy egyesevel kell kikapni a szimbolumokat, a file-bol valo beolvasas nem segit (valodi skizofren modon azert mert tobbszor definialnam ugyanazt a nevet...) Barhogyis, igy a main.elf-bol keszitett disasm mar egesz olvashato es az *.elf maga is kisebb lett. A NUL szimbolumot legalabb csak 1x helyezi el benne, nem 3492x... 

Szandekosan irsz itten-t az itt helyett? 

Szerkesztve: 2025. 09. 12., p – 17:30

hogyan lehetne azt elerni hogy ezek mar bele se keruljenek a *.o/*.elf-be

Sehogy. Ez az utasításkódolás velejárója. Amikor olyan adatra van szükség, ami immediate-be nem fér bele, de nem is lehet túl messze rakni az adott utasítástól, mert kevés bit van az indirekt címzésére, na ilyenkor van az, hogy belerakja az értéket a kódszegmensbe és egy ilyen cimkét generál hozzá. A példádban ha jól látom 16 bites fixen az utasítás, és max. egy újfent 16 bites immediate lehet csak, hát az nem túl sok.

(Ez egyébként nem a GCC rákfenéje, hanem az utasításkódolásé, ha Assemblyben írnád, akkor is kellenének ezek a cimkék.)

az Y problema pedig hogy hamar belekerultek, hogyan lehet kiszedni es/vagy megszabadulni?

nm main.elf | grep -v 't \.L[0-9]' nem jó? De egyébként is kiszedheted szerintem az összes ponttal kezdődőt, azok tipikusan mindig lokális cimkék.

Mas embedded/cross architekturakon (avr, rv32, armv6/v7) nem lattam meg ilyet

Pedig máshol is van, konkrétan ARM-on sokszor láttam (ott fixen 32 bites lehet az utasítás, immediate-tel együtt, szóval elég gyakori, a MOVK jó trükk, de általában nem elég pontos).

Pedig máshol is van, konkrétan ARM-on sokszor láttam

Megnézem akkor jobban :) v6-M és RV32 esetén konkrét cimke biztos nincs a disasm-ban de simán lehet hogy relokációs bejegyzések ugyanúgy vannak mint MSP430(X)-nél. Csak ezelőbbi arch-oknál NUL symbol-ra mutat, ezutóbbinál meg vették a fáradsgot és/vagy nem szedték ki a .L* label-eket. Pont azért amit mondasz, mármint hogy mert ezek a problémak ott, ezelőbbi ISA-knál is fennállnak. 

Szerk: igen, RV32-nel is ugyanugy vannak ezek a .L* szimbolumok, csak a disasm-ba nem kerulnek bele...