[Bug 1079] libchk (classchk.c) unable to deal properly with "new" PPC64 ABI

[email protected] Thu, 06 Oct 2005 00:46:24 -0400
Newsgroups gmane.linux.lsb.test-suite
Message-ID <[email protected]>


------- Additional Comments From [email protected]  2005-10-06 00:46 -------
(In reply to comment #4)
> Current feedback from the architecture expert is that the implementation ought
> not to fail dladdr this way - it's the sign of a buggy glibc.  The reference for
> the patch is: http://sourceware.org/ml/libc-hacker/2005-08/msg00012.html.
> There's no reasonable way for libchk to work around this.
> 
> 
Asked Jakub for a patch. Hope it helps.


--- lsb-libchk-3.0.3/tests/misc/libchk/classchk.c.jj    2005-07-12
21:10:20.000000000 +0200
+++ lsb-libchk-3.0.3/tests/misc/libchk/classchk.c       2005-09-30
16:08:55.000000000 +0200
@@ -7,6 +7,9 @@
 #include <stdlib.h>
 #include <sys/stat.h>
 #include <dlfcn.h>
+#ifdef __powerpc64__
+#include <link.h>
+#endif
 #include "elfchk.h"
 #include "hdr.h"
 #include "tetj.h"
@@ -69,7 +72,7 @@ int
 check_class_info(ElfFile *file, char *libname, struct classinfo *classes[],
struct tetj_handle *journal)
 {
        int     i,j,v;
-       Dl_info dlinfo;
+       Dl_info dlainfo;
        void    *dlhndl;
        void    *symp;
        void    **basetypes;
@@ -84,6 +87,9 @@ check_class_info(ElfFile *file, char *li
        int fndvttsize;
        char tmp_string[TMP_STRING_SIZE+1];
        int test_failed;
+#ifdef __powerpc64__
+       void *opd_start = NULL, *opd_end = NULL;
+#endif
 
        if (classes == NULL) 
                return 0;
@@ -102,6 +108,20 @@ check_class_info(ElfFile *file, char *li
        tetj_result(journal, tetj_activity_count, tetj_tp_count, TETJ_PASS);
        tetj_purpose_end(journal, tetj_activity_count, tetj_tp_count++);
 
+#ifdef __powerpc64__
+       for (i=1; i<file->numsh; i++)
+               if (strcmp(ElfGetString(file, file->saddr[i].sh_name), ".opd") == 0)
+                       break;
+       if (i<file->numsh)
+       {
+               struct link_map *lm;
+               if (dlinfo (dlhndl, RTLD_DI_LINKMAP, &lm) >= 0)
+               {
+                       opd_start = (void *) (file->saddr[i].sh_addr + lm->l_addr);
+                       opd_end = (void *) ((char *) opd_start +
file->saddr[i].sh_size);
+               }
+       }
+#endif
 
        /* Examine each class here */
        for (i=0; classes[i]!=NULL; i++) 
@@ -196,20 +216,20 @@ check_class_info(ElfFile *file, char *li
                                tetj_purpose_start(journal, tetj_activity_count,
tetj_tp_count,
                                                                               
                         "Checking rtti value");
                                test_failed = 0;
-                               dladdr(vttypeinfo,&dlinfo);
+                               dladdr(vttypeinfo,&dlainfo);
                                if ( (libchk_debug&LIBCHK_DEBUG_CLASSDETAILS) &&
-                                                dlinfo.dli_saddr != vttypeinfo) 
+                                                dlainfo.dli_saddr != vttypeinfo) 
                                {
                                        TETJ_REPORT_INFO("Uhoh1. Not an exact
match %p %p",
-                                                                              
                         dlinfo.dli_saddr, vttypeinfo);
+                                                                              
                         dlainfo.dli_saddr, vttypeinfo);
                                        test_failed = 1;
                                }
        
-                               if
(strcmp(classp->vtable[v].typeinfo,dlinfo.dli_sname)) 
+                               if
(strcmp(classp->vtable[v].typeinfo,dlainfo.dli_sname)) 
                                {
                                        fprintf(stderr,"Class %s\n", classp->name );
                                        TETJ_REPORT_INFO("RTTI Name %s
(expected) doesn't match %s (found)",
-                                                                              
                         classp->vtable[v].typeinfo,dlinfo.dli_sname);
+                                                                              
                         classp->vtable[v].typeinfo,dlainfo.dli_sname);
                                        test_failed = 1;
                                }
 
@@ -232,8 +252,8 @@ check_class_info(ElfFile *file, char *li
                                         * Look up the name of the symbol
associated with the funcptr
                                         * found in the vtable.
                                         */
-                                       memset(&dlinfo,0,sizeof(dlinfo));
-                                       if( !dladdr(fptr2ptrp(&vtvirtfuncs[j]),
&dlinfo) ) {
+                                       memset(&dlainfo,0,sizeof(dlainfo));
+                                       if( !dladdr(fptr2ptrp(&vtvirtfuncs[j]),
&dlainfo) ) {
                                                fprintf(stderr,"Class %s\n",
classp->name );
                                                TETJ_REPORT_INFO("Error looking
for symbol for Virtual table entry "
                                                                               
                                 "[%d][%d](%p) expecting %s",
@@ -246,30 +266,41 @@ check_class_info(ElfFile *file, char *li
                                        if( classp->vtable[v].virtfuncs[j][0] ) {
                                                symp = dlsym(dlhndl,
classp->vtable[v].virtfuncs[j]);
                                                if ( symp !=
fptr2ptrp(&vtvirtfuncs[j]) ) {
-                                                       Dl_info dlinfo2;
+                                                       Dl_info dlainfo2;
                                                        int s;
                                                        for(s=0;s<12;s++) {
-                                                              
memset(&dlinfo2,0,sizeof(dlinfo2));
-                                                              
dladdr(fptr2ptrp(&vtvirtfuncs[s]), &dlinfo2);
-                                                              
fprintf(stderr,"vtable[%d] %p %s\n", s, vtvirtfuncs[s], dlinfo2.dli_sname );
+                                                              
memset(&dlainfo2,0,sizeof(dlainfo2));
+                                                              
dladdr(fptr2ptrp(&vtvirtfuncs[s]), &dlainfo2);
+                                                              
fprintf(stderr,"vtable[%d] %p %s\n", s, vtvirtfuncs[s], dlainfo2.dli_sname );
                                                        }
-                                                      
memset(&dlinfo2,0,sizeof(dlinfo2));
-                                                       dladdr(symp, &dlinfo2);
+                                                      
memset(&dlainfo2,0,sizeof(dlainfo2));
+                                                       dladdr(symp, &dlainfo2);
                                                        fprintf(stderr,"Class
%s\n", classp->name );
                                                        TETJ_REPORT_INFO("Symbol
address for Virtual table entry "
                                                                               
                                 "[%d][%d] %s is not expected", v, j, 
                                                                               
                                 classp->vtable[v].virtfuncs[j]);
                                                        fprintf(stderr,"%p
doesn't match %p which appears to be %s %p\n", 
-                                                                              
        symp, fptr2ptrp(&vtvirtfuncs[j]), dlinfo2.dli_sname, dlinfo2.dli_saddr);
+                                                                              
        symp, fptr2ptrp(&vtvirtfuncs[j]), dlainfo2.dli_sname, dlainfo2.dli_saddr);
                                                test_failed = 1;
                                                }
                                        }
 #endif
 
+#ifdef __powerpc64__
+                                       /* On PPC64, especially with overlapping
.opd entries,
+                                          it is possible that dladdr returns a
preceeding
+                                          symbol rather than no symbol.  */
+                                       if( dlainfo.dli_saddr >= opd_start &&
dlainfo.dli_saddr < opd_end
+                                           && fptr2ptrp(&vtvirtfuncs[j]) >=
(void *) ((char *) dlainfo.dli_saddr + 16) ) {
+                                               dlainfo.dli_saddr = NULL;
+                                               dlainfo.dli_sname = NULL;
+                                       }
+#endif
+
                                        /*
                                         * 1.4.1) Make sure we found a named
symbol at all.
                                         */
-                                       if ( !dlinfo.dli_saddr &&
classp->vtable[v].virtfuncs[j][0] ) {
+                                       if ( !dlainfo.dli_saddr &&
classp->vtable[v].virtfuncs[j][0] ) {
                                                fprintf(stderr,"Class %s\n",
classp->name );
                                                TETJ_REPORT_INFO("Did not find
symbol addr for Virtual table entry "
                                                                               
                                 "[%d][%d] expecting %s", v,
@@ -281,19 +312,19 @@ check_class_info(ElfFile *file, char *li
                                         * 1.4.2) Check to see if the symbol
found is an exact match 
                                         * for the funcptr that was used for the
lookup.
                                         */
-                                       if( dlinfo.dli_saddr &&
-                                                       (fptr2ptr(((fptr
*)dlinfo.dli_saddr))!=fptr2ptrp(&vtvirtfuncs[j])) ) 
+                                       if( dlainfo.dli_saddr &&
+                                                       (fptr2ptr(((fptr
*)dlainfo.dli_saddr))!=fptr2ptrp(&vtvirtfuncs[j])) ) 
                                        {
                                                if(
(!libchk_debug&LIBCHK_DEBUG_CXXHUSH) ) {
                                                        printf("Uhoh2. Not an
exact match %p %p\n",
-                                                                              
 dlinfo.dli_saddr, fptr2ptrp(&vtvirtfuncs[j]));
+                                                                              
 dlainfo.dli_saddr, fptr2ptrp(&vtvirtfuncs[j]));
                                                        printf("Uhoh2. Not an
exact match %s %s\n",
-                                                                              
 dlinfo.dli_sname, classp->vtable[v].virtfuncs[j]);
+                                                                              
 dlainfo.dli_sname, classp->vtable[v].virtfuncs[j]);
                                                }
                                                fprintf(stderr,"Class %s\n",
classp->name );
                                                TETJ_REPORT_INFO("Symbol address
found for Virtual table entry [%d][%d] "
                                                                               
                                 "%p (found) doesn't match %p (expected)",
-                                                                              
                                 v, j, fptr2ptr(((fptr *)dlinfo.dli_saddr)),
+                                                                              
                                 v, j, fptr2ptr(((fptr *)dlainfo.dli_saddr)),
                                                                               
                                 fptr2ptrp(&vtvirtfuncs[j]));
                                                test_failed = 1;
                                        }
@@ -301,7 +332,7 @@ check_class_info(ElfFile *file, char *li
                                        /*
                                         * 1.4.3) Make sure we found a named
symbol at all.
                                         */
-                                       if ( !dlinfo.dli_sname &&
classp->vtable[v].virtfuncs[j][0] ) {
+                                       if ( !dlainfo.dli_sname &&
classp->vtable[v].virtfuncs[j][0] ) {
                                                fprintf(stderr,"Class %s\n",
classp->name );
                                                TETJ_REPORT_INFO("Did not find
symbol name for Virtual table entry "
                                                                               
                                 "[%d][%d] expecting %s", v,
@@ -313,14 +344,14 @@ check_class_info(ElfFile *file, char *li
                                         * 1.4.4) Check to see if the symbol
name found matches what we
                                         * are expecting to find
                                         */
-                                       if (((classp->vtable[v].virtfuncs[j] &&
dlinfo.dli_sname) &&
-                                                       
strcmp(classp->vtable[v].virtfuncs[j], dlinfo.dli_sname)) ||
-                                                       (dlinfo.dli_sname &&
!classp->vtable[v].virtfuncs[j])) 
+                                       if (((classp->vtable[v].virtfuncs[j] &&
dlainfo.dli_sname) &&
+                                                       
strcmp(classp->vtable[v].virtfuncs[j], dlainfo.dli_sname)) ||
+                                                       (dlainfo.dli_sname &&
!classp->vtable[v].virtfuncs[j])) 
                                        {
                                                fprintf(stderr,"Class %s\n",
classp->name );
                                                TETJ_REPORT_INFO("Virtual
Function[%d][%d] %s (expected) "
                                                                               
                                 "doesn't match %s (found)", v,
-                                                                              
                                 j, classp->vtable[v].virtfuncs[j],
dlinfo.dli_sname);
+                                                                              
                                 j, classp->vtable[v].virtfuncs[j],
dlainfo.dli_sname);
                                                test_failed = 1;
                                        }
                                }
@@ -386,14 +417,14 @@ check_class_info(ElfFile *file, char *li
                        symp = dlsym(dlhndl, classp->typeinfo->basevtable);
                        if (symp+(2*sizeof(long)) != rttip->basevtable) 
                        {
-                               dladdr(rttip->basevtable-8, &dlinfo);
+                               dladdr(rttip->basevtable-8, &dlainfo);
                                if( (libchk_debug&LIBCHK_DEBUG_CLASSDETAILS) &&
-                                               (vtablep && dlinfo.dli_saddr !=
vttypeinfo) )
+                                               (vtablep && dlainfo.dli_saddr !=
vttypeinfo) )
                                {
                                        printf("Uhoh3. Not an exact match\n");
                                }
                                TETJ_REPORT_INFO("Base vtype %p (expected)
doesn't match %p %s (found)",
-                                                                              
                 symp, rttip->basevtable, dlinfo.dli_sname);
+                                                                              
                 symp, rttip->basevtable, dlainfo.dli_sname);
                                tetj_result(journal, tetj_activity_count,
tetj_tp_count, TETJ_FAIL);
                        }
                        else
@@ -474,11 +505,11 @@ check_class_info(ElfFile *file, char *li
                                 * Check the basename.
                                 */
                                symp = dlsym(dlhndl,classp->basename);
-                               dladdr(si_rttip->basetype, &dlinfo);
+                               dladdr(si_rttip->basetype, &dlainfo);
                                if (symp != si_rttip->basetype)
                                {
                                        TETJ_REPORT_INFO("Base type %p
(expected) doesn't match %p %s (found)",
-                                                                              
                         symp, si_rttip->basetype, dlinfo.dli_sname);
+                                                                              
                         symp, si_rttip->basetype, dlainfo.dli_sname);
                                        test_failed = 1;
                                }
                                basetypes = si_rttip->basetypeinfo;
@@ -523,7 +554,7 @@ check_class_info(ElfFile *file, char *li
                                for (j=0; j<classp->numvmitypes; j++)
                                {
                                        btip = &(vmi_rttip->base_info[j]);
-                                       dladdr(btip->base_type, &dlinfo);
+                                       dladdr(btip->base_type, &dlainfo);
                                        symp = dlsym(dlhndl,
classp->btinfo[j].base_type);
                                        if (symp != btip->base_type) 
                                        {
@@ -567,10 +598,10 @@ check_class_info(ElfFile *file, char *li
                                 * Check the basename.
                                 */
                                symp = dlsym(dlhndl,classp->basename);
-                               dladdr(p_rttip->pointee, &dlinfo);
+                               dladdr(p_rttip->pointee, &dlainfo);
                                if (symp != p_rttip->pointee) {
                                        TETJ_REPORT_INFO("Base type %p
(expected) doesn't match %p %s (found)",
-                                                                              
                         symp, p_rttip->pointee, dlinfo.dli_sname);
+                                                                              
                         symp, p_rttip->pointee, dlainfo.dli_sname);
                                        test_failed = 1;
                                }
                                if (p_rttip->offset_flags&(~_pbase_all_mask)) {
@@ -614,12 +645,12 @@ check_class_info(ElfFile *file, char *li
                                for (j=0; j<classp->numbaseinfo; j++) 
                                {
                                        symp = dlsym(dlhndl,
classp->typeinfo->basetypeinfo[j]);
-                                       dladdr(basetypes[j]-8, &dlinfo);
+                                       dladdr(basetypes[j]-8, &dlainfo);
                                        if
((libchk_debug&LIBCHK_DEBUG_CLASSDETAILS) &&
-                                                       dlinfo.dli_saddr+8 !=
basetypes[j])
+                                                       dlainfo.dli_saddr+8 !=
basetypes[j])
                                        {
                                                printf("Uhoh4. Not an exact
match %p %p\n", 
-                                                                       
dlinfo.dli_saddr, basetypes[j]);
+                                                                       
dlainfo.dli_saddr, basetypes[j]);
                                        }
                                        if (symp != basetypes[j])
                                        {
@@ -685,7 +716,7 @@ check_class_info(ElfFile *file, char *li
                                tetj_result(journal, tetj_activity_count,
tetj_tp_count, TETJ_PASS);
                        } else {
                                TETJ_REPORT_INFO( "VTT Size mismatch for %s.
Expecting %d, found %d",
-                                                               classp->vttname,
(classp->numvtt*sizeof( void *)), fndvttsize);
+                                                               classp->vttname,
(int)(classp->numvtt*sizeof( void *)), fndvttsize);
                                tetj_result(journal, tetj_activity_count,
tetj_tp_count, TETJ_FAIL);
                        }
                        tetj_purpose_end(journal, tetj_activity_count,
tetj_tp_count++);
   
 
--    
Configure bugmail: http://bugs.linuxbase.org/userprefs.cgi?tab=email   
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.