1/* 2 * Copyright (C) 2022 Huawei Device Co., Ltd. 3 * Licensed under the Apache License, Version 2.0 (the "License"); 4 * you may not use this file except in compliance with the License. 5 * You may obtain a copy of the License at 6 * 7 * http://www.apache.org/licenses/LICENSE-2.0 8 * 9 * Unless required by applicable law or agreed to in writing, software 10 * distributed under the License is distributed on an "AS IS" BASIS, 11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 * See the License for the specific language governing permissions and 13 * limitations under the License. 14 */ 15 16importScripts('trace_converter_builtin.js'); 17self.onerror = function (error: unknown): void {}; 18 19let convertModule: unknown = null; 20 21const CONTENT_TYPE_CMDLINES = 2; 22const CONTENT_TYPE_TGIDS = 3; 23const CONTENT_TYPE_HEADER_PAGE = 30; 24const CONTENT_TYPE_PRINTK_FORMATS = 31; 25const CONTENT_TYPE_KALLSYMS = 32; 26 27function initConvertWASM(): Promise<string> { 28 return new Promise((resolve, reject) => { 29 // @ts-ignore 30 let wasm = trace_converter_builtin_wasm; 31 convertModule = wasm({ 32 locateFile: (s: unknown): unknown => { 33 return s; 34 }, 35 print: (line: unknown): void => {}, 36 printErr: (line: unknown): void => {}, 37 onAbort: (): void => { 38 reject('on abort'); 39 }, 40 onRuntimeInitialized: (): void => { 41 resolve('ok'); 42 }, 43 }); 44 }); 45} 46 47function isRawTrace(uint8Array: Uint8Array): boolean { 48 let rowTraceStr = Array.from(new Uint16Array(uint8Array.buffer.slice(0, 2))); 49 return rowTraceStr[0] === 57161; 50} 51 52const ARRAY_BUF_SIZE = 2 * 1024 * 1024; 53self.onmessage = async (e: MessageEvent): Promise<void> => { 54 if (e.data.action === 'getConvertData') { 55 await initConvertWASM(); 56 let fileData = e.data.buffer; 57 const stepSize = 4 * 1024 * 1024; 58 let totalSize = fileData.byteLength; 59 // @ts-ignore 60 let traceInsPtr = convertModule._GetTraceConverterIns(); // 获取TraceConverter 实例 61 // @ts-ignore 62 convertModule._SetDebugFlag(false, traceInsPtr); // 设置是否为debug模式 63 let currentPosition = 1024; 64 // @ts-ignore 65 let dataHeader = convertModule._malloc(1100); 66 let traceAllData = new Uint8Array(e.data.buffer); 67 let isRawTraceConvert = isRawTrace(e.data); 68 if (isRawTraceConvert) { 69 [totalSize, currentPosition, traceAllData] = handleRowTrace( 70 e, 71 fileData, 72 dataHeader, 73 traceInsPtr, 74 currentPosition, 75 traceAllData, 76 totalSize 77 ); 78 } else { 79 handleHTrace(fileData, dataHeader, traceInsPtr); 80 } 81 // @ts-ignore 82 let dataPtr = convertModule._malloc(stepSize); 83 // @ts-ignore 84 let arrayBufferPtr = convertModule._malloc(ARRAY_BUF_SIZE); 85 // @ts-ignore 86 convertModule._free(dataHeader); 87 let bodyDataStr: string[] = []; 88 let callback = (heapPtr: number, size: number): void => { 89 // @ts-ignore 90 let out = convertModule.HEAPU8.slice(heapPtr, heapPtr + size); 91 let dec = new TextDecoder(); 92 let str = dec.decode(out); 93 bodyDataStr.push(str); 94 }; 95 // @ts-ignore 96 let bodyFn = convertModule.addFunction(callback, 'vii'); 97 // @ts-ignore 98 convertModule._SetCallback(bodyFn, traceInsPtr); 99 convertData( 100 currentPosition, 101 traceAllData, 102 arrayBufferPtr, 103 dataPtr, 104 traceInsPtr, 105 isRawTraceConvert, 106 stepSize, 107 totalSize 108 ); 109 // @ts-ignore 110 convertModule._GetRemainingData(traceInsPtr); 111 let headerData: string[] = []; 112 let headerCallback = (heapPtr: number, size: number): void => { 113 // @ts-ignore 114 let out = convertModule.HEAPU8.slice(heapPtr, heapPtr + size); 115 let dec = new TextDecoder(); 116 let str = dec.decode(out); 117 headerData.push(str); 118 }; 119 // @ts-ignore 120 let headerFn = convertModule.addFunction(headerCallback, 'vii'); 121 // @ts-ignore 122 convertModule._SetCallback(headerFn, traceInsPtr); 123 // @ts-ignore 124 convertModule._GetFinalHeader(traceInsPtr); 125 let allDataStr = headerData.concat(bodyDataStr); 126 // @ts-ignore 127 convertModule._ReleaseTraceConverterIns(traceInsPtr); // 释放TraceConverter 实例 128 // @ts-ignore 129 convertModule._free(arrayBufferPtr); //释放分片内存 130 // @ts-ignore 131 convertModule._free(dataPtr); 132 postMessage(e, allDataStr); 133 } 134}; 135 136function handleHTrace(fileData: Array<unknown>, dataHeader: unknown, traceInsPtr: unknown): void { 137 // @ts-ignore 138 let uint8Array = new Uint8Array(fileData.slice(0, 1024)); 139 // @ts-ignore 140 convertModule.HEAPU8.set(uint8Array, dataHeader); 141 // @ts-ignore 142 convertModule._SendFileHeader(dataHeader, 1024, traceInsPtr); 143} 144 145function handleRowTrace( 146 e: MessageEvent, 147 fileData: Array<unknown>, 148 dataHeader: unknown, 149 traceInsPtr: unknown, 150 currentPosition: number, 151 traceAllData: Uint8Array, 152 totalSize: number 153): [number, number, Uint8Array] { 154 // @ts-ignore 155 let uint8Array = new Uint8Array(fileData.slice(0, 12)); 156 // @ts-ignore 157 convertModule.HEAPU8.set(uint8Array, dataHeader); 158 // @ts-ignore 159 convertModule._SendRawFileHeader(dataHeader, 12, traceInsPtr); 160 currentPosition = 12; 161 let allRowTraceData = new Uint8Array(e.data.buffer); 162 let commonDataOffsetList: Array<{ 163 startOffset: number; 164 endOffset: number; 165 }> = []; 166 let commonTotalLength = setCommonDataOffsetList(e, allRowTraceData, commonDataOffsetList); 167 let commonTotalOffset = 0; 168 let commonTotalData = new Uint8Array(commonTotalLength); 169 commonDataOffsetList.forEach((item) => { 170 commonTotalData.set(allRowTraceData.slice(item.startOffset, item.endOffset), commonTotalOffset); 171 commonTotalOffset += item.endOffset - item.startOffset; 172 }); 173 traceAllData = new Uint8Array(allRowTraceData.length + commonTotalData.length); 174 traceAllData.set(allRowTraceData.slice(0, currentPosition), 0); 175 traceAllData.set(commonTotalData, currentPosition); 176 traceAllData.set(allRowTraceData.slice(currentPosition), commonTotalData.length + currentPosition); 177 totalSize += commonTotalData.length; 178 return [totalSize, currentPosition, traceAllData]; 179} 180 181function isCommonData(dataType: number): boolean { 182 return ( 183 dataType === CONTENT_TYPE_CMDLINES || 184 dataType === CONTENT_TYPE_TGIDS || 185 dataType === CONTENT_TYPE_HEADER_PAGE || 186 dataType === CONTENT_TYPE_PRINTK_FORMATS || 187 dataType === CONTENT_TYPE_KALLSYMS 188 ); 189} 190 191function setCommonDataOffsetList( 192 e: MessageEvent, 193 allRowTraceData: Uint8Array, 194 commonDataOffsetList: Array<unknown> 195): number { 196 let commonTotalLength: number = 0; 197 let commonOffset = 12; 198 let tlvTypeLength = 4; 199 while (commonOffset < allRowTraceData.length) { 200 let commonDataOffset = { 201 startOffset: commonOffset, 202 endOffset: commonOffset, 203 }; 204 let dataTypeData = e.data.buffer.slice(commonOffset, commonOffset + tlvTypeLength); 205 commonOffset += tlvTypeLength; 206 let dataType = Array.from(new Uint32Array(dataTypeData)); 207 let currentLData = e.data.buffer.slice(commonOffset, commonOffset + tlvTypeLength); 208 commonOffset += tlvTypeLength; 209 let currentVLength = Array.from(new Uint32Array(currentLData)); 210 commonOffset += currentVLength[0]; 211 commonDataOffset.endOffset = commonOffset; 212 if (isCommonData(dataType[0])) { 213 commonTotalLength += commonDataOffset.endOffset - commonDataOffset.startOffset; 214 commonDataOffsetList.push(commonDataOffset); 215 } 216 } 217 return commonTotalLength; 218} 219 220function convertData( 221 currentPosition: number, 222 traceAllData: Uint8Array, 223 arrayBufferPtr: unknown, 224 dataPtr: unknown, 225 traceInsPtr: unknown, 226 isRawTraceConvert: boolean = false, 227 stepSize: number, 228 totalSize: number 229): void { 230 while (currentPosition < totalSize) { 231 let endPosition = Math.min(currentPosition + stepSize, totalSize); 232 let currentChunk = new Uint8Array(traceAllData.slice(currentPosition, endPosition)); 233 // @ts-ignore 234 convertModule.HEAPU8.set(currentChunk, dataPtr); 235 let leftLen = currentChunk.length; 236 let processedLen = 0; 237 let blockSize = 0; 238 let blockPtr = dataPtr; 239 while (leftLen > 0) { 240 if (leftLen > ARRAY_BUF_SIZE) { 241 blockSize = ARRAY_BUF_SIZE; 242 } else { 243 blockSize = leftLen; 244 } 245 // @ts-ignore 246 let subArrayBuffer = convertModule.HEAPU8.subarray(blockPtr, blockPtr + blockSize); 247 // @ts-ignore 248 convertModule.HEAPU8.set(subArrayBuffer, arrayBufferPtr); 249 // 调用分片转换接口 250 if (isRawTraceConvert) { 251 // @ts-ignore 252 convertModule._ConvertRawBlockData(arrayBufferPtr, subArrayBuffer.length, traceInsPtr); // raw trace 253 } else { 254 // @ts-ignore 255 convertModule._ConvertBlockData(arrayBufferPtr, subArrayBuffer.length, traceInsPtr); // htrace 256 } 257 processedLen = processedLen + blockSize; 258 // @ts-ignore 259 blockPtr = dataPtr + processedLen; 260 leftLen = currentChunk.length - processedLen; 261 } 262 currentPosition = endPosition; 263 } 264} 265 266function postMessage(e: MessageEvent, allDataStr: Array<string>): void { 267 self.postMessage( 268 { 269 id: e.data.id, 270 action: 'convert', 271 status: true, 272 results: new Blob(allDataStr, { type: 'text/plain' }), 273 buffer: e.data.buffer, 274 }, 275 // @ts-ignore 276 [e.data.buffer!] 277 ); 278} 279