Toby Riddell
2011-Sep-05 21:25 UTC
[dtrace-discuss] Examining values returned from lstat64()
Hi all, I''m trying to examine the values returned to a process from a lstat64() call. I''m using the common pattern: in the syscall::foo:entry probe save the address the process supplies for returning results to it, and in the syscall::foo:return probe examine the results. I''ve looked at several threads on this mailing list and seen this technique used but for the life of me I cannot get it to work for me. I''ve reduced it to a simple test case using the following C program: #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> int main() { struct stat64 buffer; int status; status = lstat64("/home/triddel/stat.c", &buffer); } And this dtrace script: #!/usr/sbin/dtrace -s #pragma D option quiet syscall::lstat64:entry / pid == $target / { self->path = arg0; /* char * */ self->stat = arg1; /* struct stat64 * */ } syscall::lstat64:return / self->stat && pid == $target / { this->path = copyinstr(self->path); printf("Path: %s\n", this->path); this->stat = (struct stat64 *) copyin( (uintptr_t) self->stat, sizeof(struct stat64) ); printf("File mode: %d\n", this->stat->st_mode); printf("File size: %d\n", this->stat->st_size); printf("File inode: %d\n", this->stat->st_ino); printf("File uid: %d\n", this->stat->st_uid); self->stat = 0; } The results are: $ sudo dtrace -s process_filesize.d -c ./stat Path: /home/triddel/stat.c File mode: 63676 File size: 0 File inode: 0 File uid: 33188 File fstype: File size is definitely not zero, and nor is the inode. Clearly the technique is working for the file path but it seems I''m doing something incorrect when accessing members of the stat64 struct. Can someone point me to what I''m doing wrong? Thanks. Toby
Casper.Dik at oracle.com
2011-Sep-06 07:48 UTC
[dtrace-discuss] Examining values returned from lstat64()
>The results are: > >$ sudo dtrace -s process_filesize.d -c ./stat >Path: /home/triddel/stat.c >File mode: 63676 >File size: 0 >File inode: 0 >File uid: 33188 >File fstype: > >File size is definitely not zero, and nor is the inode. Clearly the >technique is working for the file path but it seems I''m doing >something incorrect when accessing members of the stat64 struct. > >Can someone point me to what I''m doing wrong?There are three different stat structures in the kernel: - stat32 - stat64 (native) - stat64_32 (for 32 bit large file environment) *stat64 returns the latter and the differences are:> ::print -a "struct stat64"0 { 0 st_dev 8 st_ino 10 st_mode 14 st_nlink 18 st_uid 1c st_gid 20 st_rdev 28 st_size 30 st_atim { 30 tv_sec 38 tv_nsec } 40 st_mtim { 40 tv_sec 48 tv_nsec } 50 st_ctim { 50 tv_sec 58 tv_nsec } 60 st_blksize 68 st_blocks 70 st_fstype }> ::print -a "struct stat64_32"0 { 0 st_dev 4 st_pad1 10 st_ino 18 st_mode 1c st_nlink 20 st_uid 24 st_gid 28 st_rdev 2c st_pad2 38 st_size 40 st_atim { 40 tv_sec 44 tv_nsec } 48 st_mtim { 48 tv_sec 4c tv_nsec } 50 st_ctim { 50 tv_sec 54 tv_nsec } 58 st_blksize 60 st_blocks 68 st_fstype 78 st_pad4 }
Toby Riddell
2011-Sep-06 08:31 UTC
[dtrace-discuss] Examining values returned from lstat64()
Thanks a lot, Casper - this morning I was using tracemem and gradually approaching the conclusion that there was a 32 vs. 64-bit issue but this has helped accelerate my understanding. However, when I modify my dtrace script to use stat64_32 I get ''invalid alignment'' when I try to print the st_size member of the struct: syscall::lstat64:return / self->stat && pid == $target / { this->path = copyinstr(self->path); printf("Path: %s\n", this->path); this->stat = (struct stat64_32 *) copyin( (uintptr_t) self->stat, sizeof(struct stat64_32) ); printf("File mode: %d\n", this->stat->st_mode); printf("File size: %d\n", this->stat->st_size); printf("File inode: %d\n", this->stat->st_ino); printf("File uid: %d\n", this->stat->st_uid); tracemem( copyin(self->stat, sizeof(struct stat64_32)), sizeof(struct stat64_32) ); self->stat = 0; } $ sudo dtrace -C -s ./process_filesize.d -c ./stat cc1: warning: /dev/fd/7 is shorter than expected <command-line>: warning: "__STDC__" redefined dtrace: error on enabled probe ID 2 (ID 49454: syscall::lstat64:return): invalid alignment (0xfffffeefdc9702ec) in action #5 at DIF offset 12 Commenting out the printf()s so that I get the output from tracemem: 0 1 2 3 4 5 6 7 8 9 a b c d e f 0123456789abcdef 0: 00 00 54 01 00 00 00 00 00 00 00 00 00 00 00 00 ..T............. 10: bc f8 00 00 00 00 00 00 a4 81 00 00 01 00 00 00 ................ 20: 21 27 00 00 10 27 00 00 00 00 00 00 00 00 00 00 !''...''.......... 30: 00 00 00 00 a8 00 00 00 00 00 00 00 7a cd 65 4e ............z.eN 40: 10 b9 7a 34 1f 3e 65 4e b0 d3 b7 2d 1f 3e 65 4e ..z4.>eN...-.>eN 50: 50 24 c2 2d 00 20 00 00 02 00 00 00 00 00 00 00 P$.-. .......... 60: 6c 6f 66 73 00 00 00 00 00 00 00 00 00 00 00 00 lofs............ 70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ The size of the file (hex a8) appears at byte 34 which doesn''t agree with any of the different structs... (in struct stat32 it''s at offset 30). So I''m still a bit stumped. On 6 September 2011 08:48, <Casper.Dik at oracle.com> wrote:> >>The results are: >> >>$ sudo dtrace -s process_filesize.d -c ./stat >>Path: /home/triddel/stat.c >>File mode: 63676 >>File size: 0 >>File inode: 0 >>File uid: 33188 >>File fstype: >> >>File size is definitely not zero, and nor is the inode. Clearly the >>technique is working for the file path but it seems I''m doing >>something incorrect when accessing members of the stat64 struct. >> >>Can someone point me to what I''m doing wrong? > > There are three different stat structures in the kernel: > > ? ? ? ?- stat32 > ? ? ? ?- stat64 (native) > ? ? ? ?- stat64_32 (for 32 bit large file environment) > > *stat64 returns the latter and the differences are: > >> ::print -a "struct stat64" > 0 { > ? ?0 st_dev > ? ?8 st_ino > ? ?10 st_mode > ? ?14 st_nlink > ? ?18 st_uid > ? ?1c st_gid > ? ?20 st_rdev > ? ?28 st_size > ? ?30 st_atim { > ? ? ? ?30 tv_sec > ? ? ? ?38 tv_nsec > ? ?} > ? ?40 st_mtim { > ? ? ? ?40 tv_sec > ? ? ? ?48 tv_nsec > ? ?} > ? ?50 st_ctim { > ? ? ? ?50 tv_sec > ? ? ? ?58 tv_nsec > ? ?} > ? ?60 st_blksize > ? ?68 st_blocks > ? ?70 st_fstype > } >> ::print -a "struct stat64_32" > 0 { > ? ?0 st_dev > ? ?4 st_pad1 > ? ?10 st_ino > ? ?18 st_mode > ? ?1c st_nlink > ? ?20 st_uid > ? ?24 st_gid > ? ?28 st_rdev > ? ?2c st_pad2 > ? ?38 st_size > ? ?40 st_atim { > ? ? ? ?40 tv_sec > ? ? ? ?44 tv_nsec > ? ?} > ? ?48 st_mtim { > ? ? ? ?48 tv_sec > ? ? ? ?4c tv_nsec > ? ?} > ? ?50 st_ctim { > ? ? ? ?50 tv_sec > ? ? ? ?54 tv_nsec > ? ?} > ? ?58 st_blksize > ? ?60 st_blocks > ? ?68 st_fstype > ? ?78 st_pad4 > } > >
Casper.Dik at oracle.com
2011-Sep-06 08:51 UTC
[dtrace-discuss] Examining values returned from lstat64()
>The size of the file (hex a8) appears at byte 34 which doesn''t agree >with any of the different structs... (in struct stat32 it''s at offset >30).I run the mdb command on SPARC, on x86 it is:> ::print -at "struct stat64_32"0 struct stat64_32 { 0 dev32_t st_dev 4 int32_t [3] st_pad1 10 ino64_t st_ino 18 mode32_t st_mode 1c nlink32_t st_nlink 20 uid32_t st_uid 24 gid32_t st_gid 28 dev32_t st_rdev 2c int32_t [2] st_pad2 34 off64_t st_size <--- offset 0x34 3c timestruc32_t st_atim { 3c time32_t tv_sec 40 int32_t tv_nsec } 44 timestruc32_t st_mtim { 44 time32_t tv_sec 48 int32_t tv_nsec } 4c timestruc32_t st_ctim { 4c time32_t tv_sec 50 int32_t tv_nsec } 54 int32_t st_blksize 58 blkcnt64_t st_blocks 60 char [16] st_fstype 70 int32_t [8] st_pad4 } Not sure about the why the code doesn''t work. Casper
Toby Riddell
2011-Sep-06 09:53 UTC
[dtrace-discuss] Examining values returned from lstat64()
I managed to get it working by hard-coding the offset (ugh!): syscall::lstat64:return / self->stat && pid == $target / { this->path = copyinstr(self->path); printf("Path: %s\n", this->path); this->stat = copyin( self->stat + 0x34, sizeof(long long) ); printf("File size: %lld\n", *((long long *)(this->stat))); self->stat = 0; } On 6 September 2011 09:51, <Casper.Dik at oracle.com> wrote:> > >>The size of the file (hex a8) appears at byte 34 which doesn''t agree >>with any of the different structs... (in struct stat32 it''s at offset >>30). > > I run the mdb command on SPARC, on x86 it is: > >> ::print -at "struct stat64_32" > 0 struct stat64_32 { > ? ?0 dev32_t st_dev > ? ?4 int32_t [3] st_pad1 > ? ?10 ino64_t st_ino > ? ?18 mode32_t st_mode > ? ?1c nlink32_t st_nlink > ? ?20 uid32_t st_uid > ? ?24 gid32_t st_gid > ? ?28 dev32_t st_rdev > ? ?2c int32_t [2] st_pad2 > ? ?34 off64_t st_size ? ? ? ? ?<--- offset 0x34 > ? ?3c timestruc32_t st_atim { > ? ? ? ?3c time32_t tv_sec > ? ? ? ?40 int32_t tv_nsec > ? ?} > ? ?44 timestruc32_t st_mtim { > ? ? ? ?44 time32_t tv_sec > ? ? ? ?48 int32_t tv_nsec > ? ?} > ? ?4c timestruc32_t st_ctim { > ? ? ? ?4c time32_t tv_sec > ? ? ? ?50 int32_t tv_nsec > ? ?} > ? ?54 int32_t st_blksize > ? ?58 blkcnt64_t st_blocks > ? ?60 char [16] st_fstype > ? ?70 int32_t [8] st_pad4 > } > > > Not sure about the why the code doesn''t work. > > Casper > >
Chris Ridd
2011-Sep-06 09:59 UTC
[dtrace-discuss] Examining values returned from lstat64()
On 6 Sep 2011, at 09:51, Casper.Dik at oracle.com wrote:> Not sure about the why the code doesn''t work.Does passing -d32 to dtrace help? I get struct size/offset errors trying to analzye 32-bit binaries without this, though I''m not sure if stat64 would be affected. Chris -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://mail.opensolaris.org/pipermail/dtrace-discuss/attachments/20110906/c000af1d/attachment.html>
Casper.Dik at oracle.com
2011-Sep-06 11:15 UTC
[dtrace-discuss] Examining values returned from lstat64()
>Does passing -d32 to dtrace help? I get struct size/offset errors trying to analzye 32-bit binaries without this, though I''m not sure if stat64 would be affected. struct stat64_32 is the representation of the 32 bit "struct stat64" in a 64 bit application (specifically, time stamps are 32 bits and not 64 bits as is the case in the native stat64) Casper
Jonathan Adams
2011-Sep-06 16:55 UTC
[dtrace-discuss] Examining values returned from lstat64()
On Tue, Sep 06, 2011 at 10:53:13AM +0100, Toby Riddell wrote:> I managed to get it working by hard-coding the offset (ugh!): > > syscall::lstat64:return > / self->stat && pid == $target / > { > this->path = copyinstr(self->path); > printf("Path: %s\n", this->path); > > this->stat = copyin( self->stat + 0x34, sizeof(long long) ); > printf("File size: %lld\n", *((long long *)(this->stat))); > > self->stat = 0; > }The problem is that dtrace is trying to prevent unaligned loads, mainly because SPARC faults on them; I''m not entirely sure, but I believe amd64 wouldn''t have a problem with performing the load. If you want to make this less hardcoded, you could do: this->stat = copyin(self->stat + offsetof(struct stat64_32, st_size), sizeof (long long)); Cheers, - jonathan> On 6 September 2011 09:51, <Casper.Dik at oracle.com> wrote: > > > > > >>The size of the file (hex a8) appears at byte 34 which doesn''t agree > >>with any of the different structs... (in struct stat32 it''s at offset > >>30). > > > > I run the mdb command on SPARC, on x86 it is: > > > >> ::print -at "struct stat64_32" > > 0 struct stat64_32 { > > ? ?0 dev32_t st_dev > > ? ?4 int32_t [3] st_pad1 > > ? ?10 ino64_t st_ino > > ? ?18 mode32_t st_mode > > ? ?1c nlink32_t st_nlink > > ? ?20 uid32_t st_uid > > ? ?24 gid32_t st_gid > > ? ?28 dev32_t st_rdev > > ? ?2c int32_t [2] st_pad2 > > ? ?34 off64_t st_size ? ? ? ? ?<--- offset 0x34 > > ? ?3c timestruc32_t st_atim { > > ? ? ? ?3c time32_t tv_sec > > ? ? ? ?40 int32_t tv_nsec > > ? ?} > > ? ?44 timestruc32_t st_mtim { > > ? ? ? ?44 time32_t tv_sec > > ? ? ? ?48 int32_t tv_nsec > > ? ?} > > ? ?4c timestruc32_t st_ctim { > > ? ? ? ?4c time32_t tv_sec > > ? ? ? ?50 int32_t tv_nsec > > ? ?} > > ? ?54 int32_t st_blksize > > ? ?58 blkcnt64_t st_blocks > > ? ?60 char [16] st_fstype > > ? ?70 int32_t [8] st_pad4 > > } > > > > > > Not sure about the why the code doesn''t work. > > > > Casper > > > > > _______________________________________________ > dtrace-discuss mailing list > dtrace-discuss at opensolaris.org
Toby Riddell
2011-Sep-07 07:38 UTC
[dtrace-discuss] Examining values returned from lstat64()
That''s definitely an improvement - thanks. On 6 September 2011 17:55, Jonathan Adams <jonathan.adams at oracle.com> wrote:> On Tue, Sep 06, 2011 at 10:53:13AM +0100, Toby Riddell wrote: >> I managed to get it working by hard-coding the offset (ugh!): >> >> syscall::lstat64:return >> / self->stat && pid == $target / >> { >> ? ? ? ? this->path = copyinstr(self->path); >> ? ? ? ? printf("Path: %s\n", this->path); >> >> ? ? ? ? this->stat = ?copyin( self->stat + 0x34, sizeof(long long) ); >> ? ? ? ? printf("File size: %lld\n", *((long long *)(this->stat))); >> >> ? ? ? ? self->stat = 0; >> } > > The problem is that dtrace is trying to prevent unaligned loads, mainly > because SPARC faults on them; I''m not entirely sure, but I believe > amd64 wouldn''t have a problem with performing the load. > > If you want to make this less hardcoded, you could do: > > ? ? ? ?this->stat = copyin(self->stat + offsetof(struct stat64_32, st_size), > ? ? ? ? ? ?sizeof (long long)); > > Cheers, > - jonathan > >> On 6 September 2011 09:51, ?<Casper.Dik at oracle.com> wrote: >> > >> > >> >>The size of the file (hex a8) appears at byte 34 which doesn''t agree >> >>with any of the different structs... (in struct stat32 it''s at offset >> >>30). >> > >> > I run the mdb command on SPARC, on x86 it is: >> > >> >> ::print -at "struct stat64_32" >> > 0 struct stat64_32 { >> > ? ?0 dev32_t st_dev >> > ? ?4 int32_t [3] st_pad1 >> > ? ?10 ino64_t st_ino >> > ? ?18 mode32_t st_mode >> > ? ?1c nlink32_t st_nlink >> > ? ?20 uid32_t st_uid >> > ? ?24 gid32_t st_gid >> > ? ?28 dev32_t st_rdev >> > ? ?2c int32_t [2] st_pad2 >> > ? ?34 off64_t st_size ? ? ? ? ?<--- offset 0x34 >> > ? ?3c timestruc32_t st_atim { >> > ? ? ? ?3c time32_t tv_sec >> > ? ? ? ?40 int32_t tv_nsec >> > ? ?} >> > ? ?44 timestruc32_t st_mtim { >> > ? ? ? ?44 time32_t tv_sec >> > ? ? ? ?48 int32_t tv_nsec >> > ? ?} >> > ? ?4c timestruc32_t st_ctim { >> > ? ? ? ?4c time32_t tv_sec >> > ? ? ? ?50 int32_t tv_nsec >> > ? ?} >> > ? ?54 int32_t st_blksize >> > ? ?58 blkcnt64_t st_blocks >> > ? ?60 char [16] st_fstype >> > ? ?70 int32_t [8] st_pad4 >> > } >> > >> > >> > Not sure about the why the code doesn''t work. >> > >> > Casper >> > >> > >> _______________________________________________ >> dtrace-discuss mailing list >> dtrace-discuss at opensolaris.org >