(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
}
// 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)
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
+ );
+
}
}
}
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 */
.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. ---*/
+/*--- ---*/
/*------------------------------------------------------------*/
/*----------------------------------------------------*/
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
// 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 );
"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*/
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
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;
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;
/* 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)
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
#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
#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, \
#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, \
#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); \
/* --------------------------- 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... */