From 2b51c6a7a37cd787c773f8ec1cd19bcb715e8c1f Mon Sep 17 00:00:00 2001 From: Jamie Wong Date: Sun, 10 Mar 2019 22:49:38 -0700 Subject: [PATCH 1/3] Update Synalize It! Grammars --- .../8.3.3/integer-uniquer-index.grammar | 12 ++++---- .../8.3.3/time-sample-bulkstore.grammar | 29 ++++++++++--------- 2 files changed, 21 insertions(+), 20 deletions(-) diff --git a/sample/profiles/Instruments/8.3.3/integer-uniquer-index.grammar b/sample/profiles/Instruments/8.3.3/integer-uniquer-index.grammar index c942de2cd..e0c029f4a 100644 --- a/sample/profiles/Instruments/8.3.3/integer-uniquer-index.grammar +++ b/sample/profiles/Instruments/8.3.3/integer-uniquer-index.grammar @@ -1,12 +1,12 @@ - + Grammar for INDEX files - - - - - + + + + + diff --git a/sample/profiles/Instruments/8.3.3/time-sample-bulkstore.grammar b/sample/profiles/Instruments/8.3.3/time-sample-bulkstore.grammar index b890d35d9..d9392de61 100644 --- a/sample/profiles/Instruments/8.3.3/time-sample-bulkstore.grammar +++ b/sample/profiles/Instruments/8.3.3/time-sample-bulkstore.grammar @@ -1,21 +1,22 @@ - + Grammar for BIN files - - - - - - - - - + + + + + + + + + - - - - + + + + + From e318f63fd2518032d3618045fd52527454b473e9 Mon Sep 17 00:00:00 2001 From: Jamie Wong Date: Sun, 10 Mar 2019 23:14:56 -0700 Subject: [PATCH 2/3] Make import kind of work for the failing file --- src/import/instruments.ts | 42 +++++++++++++++++++++++++++++---------- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/src/import/instruments.ts b/src/import/instruments.ts index 34eb26550..bf810eeee 100644 --- a/src/import/instruments.ts +++ b/src/import/instruments.ts @@ -508,22 +508,44 @@ export function importThreadFromInstrumentsTrace(args: { const profile = new StackListProfileBuilder(lastOf(samples)!.timestamp) profile.setName(`${fileName} - thread ${threadID}`) + // Each sample's stack is identified by a single number. This number might be + // a an address, or an index into the integer array list. If it's an index + // into the integer arrays list, then the integer array it corresponds to + // might itself contain either addresses or indices into the integer array. function appendRecursive(k: number, stack: FrameInfo[]) { - const frame = addressToFrameMap.get(k) + // First try: let's see if the number is an address and we have + // an associated stack frame for the address. + const address = k + const frame = addressToFrameMap.get(address) if (frame) { stack.push(frame) - } else if (k in arrays) { - for (let addr of arrays[k]) { + return + } + + // Second try: let's see if the number is an index into the integer array + // list. We'll re-interpret the index as a 32 bit integer here by ignoring + // the upper 32 bits of the integer. + // + // TODO(jlfwong): This seems pretty dubious. Is there a more correct wait to + // differentiate between an address and a number? I wonder if there's either + // some metadata somewhere that we need or if there's something in the byte + // sequence that indicates what kind of number it is. + const arrayIndex = k & 0xffffffff + if (arrayIndex in arrays) { + for (let addr of arrays[arrayIndex]) { appendRecursive(addr, stack) } - } else { - const rawAddressFrame: FrameInfo = { - key: k, - name: `0x${zeroPad(k.toString(16), 16)}`, - } - addressToFrameMap.set(k, rawAddressFrame) - stack.push(rawAddressFrame) + return + } + + // Fallback case: we'll say we can't find the address, and just + // display the address instead of frame information. + const rawAddressFrame: FrameInfo = { + key: k, + name: `0x${zeroPad(k.toString(16), 16)}`, } + addressToFrameMap.set(k, rawAddressFrame) + stack.push(rawAddressFrame) } let lastTimestamp: null | number = null From 023559400280464ba1182588012d95abddc757ca Mon Sep 17 00:00:00 2001 From: Jamie Wong Date: Sun, 10 Mar 2019 23:27:15 -0700 Subject: [PATCH 3/3] Clarify magic numbers in getRawSampleList --- src/import/instruments.ts | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/import/instruments.ts b/src/import/instruments.ts index bf810eeee..efc616ac5 100644 --- a/src/import/instruments.ts +++ b/src/import/instruments.ts @@ -278,13 +278,21 @@ async function getRawSampleList(core: TraceDirectoryTree): Promise { while (true) { // Schema as of Instruments 8.3.3 is a 6 byte timestamp, followed by a bunch // of stuff we don't care about, followed by a 4 byte backtrace ID + const timestampBytes = 48 / 8 const timestamp = bulkstore.readUint48() if (timestamp === 0) break + const threadIDBytes = 32 / 8 const threadID = bulkstore.readUint32() - bulkstore.skip(bytesPerEntry - 6 - 4 - 4) + // Skip the stuff we don't care about. We can do this because we know how + // many bytes there shuold be per entry from the header of the file, and + // we know how many bytes we're reading for each of the fields we do care + // about. + const backtraceIDBytes = 32 / 8 + bulkstore.skip(bytesPerEntry - timestampBytes - threadIDBytes - backtraceIDBytes) const backtraceID = bulkstore.readUint32() + samples.push({timestamp, threadID, backtraceID}) } return samples