• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
16import { BaseElement, element } from "../../base-ui/BaseElement.js";
17
18@element('tab-native-data-modal')
19export class DisassemblingWindow extends BaseElement {
20    private canvas: HTMLCanvasElement | undefined | null;
21    private window: HTMLElement | undefined | null;
22    private loading: HTMLElement | undefined | null;
23    private ctx: CanvasRenderingContext2D | null | undefined;
24    private hintLine = 0;
25    private addrArray = new Array<string>();
26    private maxBinSize = 0;
27    private close: Function | undefined | null;
28    setCloseListener(callback:Function){
29        this.close = callback;
30    }
31
32    removeCloseListener(){
33        this.close = null;
34    };
35
36    private getMap(content: string, hintAttr: string) {
37        let lines = content.split('\n');
38        this.addrArray = new Array<string>();
39        let lineMap = new Map<string, Disassembling>();
40        let effectLint = 0;
41        this.maxBinSize = 0;
42        for (let line of lines) {
43            let lineContents = line.split(':');
44            if (lineContents.length === 2) {
45                let addrHex = lineContents[0].trim();
46                let addr = '0x' + addrHex;
47                let value = lineContents[1].split('\t');
48                try {
49                    let binary = value[0];
50                    let lineStruct = new Disassembling();
51                    if (binary === '') {
52                        if (line.includes('Disassembly') || line.includes('file format')) {
53                            continue
54                        } else {
55                            if (addr.includes(' ')) {
56                                let funcs = addr.split(' ');
57                                lineStruct.addr = funcs[0];
58                                lineStruct.binary = funcs[1];
59                            }
60                        }
61                    } else {
62                        lineStruct.addr = addr;
63                        lineStruct.binary = value[0].trim();
64                        lineStruct.type = value.length > 1 ? value[1] : '';
65                        lineStruct.code = value.length > 2 ? value[2] : '';
66                    }
67                    lineMap.set(addrHex, lineStruct);
68                    this.maxBinSize = Math.max(this.ctx!.measureText(lineStruct.addr + lineStruct.binary).width, this.maxBinSize);
69                    this.addrArray.push(addrHex);
70                    if (addrHex === hintAttr) this.hintLine = effectLint;
71                    effectLint++;
72                } catch (e) {
73                    console.log(e);
74                }
75            }
76        }
77        return lineMap;
78    }
79
80    public showContent(content: string, hintAddr: string): void {
81        this.loading!.style.display = "none";
82        this.window!.style.display = "block";
83        if (content.startsWith('error')) {
84            this.window!.innerHTML = `<span class="column1" style="width:100%;text-align: center;">${content}</span>`;
85            return;
86        }
87        let lineMap = this.getMap(content, hintAddr);
88        this.maxBinSize = this.maxBinSize * 1.7;
89        this.window!.innerHTML = '';
90        for (let addr of this.addrArray) {
91            if (!lineMap.has(addr)) continue;
92            let struct = lineMap.get(addr);
93            if (this.addrArray[this.hintLine] == addr) {
94                this.window!.innerHTML += `<div class="line" id="emphasis" style = background:red">
95                <span class="column0" style="width:${this.maxBinSize}px;">${struct!.addr} : ${struct!.binary}</span>
96                <span class="column1" style="width:100px;">${struct!.type}</span>
97                <span class="column2" style="width:300px;">${struct!.code}</span></div>`;
98                (this.window!.querySelector("#emphasis") as HTMLElement)!.style.width = this.window!.scrollWidth + 'px';
99                (this.window!.querySelector("#emphasis") as HTMLElement)!.style.background = '#0A59F7';
100            } else {
101                this.window!.innerHTML += `<div class="line">
102                <span class="column0" style="width:${this.maxBinSize}px;">${struct!.addr} : ${struct!.binary}</span>
103                <span class="column1" style="width:100px;">${struct!.type}</span>
104                <span class="column2" style="width:300px;">${struct!.code}</span></div>`;
105            }
106        }
107        this.window!.scrollTo(0, (this.hintLine - 1) * (this.shadowRoot!.querySelector("#window>.line")!.clientHeight) - this.window!.clientHeight / 2);
108    }
109
110    private resetCanvas(styleWidth: number, styleHeight: number, width: number, height: number): void {
111        this.canvas!.style.width = styleWidth + "px";
112        this.canvas!.style.height = styleHeight + "px";
113        this.canvas!.width = width;
114        this.canvas!.height = height;
115    }
116
117    public showLoading(): void {
118        this.loading!.style.display = 'block';
119        this.window!.style.display = 'none';
120        this.style.display = 'block';
121        this.style.position = 'absolute';
122        this.style.left = '0px';
123        this.style.border = '1px solid #d8d8d8';
124    }
125
126    initElements(): void {
127        this.canvas = this.shadowRoot?.querySelector<HTMLCanvasElement>("#canvas");
128        let close = this.shadowRoot?.querySelector("#close");
129        this.window = this.shadowRoot?.querySelector("#window");
130        this.loading = this.shadowRoot?.querySelector("#loading");
131        this.ctx = this.canvas!.getContext('2d');
132        this.resetCanvas(0, 0, 0, 0);
133        close!.addEventListener("click", () => {
134           if(this.close){
135              this.close();
136           }
137            return true;
138        });
139    }
140
141    initHtml(): string {
142        return `
143        <style>
144            #close{
145                position:absolute;
146                top:0px;
147                right: 0px;
148                color: #D6D6D6;
149            }
150            #modal-wrap{
151                position: absolute;
152                top: 0;
153                left: 0;
154                width:100%;
155                height:100%;
156                background: var(--dark-background,#ffffff);
157                z-index: 2000;
158            }
159            #window{
160                overflow: auto;
161                position: absolute;
162                top: 21px;
163                left: 0;
164                width: calc(100% - 10px);
165                height: calc(100% - 21px);
166                padding-left: 10px;
167            }
168            #loading{
169                position: absolute;
170                left: calc(50% - 20px);
171                top: calc(50% - 20px);
172                width:40px;
173                height:40px;
174                transform: rotate(360deg);
175                animation: rotation 2s linear infinite;
176                -webkit-animation: rotation 2s linear infinite;
177            }
178            @keyframes rotation{
179                from {
180                    -webkit-transform: rotate(0deg);
181                }
182                to {
183                    -webkit-transform: rotate(360deg);
184                }
185            }
186            .line{
187                line-height:27px;
188                white-space: nowrap;
189            }
190            span{
191                display: inline-block;
192            }
193        </style>
194        <div id="modal-wrap">
195            <canvas id="canvas" style="display: none"> </canvas>
196            <lit-icon id="close" name="close" size="20"> </lit-icon>
197            <div id="window"> </div>
198             <lit-icon id="loading" name="loading" size="40"> </lit-icon>
199        </div>
200        `;
201    }
202}
203
204class Disassembling {
205    addr = '';
206    binary = '';
207    type = '';
208    code = '';
209}