[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.