/* Copyright (C) 2006 Dave Airlie Copyright (C) 2007 Wladimir J. van der Laan Copyright (C) 2009, 2011 Marcin Slusarz This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. The GNU General Public License is contained in the file COPYING. */ #include "mmt_fgl_ioctl.h" #include "mmt_trace.h" #include "pub_tool_vki.h" #include "pub_tool_libcprint.h" #include "pub_tool_libcfile.h" #include "pub_tool_libcbase.h" #include "pub_tool_libcproc.h" #include "pub_tool_libcassert.h" #include #include #include #include #include static fd_set fglrx_fds; static int fglrx_fd; int mmt_trace_fglrx_ioctls = True; int mmt_trace_marks = False; static int trace_mark_fd; static int trace_mark_cnt = 0; static inline unsigned long long mmt_2x4to8(UInt h, UInt l) { return (((unsigned long long)h) << 32) | l; } void mmt_fgl_ioctl_fini() { if (mmt_trace_marks) { VG_(close)(trace_mark_fd); } } void mmt_fgl_ioctl_post_clo_init(void) { if (mmt_trace_marks) { SysRes ff; ff = VG_(open)("/sys/kernel/debug/tracing/trace_marker", VKI_O_WRONLY, 0777); if (ff._isError) { VG_(message) (Vg_UserMsg, "Cannot open marker file!\n"); mmt_trace_marks = 0; } trace_mark_fd = ff._val; } } static struct mmt_mmap_data *get_fgl_mapping(Off64T offset) { struct mmt_mmap_data *region; region = mmt_find_region_by_fdset_offset(&fglrx_fds, offset); if (region) return region; return mmt_add_region(0, 0, 0, offset, 0, 0, 0); } static Addr release_fgl_mapping(Off64T offset) { struct mmt_mmap_data *region; Addr start; region = mmt_find_region_by_fdset_offset(&fglrx_fds, offset); if (!region) return 0; start = region->start; mmt_free_region(region); return start; } static Addr release_fgl_mapping2(UWord data1, UWord data2) { struct mmt_mmap_data *region; Addr start; region = mmt_find_region_by_fdset_data(&fglrx_fds, data1, data2); if (!region) return 0; start = region->start; mmt_free_region(region); return start; } static void dumpmem(char *s, Addr addr, UInt size) { char line[4096]; int idx = 0; line[0] = 0; UInt i; if (!addr || (addr & 0xffff0000) == 0xbeef0000) return; size = size / 4; for (i = 0; i < size; ++i) { if (idx + 11 >= 4095) break; VG_(sprintf) (line + idx, "0x%08x ", ((UInt *) addr)[i]); idx += 11; } VG_(message) (Vg_DebugMsg, "%s%s\n", s, line); } void mmt_fgl_ioctl_post_open(UWord *args, SysRes res) { const char *path = (const char *)args[0]; if (mmt_trace_fglrx_ioctls) { if (VG_(strcmp)(path, "/dev/ati/card0") == 0) { FD_SET(res._val, &fglrx_fds); fglrx_fd = res._val; } } } void mmt_fgl_ioctl_post_close(UWord *args) { int fd = (int)args[0]; if (mmt_trace_fglrx_ioctls) { FD_CLR(fd, &fglrx_fds); } } int mmt_fgl_ioctl_post_mmap(UWord *args, SysRes res, int offset_unit) { Addr start = args[0]; unsigned long len = args[1]; // unsigned long prot = args[2]; // unsigned long flags = args[3]; unsigned long fd = args[4]; unsigned long offset = args[5]; struct mmt_mmap_data *region; struct mmt_mmap_data tmp; if (!mmt_trace_fglrx_ioctls) return 0; if (!FD_ISSET(fd, &fglrx_fds)) return 0; offset *= offset_unit; #if 0 region = mmt_find_region_by_fd_offset(fd, offset); if (!region) return 0; tmp = *region; mmt_free_region(region); #endif /* region mapped through mmap are not interesting */ #if 1 start = res._val; region = mmt_add_region(fd, start, start + len, offset, 0, 0, 0); #if 0 VG_(message) (Vg_DebugMsg, "fgl got new mmap for 0x%08lx:0x%08lx at %p, len: 0x%08lx, offset: 0x%llx, serial: %d\n", region->data1, region->data2, (void *)region->start, len, region->offset, region->id); #endif #endif return 1; } #define IOC_NR(x) (((x) >> 0) & ((1 << 8) - 1)) #define IOC_TYPE(x) (((x) >> 8) & ((1 << 8) - 1)) #define IOC_SIZE(x) (((x) >> 16) & ((1 << 14) - 1)) #define IOC_DIR(x) (((x) >> 30) & ((1 << 2) - 1)) struct mmap_info { uint64_t soffset; uint64_t eoffset; uint64_t flags; }; #define MAX_MMAP_INFO 128 static struct mmap_info mmap_infos[MAX_MMAP_INFO]; static unsigned mmap_ninfos = 0; #define MAX_GPU_OFFSET 256 static uint64_t _know_gpu_offset[MAX_GPU_OFFSET]; static unsigned _nknow_gpu_offset = 0; #define MAX_CTX_OFFSET 256 struct fgl_ctx_offset { uint64_t offset; unsigned ioctl; }; static struct fgl_ctx_offset _ctx_offset[MAX_CTX_OFFSET]; static unsigned _nctx_offset = 0; static void mmt_fgl_add_gpu_offset(uint64_t offset) { unsigned i; for (i = 0; i < _nknow_gpu_offset; i++) { if (_know_gpu_offset[i] == offset) { return; } } if (_nknow_gpu_offset < MAX_GPU_OFFSET) { _know_gpu_offset[_nknow_gpu_offset++] = offset; } } static void mmt_fgl_dump_gpu_offset(void) { unsigned i, j; uint64_t *ptr; VG_(message)(Vg_DebugMsg, "[GDUMP\n"); for (i = 0; i < _nknow_gpu_offset; i++) { ptr = _know_gpu_offset[i]; for (j = 0; j < 8; j++) { VG_(message)(Vg_DebugMsg, "gdump [0x%016llx] 0x%08x\n", &ptr[j], ptr[j]); } VG_(message)(Vg_DebugMsg, "--\n"); } VG_(message)(Vg_DebugMsg, "GDUMP]\n"); } static void mmt_read_line(Int fd, Char *line) { unsigned i = 0; do { if (VG_(read)(fd, &line[i++], 1) == -1) { line[i - 1] = 0; return; } } while (line[i - 1] != '\n'); line[i] = 0; } static void mmt_fgl_update_mmaps(void) { Char name[64], line[256]; Int fd, pid, added = 0; pid = VG_(getpid)(); VG_(sprintf)(name, "/proc/%d/maps", pid); fd = VG_(fd_open)(name, O_RDONLY, 0); if (fd == -1) { return; } mmt_fgl_clear_region(fglrx_fd); mmap_ninfos = 0; // VG_(message)(Vg_DebugMsg, "MMAPS: *******************************************\n"); do { unsigned long saddr; unsigned long eaddr; unsigned long offset; Char *next; line[0] = 0; mmt_read_line(fd, line); if (!line[0]) { break; } /* parse mmap line */ saddr = VG_(strtoull16)(line, &next); next += 1; eaddr = VG_(strtoull16)(next, &next); next += 6; offset = VG_(strtoull16)(next, &next); next += 10; if (*next == 0) { // VG_(message)(Vg_DebugMsg, "anon: %s", line); if (mmap_ninfos < MAX_MMAP_INFO) { mmap_infos[mmap_ninfos].soffset = saddr; mmap_infos[mmap_ninfos].eoffset = eaddr; mmap_infos[mmap_ninfos].flags = 0; mmap_ninfos++; } continue; } // VG_(message)(Vg_DebugMsg, "%s", line); if (line[0] && VG_(strstr)(line, "/dev/ati/card0")) { struct mmt_mmap_data *region, *tmp; tmp = mmt_find_region_by_fd_addr(saddr); if (tmp == NULL) { #if 0 VG_(message)(Vg_DebugMsg, "mmaps: [0x%016llx 0x%016llx] [0x%08x 0x%08x]\n", saddr, eaddr, offset, offset + (eaddr - saddr)); #endif region = mmt_add_region(fglrx_fd, saddr, eaddr, offset, 0, 1, 0); added++; if (mmap_ninfos < MAX_MMAP_INFO) { mmap_infos[mmap_ninfos].soffset = saddr; mmap_infos[mmap_ninfos].eoffset = eaddr; mmap_infos[mmap_ninfos].flags = 1; mmap_ninfos++; } } } } while(line[0]); VG_(close)(fd); if (added) { // mmt_fgl_scan_region(fglrx_fd); } } static const struct mmap_info *mmt_mmap_info(uint64_t addr) { unsigned i; for (i = 0; i < mmap_ninfos; i++) { if (addr >= mmap_infos[i].soffset && addr < mmap_infos[i].eoffset) { return &mmap_infos[i]; } } return NULL; } static void mmt_print_line_grec(void *data, unsigned nqw, char *prefix, int maxrec, int rec, unsigned ioctl) { uint32_t *ptr = data; unsigned i; char space[64]; space[0] = 0; for (i = 0; i < rec; i++) { space[i] = ' '; space[i+1] = 0; } for (i = 0; i < nqw * 2; i++) { VG_(message)(Vg_DebugMsg, "%s ioctl_%02x %s [0x%016llx] 0x%08x gdata\n", prefix, ioctl, space, &ptr[i], ptr[i]); } } void fgl_add_ctx_offset(uint64_t offset, unsigned ioctl) { unsigned i; for (i = 0; i < _nctx_offset; i++) { if (_ctx_offset[i].offset == offset) { return; } } _ctx_offset[_nctx_offset].offset = offset; _ctx_offset[_nctx_offset].ioctl = ioctl; _nctx_offset++; } static void mmt_fgl_dump_ctx_offset(void) { unsigned i, j; uint64_t *ptr; VG_(message)(Vg_DebugMsg, "[GCTX\n"); for (i = 0; i < _nctx_offset; i++) { ptr = _ctx_offset[i].offset; for (j = 0; j < 8; j++) { VG_(message)(Vg_DebugMsg, "gctx ioctl_%02x [0x%016llx] 0x%08x\n", _ctx_offset[i].ioctl, &ptr[j], ptr[j]); } VG_(message)(Vg_DebugMsg, "--\n"); } VG_(message)(Vg_DebugMsg, "GCTX]\n"); } void fgl_scan_ctx_offset(void *data, unsigned nqw, unsigned ioctl) { const struct mmap_info *info; uint64_t *ptr = data; unsigned i; for (i = 0; i < nqw; i++) { info = mmt_mmap_info(ptr[i]); if (info && !info->flags) { fgl_add_ctx_offset(ptr[i], ioctl); } } } static void mmt_print_line_rec(void *data, unsigned nqw, char *prefix, int maxrec, int rec, unsigned ioctl) { const struct mmap_info *info; uint64_t *ptr = data; unsigned i; char space[64]; space[0] = 0; for (i = 0; i < rec; i++) { space[i] = ' '; space[i+1] = 0; } for (i = 0; i < nqw; i++) { info = mmt_mmap_info(ptr[i]); if (info) { switch (info->flags) { case 1: mmt_fgl_add_gpu_offset(ptr[i]); VG_(message)(Vg_DebugMsg, "%s ioctl_%02x %s [0x%016llx] 0x%016llx gptr\n", prefix, ioctl, space, &ptr[i], ptr[i]); if (rec < maxrec) mmt_print_line_grec(ptr[i], 2, prefix, maxrec, ++rec, ioctl); break; default: VG_(message)(Vg_DebugMsg, "%s ioctl_%02x %s [0x%016llx] 0x%016llx aptr\n", prefix, ioctl, space, &ptr[i], ptr[i]); // if (rec < maxrec) mmt_print_line_rec(ptr[i], 8, prefix, maxrec, ++rec, ioctl); break; } } else { VG_(message)(Vg_DebugMsg, "%s ioctl_%02x %s [0x%016llx] 0x%016llx\n", prefix, ioctl, space, &ptr[i], ptr[i]); } } } static void mmt_print_line(void *data, unsigned nqw, char *prefix, int maxrec, unsigned ioctl) { const struct mmap_info *info; uint64_t *ptr = data; unsigned i; for (i = 0; i < nqw; i++) { info = mmt_mmap_info(ptr[i]); if (info) { switch (info->flags) { case 1: mmt_fgl_add_gpu_offset(ptr[i]); VG_(message)(Vg_DebugMsg, "%s ioctl_%02x [0x%016llx] 0x%016llx gptr\n", prefix, ioctl, &ptr[i], ptr[i]); if (maxrec) mmt_print_line_grec(ptr[i], 5, prefix, maxrec, 0, ioctl); break; default: VG_(message)(Vg_DebugMsg, "%s ioctl_%02x [0x%016llx] 0x%016llx aptr\n", prefix, ioctl, &ptr[i], ptr[i]); if (maxrec) mmt_print_line_rec(ptr[i], 5, prefix, maxrec, 0, ioctl); break; } } else { VG_(message)(Vg_DebugMsg, "%s ioctl_%02x [0x%016llx] 0x%016llx\n", prefix, ioctl, &ptr[i], ptr[i]); } } } struct fglrx_ioctl_a6 { uint64_t header0; uint64_t args_size; uint64_t *args; uint64_t rets_size; uint64_t *rets; }; void mmt_fgl_ioctl_a6(void *data, unsigned size, char *prefix, unsigned post) { static uint64_t next_gpu_addr = 0, ib_count = 0; struct fglrx_ioctl_a6 *p_a6 = data; const struct mmap_info *info; unsigned i; #if 0 /* header0 | always 0x30 * args_size | args size in byte (=0x50 only in clear operation) * args | layout: * [...] * ((u64*)args)[1] always 0x00000002dead0000 * [...] * ((u64*)args)[4] if args_size = 0x50 then last fglrx_ioctl_a6.rets[2] aka id1 << 32 * if args_size = 0x40 then last fglrx_ioctl_a6.rets[2] aka id1 * rets_size | rets size in byte * rets | layout: * ((u64*)rets)[0] unknown * ((u64*)rets)[1] unknown * ((u64*)rets)[2] id1 some kind of id always increasing * ((u64*)rets)[3] id2 some kind of id always increasing same as [2] * ((u64*)rets)[4] user space ptr to ib buffer (mmaped GPU memory) */ struct fglrx_ioctl_a6 { uint64_t header0; uint64_t args_size; uint64_t *args; uint64_t rets_size; uint64_t *rets; }; #endif #if 0 mmt_print_line(data, 5 + 7, prefix, 0, 0xa6); mmt_print_line(p_a6->args, p_a6->args_size / 8, " args", 0, 0xa6); VG_(message)(Vg_DebugMsg, "_\n"); mmt_print_line(p_a6->rets, p_a6->rets_size / 8, " rets", 1, 0xa6); #else if (post && p_a6->args_size == 0x78 && p_a6->rets_size == 0x68) { next_gpu_addr = p_a6->rets[4]; } if (!post && p_a6->args_size == 0x78 && p_a6->rets_size == 0x68) { info = mmt_mmap_info(next_gpu_addr); if (info && p_a6->args[2] == 0x1000180200000068) { unsigned ib_size = (p_a6->args[4] >> 32ULL) & 0x0000ffffULL; uint32_t *ptr = next_gpu_addr; VG_(message)(Vg_DebugMsg, "ib size 0x%08x from 0x%016llx\n", ib_size, p_a6->args[4]); for (i = 0; i < ib_size/4; i++) { VG_(message)(Vg_DebugMsg, "[%4d] [%4d] 0x%08x\n", ib_count, i, ptr[i]); } ib_count++; } } #endif } void mmt_fgl_ioctl_2a(void *data, unsigned size) { uint32_t *ptr1 = ((uint64_t*)data)[3]; uint32_t *ptr2 = ((uint64_t*)ptr1)[0]; uint32_t *ptr3 = ((uint64_t*)ptr1)[1]; uint32_t *ptr4 = ((uint64_t*)ptr3)[0]; uint32_t *ptr5 = ((uint64_t*)ptr3)[1]; unsigned i; VG_(message)(Vg_DebugMsg, "IOCTL_2A [0x%016llx]\n", ptr1); for (i = 0; i < 8; i++) { VG_(message)(Vg_DebugMsg, "[0x%016llx] 0x%08x\n", &ptr1[i], ptr1[i]); } VG_(message)(Vg_DebugMsg, "IOCTL_2A ptr2 [0x%016llx]\n", ptr2); for (i = 0; i < 8; i++) { // VG_(message)(Vg_DebugMsg, "[0x%016llx] 0x%08x\n", &ptr2[i], ptr2[i]); } VG_(message)(Vg_DebugMsg, "IOCTL_2A ptr3 [0x%016llx]\n", ptr3); for (i = 0; i < 8; i++) { VG_(message)(Vg_DebugMsg, "[0x%016llx] 0x%08x\n", &ptr3[i], ptr3[i]); } VG_(message)(Vg_DebugMsg, "IOCTL_2A ptr4 [0x%016llx]\n", ptr4); for (i = 0; i < 8; i++) { // VG_(message)(Vg_DebugMsg, "[0x%016llx] 0x%08x\n", &ptr4[i], ptr4[i]); } VG_(message)(Vg_DebugMsg, "IOCTL_2A ptr5 [0x%016llx]\n", ptr5); for (i = 0; i < 8; i++) { VG_(message)(Vg_DebugMsg, "[0x%016llx] 0x%08x\n", &ptr5[i], ptr5[i]); } } void mmt_fgl_ioctl_pre(UWord *args) { int fd = args[0]; UInt id = args[1]; UInt *data = (UInt *) args[2]; unsigned io_nr, io_type, io_size, io_dir; unsigned i, j; if (!FD_ISSET(fd, &fglrx_fds)) return; mmt_fgl_update_mmaps(); io_nr = IOC_NR(id); io_type = IOC_TYPE(id); io_size = IOC_SIZE(id); io_dir = IOC_DIR(id); if (mmt_trace_marks) { char buf[50]; VG_(snprintf)(buf, 50, "VG-%d-%d-PRE\n", VG_(getpid)(), trace_mark_cnt); VG_(write)(trace_mark_fd, buf, VG_(strlen)(buf)); VG_(message)(Vg_DebugMsg, "MARK: %s", buf); } #if 1 // VG_(get_and_pp_StackTrace)(VG_(get_running_tid)(), 12); // VG_(message)(Vg_DebugMsg, "pre_ioctl, wrong id:0x%08x (0x%02x, 0x%02x, %4d, 0x%x) [0x%x]\n", id, io_nr, io_type, io_size, io_dir, (unsigned long long) data); #if 1 switch (io_nr) { #if 0 case 0x2a: mmt_fgl_ioctl_2a(data, io_size); break; #endif case 0xa6: mmt_fgl_ioctl_a6(data, io_size, "pre ", 0); break; default: // fgl_scan_ctx_offset(data, io_size/8, io_nr); // mmt_print_line(data, (io_size/8), "pre ", 2, io_nr); break; } #endif #endif // mmt_fgl_dump_gpu_offset(); // mmt_fgl_dump_ctx_offset(); } void mmt_fgl_ioctl_post(UWord *args) { int fd = args[0]; UInt id = args[1]; UInt *data = (UInt *) args[2]; unsigned io_nr, io_type, io_size, io_dir; unsigned i, j; if (!FD_ISSET(fd, &fglrx_fds)) return; if (mmt_trace_marks) { char buf[50]; VG_(snprintf)(buf, 50, "VG-%d-%d-POST\n", VG_(getpid)(), trace_mark_cnt++); VG_(write)(trace_mark_fd, buf, VG_(strlen)(buf)); VG_(message)(Vg_DebugMsg, "MARK: %s", buf); } io_nr = IOC_NR(id); io_type = IOC_TYPE(id); io_size = IOC_SIZE(id); io_dir = IOC_DIR(id); #if 1 // VG_(message)(Vg_DebugMsg, "post_ioctl, wrong id:0x%08x (0x%02x, 0x%02x, %4d, 0x%x) [0x%x]\n", id, io_nr, io_type, io_size, io_dir, (unsigned long long) data); #if 1 switch (io_nr) { #if 0 case 0x2a: mmt_fgl_ioctl_2a(data, io_size); break; #endif case 0xa6: mmt_fgl_ioctl_a6(data, io_size, "post", 1); break; default: // mmt_print_line(data, io_size/8, "post", 2, io_nr); break; } #endif #endif } void mmt_fgl_ioctl_pre_clo_init(void) { FD_ZERO(&fglrx_fds); } /* STORE ********************************************************************/ /* STORE ********************************************************************/ /* STORE ********************************************************************/ /* STORE ********************************************************************/ /* STORE ********************************************************************/ /* STORE ********************************************************************/ VG_REGPARM(2) void mmt_trace_store_1(Addr addr, UWord value) { const struct mmap_info *info; info = mmt_mmap_info(addr); if (!info) { return; } VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%02x\n", info->flags ? 'g' : 'a', info->soffset, info->eoffset, addr, value); } VG_REGPARM(2) void mmt_trace_store_1_ia(Addr addr, UWord value, Addr inst_addr) { const struct mmap_info *info; info = mmt_mmap_info(addr); if (!info) { return; } VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%02x\n", info->flags ? 'g' : 'a', info->soffset, info->eoffset, addr, value); } VG_REGPARM(2) void mmt_trace_store_2(Addr addr, UWord value) { const struct mmap_info *info; info = mmt_mmap_info(addr); if (!info) { return; } VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%04lx\n", info->flags ? 'g' : 'a', info->soffset, info->eoffset, addr, value); } VG_REGPARM(2) void mmt_trace_store_2_ia(Addr addr, UWord value, Addr inst_addr) { const struct mmap_info *info; info = mmt_mmap_info(addr); if (!info) { return; } VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%04lx\n", info->flags ? 'g' : 'a', info->soffset, info->eoffset, addr, value); } VG_REGPARM(2) void mmt_trace_store_4(Addr addr, UWord value) { const struct mmap_info *info; info = mmt_mmap_info(addr); if (!info) { return; } VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%08lx\n", info->flags ? 'g' : 'a', info->soffset, info->eoffset, addr, value); } VG_REGPARM(2) void mmt_trace_store_4_ia(Addr addr, UWord value, Addr inst_addr) { const struct mmap_info *info; info = mmt_mmap_info(addr); if (!info) { return; } VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%08lx\n", info->flags ? 'g' : 'a', info->soffset, info->eoffset, addr, value); } #ifdef MMT_64BIT VG_REGPARM(2) void mmt_trace_store_8(Addr addr, UWord value) { const struct mmap_info *info; info = mmt_mmap_info(addr); if (!info) { return; } VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%016llx\n", info->flags ? 'g' : 'a', info->soffset, info->eoffset, addr, value); } VG_REGPARM(2) void mmt_trace_store_8_ia(Addr addr, UWord value, Addr inst_addr) { const struct mmap_info *info; info = mmt_mmap_info(addr); if (!info) { return; } VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%016llx\n", info->flags ? 'g' : 'a', info->soffset, info->eoffset, addr, value); } #endif VG_REGPARM(2) void mmt_trace_store_4_4(Addr addr, UWord value1, UWord value2) { const struct mmap_info *info; info = mmt_mmap_info(addr); if (!info) { return; } VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%08lx 0x%08lx\n", info->flags ? 'g' : 'a', info->soffset, info->eoffset, addr, value1, value2); } VG_REGPARM(2) void mmt_trace_store_4_4_ia(Addr addr, UWord value1, UWord value2, Addr inst_addr) { const struct mmap_info *info; info = mmt_mmap_info(addr); if (!info) { return; } VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%08lx 0x%08lx\n", info->flags ? 'g' : 'a', info->soffset, info->eoffset, addr, value1, value2); } #ifdef MMT_64BIT VG_REGPARM(2) void mmt_trace_store_8_8(Addr addr, UWord value1, UWord value2) { const struct mmap_info *info; info = mmt_mmap_info(addr); if (!info) { return; } VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%016llx 0x%016llx\n", info->flags ? 'g' : 'a', info->soffset, info->eoffset, addr, value1, value2); } VG_REGPARM(2) void mmt_trace_store_8_8_ia(Addr addr, UWord value1, UWord value2, Addr inst_addr) { const struct mmap_info *info; info = mmt_mmap_info(addr); if (!info) { return; } VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%016llx 0x%016llx\n", info->flags ? 'g' : 'a', info->soffset, info->eoffset, addr, value1, value2); } #endif #ifndef MMT_64BIT VG_REGPARM(2) void mmt_trace_store_4_4_4_4(Addr addr, UWord value1, UWord value2, UWord value3, UWord value4) { const struct mmap_info *info; info = mmt_mmap_info(addr); if (!info) { return; } VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%08llx 0x%08llx 0x%08llx 0x%08llx\n", info->flags ? 'g' : 'a', info->soffset, info->eoffset, addr, value1, value2, value3, value4); } VG_REGPARM(2) void mmt_trace_store_4_4_4_4_ia(Addr addr, UWord value1, UWord value2, UWord value3, UWord value4, Addr inst_addr) { const struct mmap_info *info; info = mmt_mmap_info(addr); if (!info) { return; } VG_(message)(Vg_DebugMsg, "%cdata [0x%016llx - 0x%016llx] [0x%016llx] 0x%08llx 0x%08llx 0x%08llx 0x%08llx\n", info->flags ? 'g' : 'a', info->soffset, info->eoffset, addr, value1, value2, value3, value4); } #endif