Chyba zepuste uClibc na TH - lvm2 i device-mapper

Jakub Bogusz qboosh w pld-linux.org
Pon, 4 Cze 2007, 19:51:02 CEST


On Mon, Jun 04, 2007 at 05:52:55PM +0200, Jakub Bogusz wrote:
> Nawet jeśli ten poprzedni prototyp dołącza wcześniej, to w krótkim kodzie
> nie powoduje to pominięcia warunku:
> 
> #v+
> #include <stdlib.h>
> 
> extern void func1(void);
> extern void func2(void) __attribute__((visibility("hidden")));
> 
> extern void __attribute__((weak)) func1(void);
> extern void __attribute__((weak)) func2(void) __attribute__((visibility("hidden")));
> 
> # define likely(x)      __builtin_expect((!!(x)),1)
> 
> int main()
> {
>   if(likely(func1 != NULL))
>     func1();
>   if(likely(func2 != NULL))
>     func2();
> }
> #v-

Dobra, mam warunki brzegowe.
-O{1,2,s} + -fPIC.
Przy czym w zrzucie drzewa warunek dalej jest, nie ma go dopiero
w kodzie asemblerowym.

#v+
$ cat ah.c.t93.optimized

;; Function main (main)

Analyzing Edge Insertions.
main ()
{
<bb 0>:
  if (func1 != 0B) goto <L0>; else goto <L1>;

<L0>:;
  func1 ();

<L1>:;
  if (func2 != 0B) goto <L2>; else goto <L3>;

<L2>:;
  func2 () [tail call];

<L3>:;
  return;
#v-

#v+
$ diff -u ah.s.O{0,1}
--- ah.s.O0     2007-06-04 19:18:03.849740867 +0200
+++ ah.s.O1     2007-06-04 19:17:59.273480081 +0200
@@ -8,22 +8,18 @@
        pushl   -4(%ecx)
        pushl   %ebp
        movl    %esp, %ebp
-       pushl   %ebx
-       pushl   %ecx
+       subl    $8, %esp
+       movl    %ecx, (%esp)
+       movl    %ebx, 4(%esp)
        call    __i686.get_pc_thunk.bx
        addl    $_GLOBAL_OFFSET_TABLE_, %ebx
-       movl    func1 w GOT(%ebx), %eax
-       testl   %eax, %eax
+       cmpl    $0, func1 w GOT(%ebx)
        je      .L2
        call    func1 w PLT
 .L2:
-       leal    func2 w GOTOFF(%ebx), %eax
-       testl   %eax, %eax
-       je      .L7
        call    func2
-.L7:
-       popl    %ecx
-       popl    %ebx
+       movl    (%esp), %ecx
+       movl    4(%esp), %ebx
        leave
        leal    -4(%ecx), %esp
        ret
#v-

Też bym się nie spodziewał, że przy adresie wyliczanym względem kodu,
bez tablicy relokacji, wyjdzie NULL ;)

Już rozumiem jak to działa:
- bez -fPIC są inne relokacje i adresy wstawiane bezpośrednio w kod
  (przez ld przy linkowaniu statycznym; przy dynamicznym przez ld-linux,
  ale nie na wszystkich architekturach jest to obsługiwane) - tutaj gcc
  nie zakłada niezerowości
- przy -fPIC i visibility=default i linkowaniu dynamicznym rekolacja
  obliczana jest w runtime i sprawdzenie musi być obecne w kodzie;
  przy statycznym jest obliczana przez ld
- przy -fPIC i visibility=hidden i linkowaniu dynamicznym adres jest
  obliczany przez ld; i tu sprawdza się założenie gcc o niezerowości
  adresu - symbol jest zawsze obecny w bibliotece współdzielonej
  (no dobra, da się zlinkować bez, ale to nie ma sensu, bo binarka
  czy inna biblioteka już tego symbolu nie dostarczy)

natomiast przy statycznym linkowaniu kodu PIC fakt niezerowości
adresu symbolu jest znany w momencie linkowania, a kod został już
zoptymalizowany wcześniej z błędnym założeniem.

W sumie to się nadaje do zgłoszenia do gcc - jeśli zakładają nie
robienie takich rzeczy, to niech przynajmniej udokumentują, że
przy PIC+weak+visibility=hidden dla extern "weak" jest ignorowane.

A swoją drogą na listę uclibc też to można opisać.


-- 
Jakub Bogusz    http://qboosh.pl/


Więcej informacji o liście dyskusyjnej pld-devel-pl