问题
I have been trying to read a .trace
file, which I had generated using a custom instruments template(instruments: Automator, Allocations, Leaks) using Instruments.
The best help I found in this stackoverflow answer. Basically the author created a custom Objective-C program(Traced) to read a specific type of Apples .trace
file(instrument: OpenGL ES Driver). His answer is geared towards XCode 4.6.
The code still works with XCode 6.1, but the trace-file seems to have changed slightly. You have to find the *.run.zip
file within the .trace
package and unzip it. In the extracted folder you now have to find the *.run
file. There are several *.run.zip
files in a .trace
package; one per used instrument.
Simply running the Traced program got me a uncaught exception 'NSArchiverArchiveInconsistency', reason: '*** class error for 'XRObjectAllocRun'
-error.
This error was initially easy to figure out. All I had to do was implement the missing class XRObjectAllocRun
; parallel to the example XRRun
or XRVideoCardRun
classes in XRRun.m.
This is how far I got and where I got stuck:
#import "XRObjectAllocRun.h"
@implementation XRObjectAllocRun
- (id)initWithCoder:(NSCoder *)decoder
{
if((self = [super init]))
{
NSObject *a = [decoder decodeObject];
NSObject *b = [decoder decodeObject];
NSObject *c = [decoder decodeObject];
NSObject *d = [decoder decodeObject];
NSObject *e = [decoder decodeObject];
NSObject *f = [decoder decodeObject];
NSObject *g = [decoder decodeObject];
NSObject *h = [decoder decodeObject];
NSObject *i = [decoder decodeObject];
// NSObject *j = [decoder decodeObject];
// NSObject *k = [decoder decodeObject];
NSLog(@"test");
}
return self;
}
@end
Basically I am stuck reverse-engineering the XRObjectAllocRun
class. But no matter how many or little objects I decode I always receive the following exception: uncaught exception 'NSArchiverArchiveInconsistency', reason: '*** NSUnarchiver: inconsistency between written and read data for object 0x100112750'
If you uncomment the last two decode
statements the program will crash with this exception: uncaught exception 'NSArchiverArchiveInconsistency', reason: '*** file inconsistency: read 'i', expecting '@''
.
Does anyone know the signature of Apples XRObjectAllocRun class? This class is used for the Allocations instrument.
Any help would be great!
Update
I played around with Swift and translated the entire *.trace
-reader - it fails with exactly the same error(s):
import Foundation
import Cocoa
@objc(XRObjectAllocRun)
class XRObjectAllocRun: NSObject {
func initWithCoder(decoder:NSCoder){
var x = decoder.decodeObject()
// this is where things start breaking...
}
}
@objc(XRRun)
class XRRun: NSObject {
// to be implemented
}
@objc(XRTrackSegment)
class XRTrackSegment: NSObject {
func initWithCoder(decoder:NSCoder)->NSString{
var a = decoder.decodeObject()?.integerValue
var b = decoder.decodeObject()?.integerValue
var c = decoder.decodeObject()?.integerValue
var d = decoder.decodeObject()?.integerValue
var e = decoder.decodeObject()
return "test"
}
}
@objc(PFTTrackSegment)
class PFTTrackSegment: NSObject {
func initWithCoder(decoder:NSCoder){
var a = decoder.decodeObject()?.integerValue
var b = decoder.decodeObject()?.integerValue
var c = decoder.decodeObject()?.integerValue
var d = decoder.decodeObject()?.integerValue
var e = decoder.decodeObject()?.integerValue
var f = decoder.decodeObject()?.integerValue
}
}
// parse command line
var traceFilePath = Process.arguments[1]
println("input: \(traceFilePath)")
var traceFile = NSURL(fileURLWithPath: traceFilePath)
var error:NSError?
// check if the file exists
if (traceFile?.checkResourceIsReachableAndReturnError(&error) == false){
// file does not exist or cannot be accessed
println("\(error)")
exit(1)
}
var rawData = NSData(contentsOfURL: traceFile!)
var data = NSUnarchiver(forReadingWithData: rawData!)
var decodedObject: AnyObject? = data?.decodeObject()
println("\(decodedObject)")
回答1:
Here is the signature of the XRObjectAllocRun
class
#import "XRRun.h"
#import "SymbolAwareRun.h"
#import "XRCallTreeDataSource.h"
#import "XRSourceQuery.h"
@class NSMutableArray, NSMutableDictionary, NSString, XRHeapGeneration, XROAEventSummary, XRObjectAllocRunSharedData;
@interface XRObjectAllocRun : XRRun <SymbolAwareRun, XRSourceQuery, XRCallTreeDataSource>
{
XRObjectAllocRunSharedData *_sharedData;
NSMutableArray *_allStats;
NSMutableDictionary *_statsForCategory;
NSMutableDictionary *_categoryIDForName;
XROAEventSummary *_scaleStats;
NSMutableArray *_generations;
struct XRTimeRange _filterTimeRange;
unsigned int _filterMinEventID;
unsigned int _filterMaxEventID;
unsigned long long _nextGenNumber;
NSMutableDictionary *_samplesByCategoryNumber;
unsigned long long _catNumIndex;
struct XRTimeRange _currentStatsFilterRange;
int _lifecycleFilter;
int _allocationTypeFilter;
unsigned int *_quickEventCacheIds;
id *_quickEventCache;
XRHeapGeneration *_activeGeneration;
}
+ (void)initialize;
- (id)operation:(id)arg1 commentsForSymbol:(id)arg2 inSourceManager:(id)arg3 callTreeInformation:(id)arg4;
- (id)provideCategories;
- (id)backtracesForCategory:(id)arg1 timeRange:(struct XRTimeRange)arg2 savedIndex:(unsigned long long *)arg3;
- (void)_configureCallTreeForAllocationType:(int)arg1;
- (id)symbolsForEvent:(id)arg1 reverseOrder:(BOOL)arg2;
- (id)backtraceRepository;
- (BOOL)eventIsLiveInCurrentTimeRange:(id)arg1;
- (unsigned int)uncategorizedCount;
- (unsigned int)countOfObjectEventsForCategory:(unsigned int)arg1;
- (void)enumerateObjectEventsForCategory:(unsigned int)arg1 skipToIndex:(unsigned int)arg2 withBlock:(CDUnknownBlockType)arg3;
- (BOOL)_applyLifecycleFilterToEvent:(id)arg1;
- (id)zombieEvent;
- (id)eventForIdentifier:(unsigned int)arg1;
- (BOOL)loadDTPerformanceSessionDataFromPaths:(id)arg1 error:(id *)arg2;
- (void)updateGenerations;
- (void)deleteGeneration:(id)arg1;
- (void)moveGeneration:(id)arg1 toTime:(unsigned long long)arg2;
- (void)setActiveGeneration:(id)arg1;
- (id)generationAtTime:(unsigned long long)arg1;
- (id)generations;
- (id)nextGenerationIdentifier;
- (void)createGenerationAtTime:(unsigned long long)arg1;
- (void)removeFlag:(id)arg1;
- (struct XRTimeRange)_displayTimeFilter;
- (BOOL)_isTimeScoped;
- (BOOL)useTypeFilteringRules:(id)arg1;
- (void)setAllocationTypeFilter:(int)arg1;
- (void)setLifecycleFilter:(int)arg1;
- (struct XRTimeRange)selectedTimeRange;
- (void)setSelectedTimeRange:(struct XRTimeRange)arg1;
- (id)categoryNameForIdentifier:(unsigned int)arg1;
- (id)globalStats;
- (id)scalingStats;
- (void)_clearStats;
- (void)allowEventReuse;
- (void)refreshStatsForActiveTimeFilter;
- (void)_updateStatsWithEventIdentifier:(unsigned int)arg1 category:(unsigned int)arg2 type:(unsigned int)arg3 size:(int)arg4 pastEvent:(unsigned int)arg5 summaryMap:(id *)arg6 maxCat:(unsigned int)arg7;
- (id)_statsObjectForCategoryID:(unsigned int)arg1;
- (void)_changeStatsByTimestampRange:(struct XRTimeRange)arg1 overallRange:(struct XRTimeRange)arg2 startID:(unsigned int)arg3 endID:(unsigned int)arg4;
- (id *)_createCategorySummaryMapWithMaximum:(unsigned int)arg1;
- (void)_validateGlobalStatsForTimeRange:(struct XRTimeRange)arg1;
- (void)_recomputeGlobalStats;
- (BOOL)discardsLifeCycleComplete;
- (unsigned long long)lastTimestamp;
- (id)sharedData;
- (void)setRecordMode:(int)arg1;
- (void)setDiscardsLifeCycleComplete:(BOOL)arg1;
- (void)setTargetDevice:(id)arg1 pid:(int)arg2 repository:(id)arg3;
- (id)initWithCoder:(id)arg1;
- (void)encodeWithCoder:(id)arg1;
- (void)dealloc;
- (id)init;
// Remaining properties
@property(readonly, copy) NSString *debugDescription;
@property(readonly, copy) NSString *description;
@property(readonly) unsigned long long hash;
@property(readonly) Class superclass;
@end
I've uploaded signatures of other classes here if you need them.
Instead of declaring required classes in Swift, you can simply import headers from the archive to the bridging header.
回答2:
I made it work. Here is the git project.
来源:https://stackoverflow.com/questions/27951454/how-to-read-a-xcode-6-1-instruments-trace-file