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