Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
collector: Fix dump_buffers on sparc
The problem is two-fold: - On Sparc, heap addresses have their MSB set. For example: [~]# cat /proc/self/maps 00100000-0010a000 r-xp 00000000 fd:00 7340064 /bin/cat 0020a000-0020c000 rwxp 0000a000 fd:00 7340064 /bin/cat 0020c000-0022e000 rwxp 00000000 00:00 0 [heap] 7feffe4e000-7feffe70000 rw-p 00000000 00:00 0 [stack] fffffc0100000000-fffffc0100002000 rw-p 00000000 00:00 0 fffffc0100004000-fffffc0100006000 rw-p 00000000 00:00 0 fffffc010013c000-fffffc010013e000 r--p 00000000 00:00 0 [vvar] fffffc010013e000-fffffc0100140000 r-xp 00000000 00:00 0 [vdso] fffffc0100140000-fffffc01002c4000 r-xp 00000000 fd:00 5505039 /lib64/libc-2.12.so fffffc01002c4000-fffffc01003c4000 ---p 00184000 fd:00 5505039 /lib64/libc-2.12.so fffffc01003c4000-fffffc01003c8000 r--p 00184000 fd:00 5505039 /lib64/libc-2.12.so fffffc01003c8000-fffffc01003ce000 rwxp 00188000 fd:00 5505039 /lib64/libc-2.12.so fffffc01003ce000-fffffc01003d2000 rwxp 00000000 00:00 0 fffffc0102fac000-fffffc0102fd0000 r-xp 00000000 fd:00 5505236 /lib64/ld-2.12.so fffffc01030d0000-fffffc01030d2000 r--p 00024000 fd:00 5505236 /lib64/ld-2.12.so fffffc01030d2000-fffffc01030d4000 rwxp 00026000 fd:00 5505236 /lib64/ld-2.12.so fffffc01030d4000-fffffc0108f6c000 r--p 00000000 fd:00 13126552 /usr/lib/locale/locale-archive - Linux's pread() implementation has a limitation: it treats the offset argument as a signed offset, hence it can't access the top half of the memory space: SYSCALL_DEFINE(pread64)(unsigned int fd, char __user *buf, size_t count, loff_t pos) { struct file *file; ssize_t ret = -EBADF; int fput_needed; if (pos < 0) return -EINVAL; file = fget_light(fd, &fput_needed); if (file) { ret = -ESPIPE; if (file->f_mode & FMODE_PREAD) ret = vfs_read(file, buf, count, &pos); fput_light(file, fput_needed); } return ret; } So the problem with bootchart-collector using pread() to read from /dev/{pid}/mem becomes obvious: the first call to pread() successfully reads from the stack, but subsequent calls fail reading from the heap and return value EINVAL. The fix is to replace the call to pread() by two system calls: lseek() which can handle unsigned offsets and read(). There is no real performance degradation and it is portable.
- Loading branch information