JavaScript Debugger 原理揭秘

前端 2023-07-05 17:29:38
64阅读

文中转载微信公众平台「开光的程序编写秘笈」,创作者神说要有光zxg。转截文中请联络开光的程序编写秘笈微信公众号。

编码写完会运作一下看下实际效果,开发设计的情况下大家大量全是根据 dubugger 来单步或中断点运作。大家一天到晚在使用 debugger,但是您有想过它的完成基本原理么。

文中会解释下列难题:

  • 程序执行的最底层基本原理是啥
  • 为何必须 debugger
  • debugger 完成基本原理是啥
  • 怎样完成 debugger 手机客户端

程序执行的基本原理是啥

编码的运作方法能够分成立即实行和表述实行两大类。

不清楚平常你有没有留意,可执行程序立即 ./xxx 就可以实行,而实行 js 文档必须 node ./xxx,实行 python 文档必须 python ./xxx,这就是编译程序实行(立即实行)和表述实行的差别。

立即实行

cpu 出示了一套指令系统,根据这套指令系统就可以操纵全部电子计算机的运行,程序设计语言的编码便是由这种命令和相匹配的操作数组成的,这种序列号能够立即跑在电子计算机上,也就是可立即实行。由他们组成的文档称为可执行程序。

不一样电脑操作系统可执行程序的文件格式不一样,在 windows 上是 pe(Portable Executable) 文件格式,在 linux、unix 系统软件上是 elf(Executable Linkable Format) 文件格式,在 mac 上是 mash-o 文件格式。他们要求了不一样的內容(.text 是编码、.data .bass 等是数据信息)放到文档中的什么位置。但在其中真真正正可实行的一部分或是由 cpu 出示的计算机指令组成的。

编译型语言会历经编译程序、选编、连接的环节,编译程序是把源码转成汇编程序组成的中间代码,选编是把中间代码变为总体目标编码,连接会把总体目标编码组成可执行程序。这一可执行程序是能够在电脑操作系统上立即实行的。就因为它是由 cpu 的计算机指令组成的,能够立即操纵 cpu。因此 能够立即 ./xxx 就可以实行。

表述实行

编译型语言全是转化成可执行程序立即在电脑操作系统上去实行的,不用安裝编译器,而 js、python 等解释型语言的编码必须用编译器来跑。

为何拥有编译器就不用转化成序列号了,cpu 依然不认识这种编码啊?

那是由于编译器是必须编写出序列号的,cpu 了解如何实行编译器,而编译器了解如何实行更顶层的脚本制作编码,就是这样,由序列号表述实行编译器,再由编译器表述实行顶层编码,这就是开发语言的基本原理。 包含 js、python 等全是那样。

可是编译器终究多了一层,因此 有的情况下会把它编写出序列号来立即实行,这就是 JIT c语言编译器。例如 js 模块一般便是由 parser、编译器、JIT c语言编译器、GC 组成,绝大多数编码是由编译器表述实行的,而网络热点编码会历经 JIT c语言编译器编写出由序列号,立即在电脑操作系统上实行以提升 特性。

编写出序列号立即实行,或是是以源代码表述实行,编码就这二种实行方法。二者都有各的益处,编译程序型速度更快,表述型混合开发。这就是程序执行的基本原理。

王垠说过,电子计算机的实质便是编译器。就是 cpu 用电源电路表述序列号,编译器用序列号表述更顶层的脚本制作编码,因此 电子计算机的实质是编译器。

为何必须 debugger

我们知道,图灵完备的语言表达能够表述一切可测算难题,因此 无论是编译程序型或是表述型都可以叙述全部可测算的领域模型。

大家运用不一样的语言表达叙述领域模型,随后运作它看实际效果,当编码的逻辑性非常复杂的情况下,在所难免打错,大家期待可以一步步运作或者运作到某一点慢下来,随后看一下那时候的自然环境中的自变量,实行某一脚本制作。进行这一作用的便是 debugger。

或许也有许多初级程序员总是用 console.log 打日志,可是日志不可以彻底呈现那时候的自然环境,最好是的方法或是 debugger。

狼叔说过,是不是会用 debugger 是 nodejs 水准的一个显著的区别。

debugger 的基本原理

大家知道 debugger 是程序调试不可或缺的,那麼它是怎么完成的呢?

可执行程序的 debugger

实际上 cpu、电脑操作系统在设计方案的情况下就适用了 debugger 的工作能力(由此可见 debugger 的必要性),cpu 里边有 4 个存储器能够做硬终断,电脑操作系统出示了系统进程来做软终断。它是编译型语言的 debugger 完成的基本。

终断

cpu 总是持续的实行下一条命令,但程序执行全过程中免不了要解决一些外界的信息,例如 io、互联网、出现异常这些,因此 设计方案了终断的体制,cpu 每实行完一条命令,便会去看看下终断标识,是不是必须终断了。如同 event loop 每一次 loop 完都需要查验下是不是必须3D渲染一样。

INT 命令

cpu 适用 INT 命令来开启终断,终断有序号,不一样的序号有不一样的程序处理,纪录序号和终断程序处理的表称为中断向量表。在其中 INT 3 (3 号终断)能够开启 debugger,它是一种承诺。

那麼可执行程序是怎么运用这一 3 号终断来 debugger 的呢?实际上便是运作时更换实行的內容,debugger 程序流程会在必须设定中断点的部位把命令內容换为 INT 3,也就是 0xCC,这就断住了。就可以获得此刻的自然环境数据信息来做调节。

根据序列号换成 0xcc (INT 3)是把程序流程断住了,但是如何恢复实行呢?实际上也非常简单,把那时候更换的序列号记下来,必须释放出来中断点的情况下再换回去就可以了。

这就是可执行程序的 debugger 的基本原理了,最后或是靠 cpu 适用的终断体制来完成的。

终断存储器

上边说的 debugger 完成方法是改动运行内存中的序列号的方法,但有的情况下改动不上编码,例如 ROM,这类状况就需要根据 cpu 出示的 4 个终断存储器(DR0 - DR3)来干了。这类称为硬终断。

总而言之,INT 3 的软终断,也有终断存储器的硬终断,是可执行程序完成 debugger 的二种方法。

解释型语言的 debugger

编译型语言由于立即在电脑操作系统以上实行,因此 要运用 cpu 和电脑操作系统的终断体制和系统进程来完成 debugger。可是解释型语言是自身完成编码的表述实行的,因此 不用那一套,可是完成构思或是一样的,便是插进一段编码来断住,适用自然环境数据信息的查询和编码的实行,当释放出来中断点的情况下就再次向下实行。

例如 javascript 中适用 debugger 句子,当编译器实行到这一条句子的情况下便会断住。

解释型语言的 debugger 相对性简易一些,不用掌握 cpu 的 INT 3 终断。

debugger 手机客户端

上边大家了解了立即实行和表述实行的编码的 debugger 各自是怎么完成的。大家知道编码是怎么断住的,那麼断住以后呢?如何把自然环境数据信息曝露出来 ,如何实行外界编码?

这就必须 debugger 手机客户端了。

例如 v8 模块会把设定中断点、获得自然环境信息内容、实行脚本制作的工作能力根据 socket 曝露出来 ,socket 传送的信息格式便是 v8 debug protocol 。

例如:

设定中断点:

 
  1.     "seq":117, 
  2.     "type":"request"
  3.     "command":"setbreakpoint"
  4.     "arguments":{ 
  5.         "type":"function"
  6.         "target":"f" 
  7.     } 

除掉中断点:

 
  1.     "seq":117, 
  2.     "type":"request"
  3.     "command":"clearbreakpoint"
  4.     "arguments": { 
  5.         "type":"function"
  6.         "breakpoint":1 
  7.      } 

再次:

 
  1.     "seq":117, 
  2.     "type":"request"
  3.     "command":"continue" 

实行编码:

 
  1.     "seq":117, 
  2.     "type":"request"
  3.     "command":"evaluate"
  4.     "arguments":{ 
  5.         "expression":"1 2" 
  6.     } 

有兴趣的同学们能够去 v8 debug protocol 的文本文档中去查看历史的协议书。

根据这种协议书就可以操纵 v8 的 debugger 了,全部的可以完成 debugger 的全是连接了这一协议书,例如 chrome devtools、vscode debugger 也有别的各种各样 ide 的 debugger。

nodejs 编码的调节

nodejs 能够根据加上 --inspect 的 option 来做调节(还可以是 --inspect-brk,这一会在第一行会断住)。

它会起一个 debugger 的 websocket 服务器端,大家可以用 vscode 来调节 nodejs 编码,还可以用 chrome devtools 来调节(见 nodejs debugger 文本文档)。

? node --inspect test.js

Debugger listening on ws://127.0.0.1:9229/db309268-623a-4abe-b19a-c4407ed8998d

For help see https://nodejs.org/en/docs/inspector

基本原理便是完成了 v8 debug protocol。

大家假如自己做调节专用工具、做 ide,那就需要连接这一协议书。

debugger adaptor protocol

上边详细介绍的 v8 debug protocol 能够完成 js 编码的调节,那麼 python、c# 等毫无疑问也是有自身的调节协议书,假如要完成 ide,都需要连接一遍太过不便。因此 之后发生了一个内层协议书,DAP(debugger adaptor protocol)。

debugger adaptor protocol, 说白了,便是兼容的,一端兼容各种各样 debugger 协议书,一端出示给手机客户端统一的协议书。它是适配器模式的一个非常好的运用。

照片

汇总

文中大家学了 debugger 的完成基本原理和显现出的调节协议书。

最先大家了解了编码二种运作方法:立即实行和表述实行,随后剖析了下为何必须 debugger。

以后探寻了立即实行的编码根据 INT 3 的终断的方法来完成 debugger 和解释型语言自身完成的 debugger。

随后 debugger 的工作能力会根据 socket 曝露给手机客户端,出示调节协议书,例如 v8 debug protocol,各种各样手机客户端包含 chrome devtools、ide 等都完成了这一协议书。

可是每一种语言表达都需要完成一次得话太过不便,因此 之后发生了一个兼容层协议书,屏蔽掉不一样协议书的差别,出示统一的协议书插口给手机客户端用。

期待本文可以使你了解 debugger 的基本原理,假如要完成调节专用工具也了解如何该如何去连接协议书。可以了解 chrome devtools、vscode 为什么都能够调节 nodejs 编码。

the end
免责声明:本文不代表本站的观点和立场,如有侵权请联系本站删除!本站仅提供信息存储空间服务。