From 5e77fedd75c8408b3b95faff2c6101a0d68600f2 Mon Sep 17 00:00:00 2001 From: Julian Seward Date: Thu, 12 Jan 2006 21:15:35 +0000 Subject: [PATCH] Fix more ppc64-linux function wrapping and symbol-table bits and pieces. git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5523 --- coregrind/m_debuginfo/symtab.c | 61 ++++++++++--- coregrind/m_dispatch/dispatch-ppc32-linux.S | 1 - coregrind/m_dispatch/dispatch-ppc64-linux.S | 94 ++++++++++++++++++++- coregrind/m_main.c | 13 ++- coregrind/m_redir.c | 9 +- coregrind/m_scheduler/scheduler.c | 2 +- coregrind/m_stacktrace.c | 6 +- coregrind/m_trampoline.S | 74 ++++++++++------ coregrind/pub_core_trampoline.h | 1 + include/valgrind.h | 65 +++++++++----- 10 files changed, 250 insertions(+), 76 deletions(-) diff --git a/coregrind/m_debuginfo/symtab.c b/coregrind/m_debuginfo/symtab.c index eea9ff38d2..074767a3db 100644 --- a/coregrind/m_debuginfo/symtab.c +++ b/coregrind/m_debuginfo/symtab.c @@ -1106,20 +1106,38 @@ static Bool is_interesting_symbol( SegInfo* si, (ppc64-linux only) */ /*OUT*/Addr* sym_addr_really ) { + Bool plausible; + /* Set default real address for the symbol. */ *sym_addr_really = sym_addr; - /* Figure out if we're interested in the symbol. - Firstly, is it of the right flavour? */ - if ( ! ( (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL || - ELFXX_ST_BIND(sym->st_info) == STB_LOCAL || - ELFXX_ST_BIND(sym->st_info) == STB_WEAK) - && - (ELFXX_ST_TYPE(sym->st_info) == STT_FUNC || - (VG_(needs).data_syms - && ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT)) - ) - ) + /* Figure out if we're interested in the symbol. Firstly, is it of + the right flavour? */ + plausible + = (ELFXX_ST_BIND(sym->st_info) == STB_GLOBAL + || ELFXX_ST_BIND(sym->st_info) == STB_LOCAL + || ELFXX_ST_BIND(sym->st_info) == STB_WEAK + ) + && + (ELFXX_ST_TYPE(sym->st_info) == STT_FUNC + || (VG_(needs).data_syms + && ELFXX_ST_TYPE(sym->st_info) == STT_OBJECT) + ); + +# if defined(VGP_ppc64_linux) + /* Allow STT_NOTYPE in the very special case where we're running on + ppc64-linux and the symbol is one which the .opd-chasing hack + below will chase. */ + if (!plausible + && ELFXX_ST_TYPE(sym->st_info) == STT_NOTYPE + && sym->st_size > 0 + && si->opd_start_vma != 0 + && sym_addr >= si->opd_start_vma + && sym_addr < si->opd_start_vma + si->opd_size) + plausible = True; +# endif + + if (!plausible) return False; /* Secondly, if it's apparently in a GOT or PLT, it's really @@ -1287,7 +1305,8 @@ void read_symtab( SegInfo* si, Char* tab_name, Bool do_intercepts, } // Record interesting symbols in our symtab. - if ( is_interesting_symbol(si, sym, sym_name, sym_addr, opd_filea, &sym_addr_really) ) { + if ( is_interesting_symbol(si, sym, sym_name, sym_addr, + opd_filea, &sym_addr_really) ) { vg_assert(sym->st_name != 0); vg_assert(sym_name[0] != 0); # if defined(VGP_ppc64_linux) @@ -1299,12 +1318,30 @@ void read_symtab( SegInfo* si, Char* tab_name, Bool do_intercepts, vg_assert(sym_addr_really + sym->st_size <= si->opd_start_vma || sym_addr_really >= si->opd_start_vma + si->opd_size); # endif +# if defined(VGP_ppc64_linux) + /* Another ppc64-linux kludge, for the pre-"dotless" ABI + (prior to gcc 4.0.0). If the symbol to be added has a + leading dot and it wasn't derived via an indirect through + .opd, remove the dot before adding it. */ + if (sym_addr_really == sym_addr && sym_name[0] == '.') + sym_name++; +# endif + name = ML_(addStr) ( si, sym_name, -1 ); vg_assert(name != NULL); + risym.addr = sym_addr_really; risym.size = sym->st_size; risym.name = name; addSym ( si, &risym ); + + if (VG_(clo_trace_symtab)) + VG_(printf)(" record [%d]: " + " value %p, size %d, name %s\n", + i, (void*)risym.addr, (Int)risym.size, + (HChar*)risym.name + ); + } } } diff --git a/coregrind/m_dispatch/dispatch-ppc32-linux.S b/coregrind/m_dispatch/dispatch-ppc32-linux.S index 1a672896b2..0f3226bbc7 100644 --- a/coregrind/m_dispatch/dispatch-ppc32-linux.S +++ b/coregrind/m_dispatch/dispatch-ppc32-linux.S @@ -562,7 +562,6 @@ void VG_(run_a_noredir_translation) ( UWord* argblock ); 2: output: next guest PC 3: output: guest state pointer afterwards (== thread return code) */ -.align 16 .global VG_(run_a_noredir_translation) VG_(run_a_noredir_translation): /* save callee-save int regs, & lr */ diff --git a/coregrind/m_dispatch/dispatch-ppc64-linux.S b/coregrind/m_dispatch/dispatch-ppc64-linux.S index f9b11dee18..458a7e76a7 100644 --- a/coregrind/m_dispatch/dispatch-ppc64-linux.S +++ b/coregrind/m_dispatch/dispatch-ppc64-linux.S @@ -52,7 +52,10 @@ .tc vgPlain_machine_ppc64_has_VMX[TC],vgPlain_machine_ppc64_has_VMX /*------------------------------------------------------------*/ -/*--- The dispatch loop. ---*/ +/*--- ---*/ +/*--- The dispatch loop. VG_(run_innerloop) is used to ---*/ +/*--- run all translations except no-redir ones. ---*/ +/*--- ---*/ /*------------------------------------------------------------*/ /*----------------------------------------------------*/ @@ -570,6 +573,95 @@ VG_(run_innerloop__dispatch_profiled): blr +/*------------------------------------------------------------*/ +/*--- ---*/ +/*--- A special dispatcher, for running no-redir ---*/ +/*--- translations. Just runs the given translation once. ---*/ +/*--- ---*/ +/*------------------------------------------------------------*/ + +/* signature: +void VG_(run_a_noredir_translation) ( UWord* argblock ); +*/ + +/* Run a no-redir translation. argblock points to 4 UWords, 2 to carry args + and 2 to carry results: + 0: input: ptr to translation + 1: input: ptr to guest state + 2: output: next guest PC + 3: output: guest state pointer afterwards (== thread return code) +*/ +.section ".text" +.align 2 +.globl VG_(run_a_noredir_translation) +.section ".opd","aw" +.align 3 +VG_(run_a_noredir_translation): +.quad .VG_(run_a_noredir_translation),.TOC.@tocbase,0 +.previous +.type .VG_(run_a_noredir_translation),@function +.globl .VG_(run_a_noredir_translation) +.VG_(run_a_noredir_translation): + /* save callee-save int regs, & lr */ + stdu 1,-512(1) + std 14,256(1) + std 15,264(1) + std 16,272(1) + std 17,280(1) + std 18,288(1) + std 19,296(1) + std 20,304(1) + std 21,312(1) + std 22,320(1) + std 23,328(1) + std 24,336(1) + std 25,344(1) + std 26,352(1) + std 27,360(1) + std 28,368(1) + std 29,376(1) + std 30,384(1) + std 31,392(1) + mflr 31 + std 31,400(1) + std 2,408(1) /* also preserve R2, just in case .. */ + + stw 3,416(1) + lwz 31,8(3) + lwz 30,0(3) + mtlr 30 + blrl + + lwz 4,416(1) + stw 3, 16(4) + stw 31,24(4) + + ld 14,256(1) + ld 15,264(1) + ld 16,272(1) + ld 17,280(1) + ld 18,288(1) + ld 19,296(1) + ld 20,304(1) + ld 21,312(1) + ld 22,320(1) + ld 23,328(1) + ld 24,336(1) + ld 25,344(1) + ld 26,352(1) + ld 27,360(1) + ld 28,368(1) + ld 29,376(1) + ld 30,384(1) + ld 31,400(1) + mtlr 31 + ld 31,392(1) + ld 2,408(1) /* also preserve R2, just in case .. */ + + addi 1,1,512 + blr + + /* Let the linker know we don't need an executable stack */ .section .note.GNU-stack,"",@progbits diff --git a/coregrind/m_main.c b/coregrind/m_main.c index a66fdb9e1c..8cd1e944f8 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -2399,12 +2399,8 @@ Int main(Int argc, HChar **argv, HChar **envp) // p: aspacem //-------------------------------------------------------------- { Bool change_ownership_v_c_OK; - Addr co_start = VG_PGROUNDDN( - (Addr)VG_(fnptr_to_fnentry)( - &VG_(trampoline_stuff_start) ) ); - Addr co_endPlus = VG_PGROUNDUP( - (Addr)VG_(fnptr_to_fnentry)( - &VG_(trampoline_stuff_end) ) ); + Addr co_start = VG_PGROUNDDN( (Addr)&VG_(trampoline_stuff_start) ); + Addr co_endPlus = VG_PGROUNDUP( (Addr)&VG_(trampoline_stuff_end) ); VG_(debugLog)(1,"redir", "transfer ownership V -> C of 0x%llx .. 0x%llx\n", (ULong)co_start, (ULong)co_endPlus-1 ); @@ -2703,8 +2699,11 @@ static void final_tidyup(ThreadId tid) "Caught __NR_exit; running __libc_freeres()"); /* set thread context to point to libc_freeres_wrapper */ + /* ppc64-linux note: __libc_freeres_wrapper gives us the real + function entry point, not a fn descriptor, so can use it + directly. However, we need to set R2 (the toc pointer) + appropriately. */ VG_(set_IP)(tid, __libc_freeres_wrapper); - // XXX should we use a special stack? /* Block all blockable signals by copying the real block state into the thread's block state*/ diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c index df3fcae537..d4ccdb3471 100644 --- a/coregrind/m_redir.c +++ b/coregrind/m_redir.c @@ -767,11 +767,16 @@ void VG_(redir_initialise) ( void ) the start, otherwise ld.so makes a lot of noise. */ if (0==VG_(strcmp)("Memcheck", VG_(details).name)) { - add_redirect_sym_to_addr( - "soname:ld64.so.1", "strlen", + add_hardwired_spec( + "ld64.so.1", "strlen", (Addr)VG_(fnptr_to_fnentry)( &VG_(ppc64_linux_REDIR_FOR_strlen) ) ); + add_hardwired_spec( + "ld64.so.1", "index", + (Addr)VG_(fnptr_to_fnentry)( &VG_(ppc64_linux_REDIR_FOR_strchr) ) + ); + } # else diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c index 275f73b1e3..0b5246592f 100644 --- a/coregrind/m_scheduler/scheduler.c +++ b/coregrind/m_scheduler/scheduler.c @@ -522,7 +522,7 @@ static inline void do_pre_run_checks ( volatile ThreadState* tst ) static UInt run_thread_for_a_while ( ThreadId tid ) { volatile Int jumped; - volatile ThreadState* tst; + volatile ThreadState* tst = NULL; /* stop gcc complaining */ volatile UInt trc; volatile Int dispatch_ctr_SAVED; volatile Int done_this_time; diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c index a9ad219630..2e866d6946 100644 --- a/coregrind/m_stacktrace.c +++ b/coregrind/m_stacktrace.c @@ -389,8 +389,10 @@ void VG_(apply_StackTrace)( void(*action)(UInt n, Addr ip), mybuf[MYBUF_LEN-1] = 0; // paranoia if ( VG_STREQ("main", mybuf) # if defined(VGO_linux) - || VG_STREQ("__libc_start_main", mybuf) // glibc glibness - || VG_STREQ("generic_start_main", mybuf) // Yellow Dog doggedness + || VG_STREQ("__libc_start_main", mybuf) // glibc glibness + || VG_STREQ("generic_start_main", mybuf) // Yellow Dog doggedness + || VG_STREQ(".__libc_start_main", mybuf) // ppc64 dottyness + || VG_STREQ(".generic_start_main", mybuf) // ditto # endif ) main_done = True; diff --git a/coregrind/m_trampoline.S b/coregrind/m_trampoline.S index f2e0c8a32f..85428df2c7 100644 --- a/coregrind/m_trampoline.S +++ b/coregrind/m_trampoline.S @@ -299,25 +299,21 @@ VG_(trampoline_stuff_end): /* a leading page of unexecutable code */ UD2_PAGE -.align 2 .global VG_(trampoline_stuff_start) -.section ".opd","aw" -.align 3 VG_(trampoline_stuff_start): -.quad .VG_(trampoline_stuff_start),.TOC.@tocbase,0 -.previous -.type .VG_(trampoline_stuff_start),@function -.global .VG_(trampoline_stuff_start) -.VG_(trampoline_stuff_start): - -.align 2 -.globl VG_(ppc64_linux_REDIR_FOR_strlen) -.section ".opd","aw" -.align 3 + + /* this function is written using the "dotless" ABI convention */ + .align 2 + .globl VG_(ppc64_linux_REDIR_FOR_strlen) + .section ".opd","aw" + .align 3 VG_(ppc64_linux_REDIR_FOR_strlen): -.quad .L.VG_(ppc64_linux_REDIR_FOR_strlen),.TOC.@tocbase -.previous -.type VG_(ppc64_linux_REDIR_FOR_strlen), @function + .quad .L.VG_(ppc64_linux_REDIR_FOR_strlen),.TOC.@tocbase,0 + .previous + .size VG_(ppc64_linux_REDIR_FOR_strlen), \ + .L0end-.L.VG_(ppc64_linux_REDIR_FOR_strlen) + .type VG_(ppc64_linux_REDIR_FOR_strlen), @function + .L.VG_(ppc64_linux_REDIR_FOR_strlen): mr 9,3 lbz 0,0(3) @@ -325,27 +321,51 @@ VG_(ppc64_linux_REDIR_FOR_strlen): cmpwi 7,0,0 beqlr 7 li 3,0 -.L5: +.L01: addi 0,3,1 extsw 3,0 lbzx 0,9,3 cmpwi 7,0,0 - bne 7,.L5 + bne 7,.L01 blr .long 0 .byte 0,0,0,0,0,0,0,0 - .size VG_(ppc64_linux_REDIR_FOR_strlen),.-.L.VG_(ppc64_linux_REDIR_FOR_strlen) +.L0end: + + /* this function is written using the "dotless" ABI convention */ + .align 2 + .globl VG_(ppc64_linux_REDIR_FOR_strchr) + .section ".opd","aw" + .align 3 +VG_(ppc64_linux_REDIR_FOR_strchr): + .quad .L.VG_(ppc64_linux_REDIR_FOR_strchr),.TOC.@tocbase,0 + .previous + .size VG_(ppc64_linux_REDIR_FOR_strchr), \ + .L1end-.L.VG_(ppc64_linux_REDIR_FOR_strchr) + .type VG_(ppc64_linux_REDIR_FOR_strchr),@function + +.L.VG_(ppc64_linux_REDIR_FOR_strchr): + rldicl 4,4,0,56 + li 9,0 +.L11: + lbz 0,0(3) + cmpw 7,0,4 + bne+ 7,.L12 + mr 9,3 +.L12: + lbz 0,0(3) + addi 3,3,1 + cmpwi 7,0,0 + bne+ 7,.L11 + mr 3,9 + blr + .long 0 + .byte 0,0,0,0,0,0,0,0 +.L1end: -.align 2 + .global VG_(trampoline_stuff_end) -.section ".opd","aw" -.align 3 VG_(trampoline_stuff_end): -.quad .VG_(trampoline_stuff_end),.TOC.@tocbase,0 -.previous -.type .VG_(trampoline_stuff_end),@function -.global .VG_(trampoline_stuff_end) -.VG_(trampoline_stuff_end): /* and a trailing page of unexecutable code */ UD2_PAGE diff --git a/coregrind/pub_core_trampoline.h b/coregrind/pub_core_trampoline.h index 0113fa70cb..2034c41d86 100644 --- a/coregrind/pub_core_trampoline.h +++ b/coregrind/pub_core_trampoline.h @@ -68,6 +68,7 @@ extern void* VG_(ppc32_linux_REDIR_FOR_strchr)( void*, Int ); #if defined(VGP_ppc64_linux) extern UInt VG_(ppc64_linux_REDIR_FOR_strlen)( void* ); +extern void* VG_(ppc64_linux_REDIR_FOR_strchr)( void*, Int ); #endif #endif // __PUB_CORE_TRAMPOLINE_H diff --git a/include/valgrind.h b/include/valgrind.h index 6864d40923..0865fa95d1 100644 --- a/include/valgrind.h +++ b/include/valgrind.h @@ -163,7 +163,7 @@ #if defined(ARCH_x86) #define __SPECIAL_INSTRUCTION_PREAMBLE \ "roll $3, %%edi ; roll $13, %%edi\n\t" \ - "roll $29, %%edi ; roll $19, %%edi\n\t" \ + "roll $29, %%edi ; roll $19, %%edi\n\t" #define VALGRIND_DO_CLIENT_REQUEST( \ _zzq_rlval, _zzq_default, _zzq_request, \ @@ -208,7 +208,7 @@ #if defined(ARCH_amd64) #define __SPECIAL_INSTRUCTION_PREAMBLE \ "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \ - "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" \ + "rolq $61, %%rdi ; rolq $51, %%rdi\n\t" #define VALGRIND_DO_CLIENT_REQUEST( \ _zzq_rlval, _zzq_default, _zzq_request, \ @@ -253,15 +253,15 @@ #if defined(ARCH_ppc32) #define __SPECIAL_INSTRUCTION_PREAMBLE \ "rlwinm 0,0,3,0,0 ; rlwinm 0,0,13,0,0\n\t" \ - "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" \ + "rlwinm 0,0,29,0,0 ; rlwinm 0,0,19,0,0\n\t" #define VALGRIND_DO_CLIENT_REQUEST( \ _zzq_rlval, _zzq_default, _zzq_request, \ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4) \ \ - { volatile unsigned int _zzq_args[5]; \ - register unsigned int _zzq_result __asm__("r3"); \ - register volatile unsigned int *_zzq_ptr __asm__("r4"); \ + { unsigned int _zzq_args[5]; \ + register unsigned int _zzq_result __asm__("r3"); \ + register unsigned int* _zzq_ptr __asm__("r4"); \ _zzq_args[0] = (unsigned int)(_zzq_request); \ _zzq_args[1] = (unsigned int)(_zzq_arg1); \ _zzq_args[2] = (unsigned int)(_zzq_arg2); \ @@ -298,30 +298,49 @@ /* --------------------------- ppc64 --------------------------- */ #if defined(ARCH_ppc64) +#define __SPECIAL_INSTRUCTION_PREAMBLE \ + "rotldi 0,0,3 ; rotldi 0,0,13\n\t" \ + "rotldi 0,0,61 ; rotldi 0,0,51\n\t" + #define VALGRIND_DO_CLIENT_REQUEST( \ _zzq_rlval, _zzq_default, _zzq_request, \ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4) \ \ - { volatile unsigned long long int _zzq_args[5]; \ - register unsigned long long int _zzq_tmp __asm__("r3"); \ - register volatile unsigned long long int *_zzq_ptr __asm__("r4"); \ - _zzq_args[0] = (volatile unsigned long long int)(_zzq_request); \ - _zzq_args[1] = (volatile unsigned long long int)(_zzq_arg1); \ - _zzq_args[2] = (volatile unsigned long long int)(_zzq_arg2); \ - _zzq_args[3] = (volatile unsigned long long int)(_zzq_arg3); \ - _zzq_args[4] = (volatile unsigned long long int)(_zzq_arg4); \ + { unsigned long long int _zzq_args[5]; \ + register unsigned long long int _zzq_result __asm__("r3"); \ + register unsigned long long int* _zzq_ptr __asm__("r4"); \ + _zzq_args[0] = (unsigned long long int)(_zzq_request); \ + _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \ + _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \ + _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \ + _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \ _zzq_ptr = _zzq_args; \ - __asm__ volatile("tw 0,3,27\n\t" \ - "rotldi 0,0,61\n\t" \ - "rotldi 0,0,3\n\t" \ - "rotldi 0,0,13\n\t" \ - "rotldi 0,0,51\n\t" \ - "nop\n\t" \ - : "=r" (_zzq_tmp) \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = client_request ( %R4 ) */ \ + "or 1,1,1" \ + : "=r" (_zzq_result) \ : "0" (_zzq_default), "r" (_zzq_ptr) \ - : "memory"); \ - _zzq_rlval = (__typeof__(_zzq_rlval)) _zzq_tmp; \ + : "cc", "memory"); \ + _zzq_rlval = _zzq_result; \ + } + +#define VALGRIND_GET_NRADDR(_zzq_rlval) \ + { register unsigned long long int __addr __asm__("r3"); \ + __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \ + /* %R3 = guest_NRADDR */ \ + "or 2,2,2" \ + : "=r" (__addr) \ + : \ + : "cc", "memory" \ + ); \ + _zzq_rlval = (void*)__addr; \ } + +#define VALGRIND_BRANCH_AND_LINK_TO_NOREDIR_R11 \ + __SPECIAL_INSTRUCTION_PREAMBLE \ + /* branch-and-link-to-noredir *%R11 */ \ + "or 3,3,3\n\t" + #endif /* ARCH_ppc64 */ /* Insert assembly code for other architectures here... */ -- 2.47.2