Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does DTrace give me invalid-address errors sometimes but not always?

My program:

typedef struct objc_class {
    struct objc_class *isa;
    struct objc_class *super_class;
    char *name;
    long version;
    long info;
    long instance_size;
    void *ivars;
    void *methodLists;
    void *cache;
    void *protocols;
} *Class;
struct objc_object {
    Class isa;
};

/* Code to extract the class name from arg0 based on a snippet by Bill Bumgarner: http://friday.com/bbum/2008/01/26/objective-c-printing-class-name-from-dtrace/ */

objc$target:NSObject:-init:entry {
    printf("time: %llu\n", timestamp);
    printf("arg0: %p\n", arg0);
    obj = (struct objc_object *)copyin(arg0, sizeof(struct objc_object));
    printf("obj: %p\n", obj);
    printf("obj->isa: %p\n", obj->isa);
    isa = (Class)copyin((user_addr_t)obj->isa, sizeof(struct objc_class));
    printf("isa: %p\n", obj->isa);
    classname = copyinstr((user_addr_t)(isa->name));
    printf("classname: %s\n", classname);
}

Some output:

dtrace: script 'test.d' matched 1 probe
dtrace: error on enabled probe ID 1 (ID 61630: objc5936:NSObject:-init:entry): invalid address (0x90206b98) in action #8 at DIF offset 28
dtrace: error on enabled probe ID 1 (ID 61630: objc5936:NSObject:-init:entry): invalid address (0x90206b98) in action #8 at DIF offset 28
dtrace: error on enabled probe ID 1 (ID 61630: objc5936:NSObject:-init:entry): invalid address (0x90206b98) in action #8 at DIF offset 28
CPU     ID                    FUNCTION:NAME
  0  61630                      -init:entry time: 28391086668386
arg0: 1291ae10
obj: 6f0a1158
obj->isa: a023f360
isa: a023f360
classname: NSBitmapImageRep

  1  61630                      -init:entry time: 28391586872297
arg0: 12943560
obj: 6f4a1158
obj->isa: 2fca0
isa: 2fca0
classname: GrowlApplicationTicket

  1  61630                      -init:entry time: 28391586897807
arg0: 152060
obj: 6f4a1280
obj->isa: 2fe20
isa: 2fe20
classname: GrowlNotificationTicket

  2  61630                      -init:entry time: 28391079142905
arg0: 129482d0
obj: 700a1128
obj->isa: a0014140
isa: a0014140
classname: NSDistributedObjectsStatistics

  2  61630                      -init:entry time: 28391079252640
arg0: 147840
obj: 700a1250
obj->isa: a0014780
isa: a0014780
classname: NSDistantObjectTableEntry

Why the errors? It seems to be the class name (that's the only %s, and I don't get any errors if I remove it), but why does it think some classes' names are invalid pointers?

Is there any way to get the error messages to actually tell me which line of my DTrace program caused a problem?

Is there a way to call object_getClassName instead of doing this structure-inspection dance?

For what it's worth, the program I'm tracing works fine—it's not crashing, so I don't believe that the classes really are broken.

like image 476
Peter Hosey Avatar asked Jul 29 '09 04:07

Peter Hosey


3 Answers

Colin is pretty close to correct.

See:

http://www.friday.com/bbum/2008/01/03/objective-c-using-dtrace-to-trace-messages-to-nil/

More likely than not, you need to set the DYLD_SHARED_REGION environment variable to avoid. dtrace only really works against mapped memory that is actually resident in physical memory.

You can figure out what is missing by using the vmmap command line tool.

Do a vmmap PID on your application after the above failure messages are generated. Looking at the output, see what region the addresses like 0x90206b98 fall into. Given that address, it is likely in a non-writeable shared chunk of memory that probably isn't resident and, thus, dtrace can't read from it.

like image 191
bbum Avatar answered Sep 18 '22 16:09

bbum


This error happens when copyin / copyinstr is used on a page that's not faulted in yet. A common workaround is to let the function use the data in question, and then copyin[str] in a :::return clause. For example:

syscall::open:entry
{
    self->filename = arg0;  /* Hang on to the file name pointer.  */
}

syscall::open:return
/self->filename/
{
    @files[copyinstr(self->filename)] = count();
    self->filename = 0;
}

END
{
    trunc(@files, 5);
}
like image 26
Mark Dalrymple Avatar answered Sep 20 '22 16:09

Mark Dalrymple


I haven't entirely tracked this down myself. It's possible that DTrace is trying to resolve some Objective-C symbols. Although DTrace is a dynamic tracing facility it doesn't mesh well with Objective-C dynamically loading things at runtime. When Objective-C does load new classes,etc DTrace has to resolve this and it takes a little time, especially when your app is just starting up. Even if it does get things loaded, and your objc app is still loading new classes onto the objc runtime its possible DTrace could get screwed up and print methods in the wrong order (if you care about seeing the correct order methods are being executed in), print incorrect timing results,etc.

like image 36
Colin Wheeler Avatar answered Sep 19 '22 16:09

Colin Wheeler