UNPKG

trbr

Version:

TraceBreaker is a simple tool to decode and analyze ESP backtraces

2 lines 31.6 kB
(()=>{"use strict";var t={1421:t=>{t.exports=require("node:child_process")},1455:t=>{t.exports=require("node:fs/promises")},2018:t=>{t.exports=require("tty")},2872:(t,e,r)=>{r.d(e,{j:()=>s,x:()=>o});var n=r(7121);function o(t){return"coredumpMode"in t&&Boolean(t.coredumpMode)}async function s(t){let e,r;if(function(t){return"toolPath"in t&&"string"==typeof t.toolPath}(t))e=t.toolPath,r=t.targetArch??n.Br;else if(function(t){return"buildProperties"in t&&"object"==typeof t.buildProperties}(t))e=await(0,n.mv)(t),r=(0,n.bU)(t);else{if(!function(t){return"arduinoCliPath"in t&&"string"==typeof t.arduinoCliPath}(t))throw new Error(`Unexpected create decode params input: ${JSON.stringify(t)}`);{const o=await(0,n.ol)(t);e=await(0,n.mv)({fqbn:t.fqbn,buildProperties:o}),r=(0,n.bU)({buildProperties:o})}}const s={elfPath:t.elfPath,toolPath:e,targetArch:r};return o(t)?{...s,coredumpMode:!0}:s}},3281:(t,e,r)=>{function n(t){return`${t}${"win32"===process.platform?".exe":""}`}r.d(e,{c:()=>n})},6217:(t,e,r)=>{r.d(e,{tI:()=>M,D4:()=>D,Br:()=>F,M4:()=>_,aV:()=>q,jp:()=>G});var n=r(1455),o=r(8161),s=r(6760),i=r(6466),a=r(8057),c=r(1421);function d(t){return t.split(/\r?\n/).map((t=>t.trim())).filter(Boolean).map((t=>function(t){const e=[/#\d+\s+(0x[0-9a-f]+)\s+in\s+([^(]+\((?:"(?:\\.|[^"\\])*"|[^()])*?\))\s+at\s+(.+):(\d+)/i,/(0x[0-9a-f]+)\s+in\s+([^(]+(?:\([^()]*\))?)\s+at\s+(.+):(\d+)/i,/(?:#\d+\s+)?(0x[0-9a-f]+)\s+in\s+([^(]+(?:\([^()]*\))?)\s+at\s+(\?+):(\?+)/i,/(0x[0-9a-f]+)\s+is\s+in\s+([^(]+(?:\([^()]*\))?)\s+\((.+):(\d+)\)/i,/(0x[0-9a-f]+)\s+is\s+in\s+([^(]+(?:\([^()]*\))?)\s+\(([^():]+)\)/i,/(0x[0-9a-f]+)\s+is\s+at\s+(.+):(\d+)/i,/(?:#\d+\s+)?([^(]+(?:\([^()]*\))?)\s+at\s+(.+):(\d+)/];for(const[r,n]of e.entries()){const e=t.match(n);if(e){if(0===r||1===r){const[,t,r,n,o]=e;return l({regAddr:t,method:r,file:n,lineNumber:o})}if(2===r){const[,t,r,n,o]=e;return l({regAddr:t,method:r,file:n,lineNumber:o})}if(3===r){const[,t,r,n,o]=e;return l({regAddr:t,method:r,file:n,lineNumber:o})}if(4===r){const[,t,r,n]=e;return l({regAddr:t,method:r,file:n,lineNumber:"??"})}if(5===r){const[,t,r,n]=e;return l({regAddr:t,method:"??",file:r,lineNumber:n})}if(6===r){const[,t,r,n]=e;return l({regAddr:"??",method:t,file:r,lineNumber:n})}}}const r=t.match(/(?:#\d+\s+)?(0x[0-9a-f]+)\s+(?:is\s+in|in)\s+([^(]+(?:\([^()]*\))?)/i);if(r){const[,t,e]=r;return l({regAddr:t,method:e.trim(),file:"??",lineNumber:"??"})}}(t))).filter(q||G)}function l(t){const{file:e,lineNumber:r,method:n,regAddr:o}=t,s=function(t){const e=t.match(/^([^(]+)\s*\((.*)\)$/s);if(!e)return{name:t.trim(),args:[]};const[,r,n]=e,o=n.match(/(?:[^,"']+|"[^"]*"|'[^']*')+/g)?.map((t=>{const e=t.split("=");if(2===e.length){const[t,r]=e.map((t=>t.trim()));return{name:t,value:r}}return{name:t.trim()}}))||[];return{name:r.trim(),args:o}}(n),i=e&&""!==e&&"??"!==e,a=r&&""!==r&&"??"!==r;if(i||a){const t={regAddr:o,method:s.name,file:i?e:"??",lineNumber:a?r:"??"};return s.args&&s.args.length>0&&Object.assign(t,{args:s.args}),t}const c=s.name&&""!==s.name&&"??"!==s.name&&"?? ()"!==s.name;return!a&&c?{regAddr:o,lineNumber:s.name}:{regAddr:o,lineNumber:r||"??"}}function u(t=0){return`0x${t.toString(16).padStart(8,"0")}`}const f="(gdb)";class h{constructor({toolPath:t,elfPath:e},r={}){this.toolPath=t,this.elfPath=e,this.error=null,this.didExecuteFirstCommand=!1,this.gdb=(0,c.spawn)(t,[e],{stdio:"pipe",signal:r.signal}),this.buffer="",this.queue=[],this.current=null,this.gdb.stdout.on("data",(t=>this._onData(t))),this.gdb.stderr.on("data",(t=>this._onData(t))),this.gdb.on("error",(t=>this.current?.reject(t))),this.gdb.on("exit",((t,e)=>{0!==t&&"SIGTERM"!==e&&console.warn(`GDB exited with code ${t} or signal ${e}`)}))}_onData(t){if(this.buffer+=t.toString(),!this.current)return;const e=this.buffer.indexOf(f);if(-1===e)return;const r=this.buffer.slice(0,e);this.buffer=this.buffer.slice(e+5);const{resolve:n}=this.current;this.current=null,n(r),this._processQueue()}_processQueue(){const t=this.queue.shift();if(this.current||!t)return;const{cmd:e,resolve:r,reject:n}=t;this.current={resolve:r,reject:n},this.gdb.stdin.write(e+"\n")}start(){return new Promise(((t,e)=>{const r=r=>{if(!this.didExecuteFirstCommand&&this.buffer.includes("No such file or directory"))return void(this.error||(this.error=new Error(`The ELF file does not exist or is not readable: ${this.elfPath}`),e(this.error)));if(!this.didExecuteFirstCommand&&(this.buffer.includes("not in executable format")||this.buffer.includes("file format not recognized")))return void(this.error||(this.error=new Error(`The ELF file is not in executable format: ${this.elfPath}`),e(this.error)));this.buffer+=r.toString();const n=this.buffer.indexOf(f);-1!==n&&(this.buffer=this.buffer.slice(n+5),t(""))};this.gdb.on("error",(t=>{let r=t;t instanceof Error&&"code"in t&&"ENOENT"===t.code&&(r=new Error(`GDB tool not found at ${this.toolPath}`)),e(r)})),this.gdb.stdout.on("data",r),this.gdb.stderr.on("data",r)}))}async exec(t){if(this.error)return this.close(),Promise.reject(this.error);const e=await new Promise(((e,r)=>{this.queue.push({cmd:t,resolve:e,reject:r}),this._processQueue()}));return this.didExecuteFirstCommand=!0,e}async close(){this.gdb.killed||(this.gdb.stdin.end(),this.gdb.kill("SIGTERM"),"number"!=typeof this.gdb.exitCode&&await new Promise((t=>this.gdb.once("exit",t))))}}async function p({elfPath:t,toolPath:e},r,n={}){const o=function(t){const e=new Set;for(const r of t){let t;"object"==typeof r?t=r.addr:"number"==typeof r&&(t=r),void 0===t||e.has(t)||e.add(t)}return Array.from(e.values())}(r);if(!o.length)throw new Error("No register addresses found to decode");const s=new Map,i=new h({elfPath:t,toolPath:e},n);try{await i.start(),await i.exec("set pagination off"),await i.exec("set listsize 1");for(const t of o){const e=u(t);let r=d(await i.exec(`list *${e}`)),n=r.find(G);n||(r=d(await i.exec(`info line *${e}`)),n=r.find(G)),s.set(t,{addr:t,location:n??{regAddr:e,lineNumber:"??"}})}}finally{await i.close()}return r.map((t=>{const e="object"==typeof t?t.addr:t;return s.get(e)||{location:"??"}}))}class g{constructor(t,e,r={}){this.cp=c.spawn(t,e,{stdio:"pipe",signal:r.signal}),this.error=void 0,this.commandQueue=[],this.signal=r.signal,this.signal&&this.signal.addEventListener("abort",(()=>{const t=new a.l;this.error=t,this.commandQueue.forEach((e=>e.reject(t))),this.commandQueue=[]})),this.stdoutBuffer="",this.cp.stdout.on("data",(t=>this._onData(t))),this.cp.stderr.on("data",(t=>this._onData(t))),this.cp.on("error",(t=>{this.error=t,this.commandQueue.forEach((e=>e.reject(t))),this.commandQueue=[]}))}sendCommand(t){return this.error?Promise.reject(this.error):new Promise(((e,r)=>{const n={resolve:e,reject:r};this.commandQueue.push(n),this.cp.stdin.write(`${t}\n`)}))}_onData(t){if(this.error&&(this.commandQueue.forEach((t=>t.reject(this.error))),this.commandQueue=[]),this.stdoutBuffer+=t.toString(),/\(gdb\)\s*$/m.test(this.stdoutBuffer)){const t=this.stdoutBuffer;this.stdoutBuffer="";const e=this.commandQueue.shift();e?.resolve(t)}}close(){this.cp.stdin.end(),this.cp.kill()}async drainHandshake(){return new Promise(((t,e)=>{const r=o=>{if(this.error)return this.cp.stdout.off("data",r),void e(this.error);this.stdoutBuffer+=o.toString(),/\(gdb\)\s*$/m.test(this.stdoutBuffer)&&(this.cp.stdout.off("data",r),this.signal&&this.signal.removeEventListener("abort",n),this.stdoutBuffer="",t())},n=()=>{this.cp.stdout.off("data",r),this.signal?.removeEventListener("abort",n),e(new a.l)};this.cp.stdout.on("data",r),this.signal?.addEventListener("abort",n)}))}}function m(t){const e={},r=t.match(/(?:frame=\{[^}]*\},)?register-values=\[([^\]]*)\]/);if(r){const t=r[1],n=/\{number="(\d+)",value="(0x[a-fA-F0-9]+)"\}/g;for(const r of t.matchAll(n))e[r[1]]=r[2];return e}const n=t.split(/\r?\n/);for(const t of n){const r=t.match(/^~?"?(\w+)\s+(0x[a-fA-F0-9]+)\b/);if(r){const[,t,n]=r;e[t]=n}}return e}async function b(t,e,r={},i=!0){const{elfPath:a,toolPath:c}=t,{inputPath:d}=e,l=new g(c,["--interpreter=mi2","-c",d,a],r),f=[];try{await l.drainHandshake();const t=await l.sendCommand("-thread-info"),e=t.match(/current-thread-id="(\d+)"/),r=e?e[1]:null,n=function(t){const e=t.indexOf("threads=[");if(e<0)return;const r=t.indexOf("[",e);if(r<0)return;let n=0;for(let e=r;e<t.length;e++){const o=t[e];if("["===o)n++;else if("]"===o&&(n--,0===n))return t.substring(r+1,e)}}(t),o=[];if(n){const t=[];let e=0,r=-1;for(let o=0;o<n.length;o++){const s=n[o];"{"===s?(0===e&&(r=o),e++):"}"===s&&(e--,0===e&&r>=0&&t.push(n.slice(r,o+1)))}for(const e of t){const t=/id="([^"]+)"\s*,\s*target-id="process\s+(\d+)"/.exec(e);t&&o.push([t[1],t[2]])}}const s=o.map((([t])=>t)),i=Object.fromEntries(o.map((([t,e])=>[t,Number(e)])));for(const t of s){await l.sendCommand(`-thread-select ${t}`);const e=(await l.sendCommand("-data-list-register-names")).match(/register-names=\[(.*?)\]/),n=e?e[1].split(",").map((t=>t.trim().replace(/^"|"$/g,""))).map(((t,e)=>[e.toString(),t])).filter((([,t])=>!!t)):[],o=Object.fromEntries(n),s=m(await l.sendCommand("-data-list-register-values x")),a=Object.fromEntries(Object.entries(s).map((([t,e])=>[o[t],Number(e)])).filter((([t])=>!!t))),c=a.pc,d=await l.sendCommand("-stack-list-frames"),h=(await l.sendCommand("-stack-list-arguments --simple-values 0 100")).match(/stack-args=\[([\s\S]*)\]/);let p=[];if(h){const t=h[1].split(/},\s*frame=\{/).map(((t,e)=>0===e?t+"}":"frame={"+t+"}"));p=t.map((t=>{const e=t.match(/frame=\{([\s\S]*)\}/),r=e?e[1]:"",n={args:[]},o=r.match(/level="(\d+)"/);o&&(n.level=o[1]);const s=r.match(/args=\[([\s\S]*)\]/);if(s&&s[1].trim()){const t=s[1],e=/\{name="([^"]+)",type="([^"]+)",value="([^"]+)"\}/g;let r;for(;r=e.exec(t);)n.args.push({name:r[1],type:r[2],value:r[3]})}return n}))}else p=[];const g=[...d.matchAll(/frame=\{([^}]+)\}/g)].map((t=>{const e={};for(const r of t[1].split(",")){const[t,n]=r.split("=");e[t]=n?.startsWith('"')?n.slice(1,-1):n}return e})).map(((t,e)=>{const r=p[e]?.args||"";return{regAddr:t.addr,lineNumber:t.line??"??",...t.func&&t.file?{method:t.func,file:t.file,args:r}:{}}}));f.push({threadId:t,TCB:i[t],result:{faultInfo:{coreId:parseInt(t),programCounter:{addr:c,location:g[0]??{regAddr:u(c),lineNumber:"??"}},faultCode:void 0},regs:a,stacktraceLines:g},current:t===r})}}finally{l.close()}if(!f.length&&i){const r=await n.readFile(e.inputPath),i=await async function(t,e){const r=Buffer.from([127,69,76,70]),i=e.indexOf(r);if(-1!==i){const r=e.readUInt32LE(i+28),a=e.readUInt16LE(i+42),c=e.readUInt16LE(i+44),d=(()=>{let t=0;for(let n=0;n<c;n++){const o=i+r+n*a,s=e.readUInt32LE(o+4)+e.readUInt32LE(o+16);s>t&&(t=s)}return t})();if(e.length>=i+d){const r=e.subarray(i,i+d),a=await n.mkdtemp(s.join(o.tmpdir(),"trbr-")),c=s.join(a,"extracted.elf");await n.writeFile(c,r);try{return await b({...t},{inputPath:c},void 0,!1)}finally{await n.rm(a,{recursive:!0,force:!0}).catch((t=>console.warn("Failed to clean up temp dir:",t)))}}}}(t,r);if(i)return i}return f}const w={unsupportedTargetArch:t=>`Unsupported decode target: ${t}`};var A=r(2872);const y=require("node:net");var v=r(6342),C=r(7121);const I=["X0","RA","SP","GP","TP","T0","T1","T2","S0/FP","S1","A0","A1","A2","A3","A4","A5","A6","A7","S2","S3","S4","S5","S6","S7","S8","S9","S10","S11","T3","T4","T5","T6","MEPC"],S={esp32c2:L,esp32c3:L,esp32c6:L,esp32h2:L,esp32h4:L,esp32p4:L},P={esp32c2:I,esp32c3:I,esp32c6:I,esp32h2:I,esp32h4:I,esp32p4:I};function E({input:t,target:e}){const{regDumps:r,stackDump:n,programCounter:o,faultAddr:s,faultCode:i}=function({input:t,target:e}){const r=t.split(/\r?\n|\r/),n=[],o=[];let s,i,a,c=!1,d=0;const l=function(t){const e=P[t];if(!e)throw new Error(`Unsupported target: ${t}`);return t=>e.includes(t)}(e);return r.forEach((t=>{if(t.startsWith("Core")){const e=t.match(/^Core\s+(\d+)\s+register dump:/);e&&(s={coreId:parseInt(e[1],10),regs:{}},n.push(s))}else if(s&&!c){const e=t.matchAll(/([A-Z_0-9/]+)\s*:\s*(0x[0-9a-fA-F]+)/g);for(const t of e){const e=t[1],r=parseInt(t[2],16);r&&l(e)?(s.regs[e]=r,"MEPC"===e&&(d=r)):"MCAUSE"===e?i=r:"MTVAL"===e&&(a=r)}"Stack memory:"===t.trim()&&(c=!0)}else if(c){const e=t.match(/^([0-9a-fA-F]+):\s*((?:0x[0-9a-fA-F]+\s*)+)/);if(e){const t=parseInt(e[1],16),r=e[2].trim().split(/\s+/).map((t=>parseInt(t,16)));o.push({baseAddr:t,data:r})}}})),{regDumps:n,stackDump:o,faultCode:i,faultAddr:a,programCounter:d}}({input:t,target:e});if(0===r.length)throw new Error("No register dumps found");if(r.length>1)throw new Error("Handling of multi-core register dumps not implemented");const{coreId:a,regs:c}=r[0],{stackBaseAddr:d,stackData:l}=function({stackDump:t}){let e=0,r=0,n=0,o=Buffer.alloc(0);return t.forEach((t=>{const s=r;if(r=t.baseAddr,0===e)e=r;else if(r!==s+n)throw new Error("Invalid base address");const i=Buffer.concat(t.data.map((t=>Buffer.from(t.toString(16).padStart(8,"0"),"hex"))));n=i.length,o=Buffer.concat([o,i])})),{stackBaseAddr:e,stackData:o}}({stackDump:n});return{coreId:a,programCounter:o,faultAddr:s,faultCode:i,regs:c,stackBaseAddr:d,stackData:l,target:e}}class ${constructor(t){this.panicInfo=t.panicInfo,this.regList=P[t.panicInfo.target],this.debug=t.debug??(()=>{})}async start(t={}){if(this.server)throw new Error("Server already started");const{signal:e=a.$}=t,r=y.createServer();this.server=r,await new Promise(((t,n)=>{const o=()=>{this.debug("User abort"),n(new a.l),this.close()};e.aborted?o():(e.addEventListener("abort",o),r.on("listening",(()=>{e.removeEventListener("abort",o),t(void 0)})),r.listen(0))}));const n=r.address();if(!n)throw this.close(),new Error("Failed to start server");if("string"==typeof n)throw this.close(),new Error(`Expected an address info object. Got a string: ${n}`);return r.on("connection",(t=>{t.on("data",(e=>{const r=e.toString();if(r.startsWith("-"))return this.debug(`Invalid command: ${r}`),t.write("-"),void t.end();r.length>3&&"#"===r.slice(-3,-2)&&(this.debug(`Command: ${r}`),this._handleCommand(r,t))}))})),n}close(){this.server?.close(),this.server=void 0}_handleCommand(t,e){t.startsWith("+")&&(t=t.slice(1));const r=t.slice(1,-3);if(e.write("+"),this.debug(`Raw buffer (length ${t.length}): ${JSON.stringify(t)}`),this.debug(`Got command: ${r}`),"?"===r)this.debug("Responding with: T05"),this._respond("T05",e);else if(r.startsWith("Hg")||r.startsWith("Hc"))this.debug("Responding with: OK"),this._respond("OK",e);else if("qfThreadInfo"===r)this.debug("Responding with: m1"),this._respond("m1",e);else if("qC"===r)this.debug("Responding with: QC1"),this._respond("QC1",e);else if("g"===r)this._respondRegs(e);else if(r.startsWith("m")){const[t,n]=r.slice(1).split(",").map((t=>parseInt(t,16)));this._respondMem(t,n,e)}else r.startsWith("vKill")||"k"===r?(this.debug("Responding with: OK"),this._respond("OK",e),e.end()):(this.debug("Responding with: (empty)"),this._respond("",e))}_respond(t,e){const r=`$${t}#${(255&Buffer.from(t,"ascii").reduce(((t,e)=>t+e),0)).toString(16).padStart(2,"0")}`;e.write(r),this.debug(`Wrote: ${r}`)}_respondRegs(t){let e="";for(const t of this.regList){const r=this.panicInfo.regs[t]||0,n=Buffer.alloc(4);n.writeUInt32LE(r),e+=n.toString("hex")}this.debug(`Register values: ${this.regList.map((t=>`${t}=${u(this.panicInfo.regs[t]||0)}`)).join(", ")}`),this.debug(`Register response: ${e}`),this._respond(e,t)}_respondMem(t,e,r){const n=this.panicInfo.stackBaseAddr,o=this.panicInfo.stackData,s=o.length,i=n+s,a=t=>n<=t&&t<i;let c="";for(let r=t;r<t+e;r++)a(r)?c+=o[r-n].toString(16).padStart(2,"0"):c+="00";this.debug(`Memory read request from 0x${t.toString(16)} for ${e} bytes`),this.debug(`Responding with memory: ${c}`),this._respond(c,r)}}const x=[{code:0,description:"Instruction address misaligned"},{code:1,description:"Instruction access fault"},{code:2,description:"Illegal instruction"},{code:3,description:"Breakpoint"},{code:4,description:"Load address misaligned"},{code:5,description:"Load access fault"},{code:6,description:"Store/AMO address misaligned"},{code:7,description:"Store/AMO access fault"},{code:8,description:"Environment call from U-mode"},{code:9,description:"Environment call from S-mode"},{code:11,description:"Environment call from M-mode"},{code:12,description:"Instruction page fault"},{code:13,description:"Load page fault"},{code:15,description:"Store/AMO page fault"}];async function B(t,e,r={}){const{elfPath:n,toolPath:o}=t;let s;try{const{signal:t,debug:i}=r,a=new $({panicInfo:e,debug:i}),{port:c}=await a.start({signal:t});s=a;const d=function(t,e){return["--batch","-n",t,"-ex",`target remote :${e}`,"-ex","bt"]}(n,c),{stdout:l}=await(0,v.m)(o,d,{signal:t});return l}finally{s?.close()}}async function L(t,e,r){const n=t.targetArch;if(!(0,C.Hx)(n))throw new Error(`Unsupported target: ${n}`);let o;if(o="string"==typeof e?E({input:e,target:n}):e,"backtraceAddrs"in o)throw new Error("Unexpectedly received a panic info with backtrace addresses for RISC-V");const[s,[i,a]]=await Promise.all([B(t,o,r),p(t,[o.programCounter,o.faultAddr],r)]);return function(t,e,r,n){const o=x.find((e=>e.code===t.faultCode)),s=d(n);return{faultInfo:{coreId:t.coreId,programCounter:e,faultAddr:r,faultCode:t.faultCode,faultMessage:o?o.description:void 0},regs:t.regs,stacktraceLines:s,allocInfo:void 0}}(o,i,a,s)}const O="reserved",N=["Illegal instruction","SYSCALL instruction","InstructionFetchError: Processor internal physical address or data error during instruction fetch","LoadStoreError: Processor internal physical address or data error during load or store","Level1Interrupt: Level-1 interrupt as indicated by set level-1 bits in the INTERRUPT register","Alloca: MOVSP instruction, if caller's registers are not in the register file","IntegerDivideByZero: QUOS, QUOU, REMS, or REMU divisor operand is zero",O,"Privileged: Attempt to execute a privileged operation when CRING ? 0","LoadStoreAlignmentCause: Load or store to an unaligned address",O,O,"InstrPIFDataError: PIF data error during instruction fetch","LoadStorePIFDataError: Synchronous PIF data error during LoadStore access","InstrPIFAddrError: PIF address error during instruction fetch","LoadStorePIFAddrError: Synchronous PIF address error during LoadStore access","InstTLBMiss: Error during Instruction TLB refill","InstTLBMultiHit: Multiple instruction TLB entries matched","InstFetchPrivilege: An instruction fetch referenced a virtual address at a ring level less than CRING",O,"InstFetchProhibited: An instruction fetch referenced a page mapped with an attribute that does not permit instruction fetch",O,O,O,"LoadStoreTLBMiss: Error during TLB refill for a load or store","LoadStoreTLBMultiHit: Multiple TLB entries matched for a load or store","LoadStorePrivilege: A load or store referenced a virtual address at a ring level less than CRING",O,"LoadProhibited: A load referenced a page mapped with an attribute that does not permit loads","StoreProhibited: A store referenced a page mapped with an attribute that does not permit stores"];function k(t){if(!t)return;const e=parseInt(q(t)?t.regAddr:t??"0",16);return isNaN(e)?void 0:e}function R(t){return null!==t&&"object"==typeof t&&"inputPath"in t&&"string"==typeof t.inputPath}function T(t){return null!==t&&"object"==typeof t&&"inputStream"in t&&t.inputStream instanceof require("stream").Readable}const F="xtensa",j={[F]:async function(t,e,r){let n;if("string"==typeof e?(n=function(t){const e=t.split(/\r?\n|\r/),r={};let n=0;const o=[],s=t.match(/Guru Meditation Error: Core\s+(\d+)/);s&&(n=parseInt(s[1],10));const i=/([A-Z]+[0-9]*)\s*:\s*(0x[0-9a-fA-F]+)/g;for(const t of e){for(const e of t.matchAll(i)){const[,t,n]=e,o=parseInt(n,16);Number.isNaN(o)||(r[t]=o)}if(t.startsWith("Backtrace:")){const e=Array.from(t.matchAll(/0x[0-9a-fA-F]{8}/g));for(const t of e){const e=parseInt(t[0],16);Number.isNaN(e)||o.push(e)}}}return{coreId:n,regs:r,backtraceAddrs:o,faultCode:r.EXCCAUSE,faultAddr:r.EXCVADDR,programCounter:r.PC}}(e),Object.keys(n.regs).length||n.backtraceAddrs.length||(n=function(t){const e=t.split(/\r?\n|\r/),r={},n=[];let o,s;const i=t.match(/Exception\s+\((\d+)\)/);i&&(o=parseInt(i[1],10));for(const t of e){const e=t.matchAll(/(epc\d+|excvaddr|depc)=(0x[0-9a-fA-F]{8})/g);for(const t of e){const[,e,n]=t;r[e.toUpperCase()]=parseInt(n,16),"excvaddr"===e.toLowerCase()&&(s=parseInt(n,16))}const o=t.match(/^\s*[0-9a-f]{8}:\s+((?:[0-9a-f]{8}\s*)+)/i);if(o){const t=o[1].trim().split(/\s+/);for(const e of t){const t=parseInt(e,16);!Number.isNaN(t)&&1073741824&t&&n.push(t)}}}return{coreId:0,regs:r,backtraceAddrs:n,faultCode:o,faultAddr:s,programCounter:r.EPC1}}(e))):n=e,"stackBaseAddr"in n)throw console.error("input contains stackBaseAddr",JSON.stringify(n)),new Error("panicInfo must not contain stackBaseAddr");const[o,s,...i]=await p(t,[n.programCounter,n.faultAddr,...n.backtraceAddrs??[]],r);let a;return n.faultCode&&(a=N[n.faultCode]),{faultInfo:{coreId:n.coreId,programCounter:o,faultAddr:s,faultCode:n.faultCode,faultMessage:a},regs:n.regs,stacktraceLines:i.map((({location:t})=>t)).filter(q),allocInfo:void 0}},...S},M=Object.keys(j);function _(t){return"string"==typeof t&&t in j}async function D(t,e,r={debug:()=>{},signal:(new AbortController).signal}){const c=[];try{if((0,A.x)(t)){let a;if(R(e))a=e.inputPath;else if(T(e)){const t=await n.mkdtemp(s.join(o.tmpdir(),"trbr-"));a=s.join(t,"coredump.elf"),c.push((async()=>{try{await n.rm(t,{recursive:!0,force:!0})}catch(t){console.error("Failed to delete temporary coredump directory:",t)}}));const r=await n.open(a,"w");let d;try{d=r.createWriteStream(),await(0,i.pipeline)(e.inputStream,d)}finally{Promise.allSettled([r.close(),new Promise(((t,e)=>d?.close((r=>{r?e(r):t(void 0)}))))]).then((t=>t.forEach((t=>{"rejected"===t.status&&console.error("Failed to close stream:",t.reason)}))))}}if(!a)throw new Error(`Could not determine coredump path from input: ${JSON.stringify(e)}`);return(await b(t,{inputPath:a},r)).map((t=>({...t,...U(t.result)})))}const{targetArch:d}=t,l=j[d];if(!l)throw new Error(w.unsupportedTargetArch(d));let u;if("string"==typeof e)u=e;else if(R(e))u=await n.readFile(e.inputPath,"utf8");else if(T(e)){u="";for await(const t of e.inputStream)u=t.toString()}else u=e;const f=U(await l(t,u,r));if(r.signal?.aborted)throw new a.l;return f}catch(t){if(t instanceof Error&&"code"in t&&"ABORT_ERR"===t.code)throw new a.l;throw t}finally{for(const t of c)try{await t()}catch(t){console.error("Failed to dispose resource:",t)}}}function U(t){let e=function(t){return{...t,stacktraceLines:t.stacktraceLines.filter((t=>!q(t)||"??"!==t.lineNumber||"0xfeefeffe"!==t.regAddr.toLowerCase()))}}(function(t){return{...t,faultInfo:t.faultInfo?{...t.faultInfo,programCounter:Q(t.faultInfo.programCounter),faultAddr:Q(t.faultInfo.faultAddr)}:void 0,stacktraceLines:t.stacktraceLines.map(Q),allocInfo:t.allocInfo?{...t.allocInfo,allocAddr:Q(t.allocInfo.allocAddr)}:void 0}}(t));e=function(t){return{...t,stacktraceLines:t.stacktraceLines.reduce(((t,e,r,n)=>{const o=n[r-1];return o&&function(t,e){if(!G(e))return!1;const r=k(e.regAddr),n=k(t.regAddr);if(void 0===n||void 0===r)return!1;const o=n>>>28==3,s=r>>>28==4;return"??"===t.lineNumber&&o&&s}(e,o)?t:[...t,e]}),[])}}(e);const r=function(t){if(t.faultInfo&&q(t.faultInfo.faultAddr?.location)&&"??"===t.faultInfo.faultAddr.location.lineNumber&&!t.faultInfo.faultAddr.addr){const e=JSON.parse(JSON.stringify(t));return delete e.faultInfo.faultAddr,e}return t}(e),n=function(t){return{...t,stacktraceLines:t.stacktraceLines.reduce(((t,e,r)=>{const n=t[r-1];return!n||(s=e,G(o=n)&&!G(s)||!G(o)&&G(s)||(G(o)&&G(s)?o.regAddr!==s.regAddr||o.lineNumber!==s.lineNumber||o.file!==s.file||o.method!==s.method:o.regAddr!==s.regAddr||o.lineNumber!==s.lineNumber))?[...t,e]:t;var o,s}),[])}}(r);return n}function q(t){return null!==t&&"object"==typeof t&&"regAddr"in t&&"string"==typeof t.regAddr&&"lineNumber"in t&&"string"==typeof t.lineNumber}function G(t){return q(t)&&"file"in t&&"string"==typeof t.file&&"method"in t&&"string"==typeof t.method}function Q(t){if(!t)return t;if(null!==(e=t)&&"object"==typeof e&&"addr"in e&&("number"==typeof e.addr||void 0===e.addr)&&"location"in e&&("string"==typeof e.location||q(e.location)||G(e.location))){const e=t.location;if(G(e)){const r=JSON.parse(JSON.stringify(t));return r.location.file=W(e.file),r}}var e;if(G(t)){const e=JSON.parse(JSON.stringify(t));return e.file=W(t.file),e}return t}function W(t){return"win32"===process.platform&&/^[a-zA-Z]:\\/.test(t)?t.replace(/\//g,"\\"):t}},6342:(t,e,r)=>{r.d(e,{m:()=>o});var n=r(1421);async function o(t,e=[],r={}){return new Promise(((o,s)=>{(0,n.execFile)(t,e,r,((t,e,r)=>{t?s(t):o({stdout:e.toString(),stderr:r.toString()})}))}))}},6466:t=>{t.exports=require("node:stream/promises")},6760:t=>{t.exports=require("node:path")},7121:(t,e,r)=>{r.d(e,{Br:()=>l,Hx:()=>u,bU:()=>h,mv:()=>y,ol:()=>c,xR:()=>a});var n=r(1455),o=r(6760),s=r(6342),i=r(3281);async function a({arduinoCliPath:t,fqbn:e,arduinoCliConfigPath:r,additionalUrls:n},o){return y({fqbn:e,buildProperties:await c({arduinoCliPath:t,fqbn:e,additionalUrls:n,arduinoCliConfigPath:r},o)})}async function c({arduinoCliPath:t,fqbn:e,arduinoCliConfigPath:r,additionalUrls:n},o){const{stdout:i}=await async function({fqbn:t,arduinoCliPath:e,arduinoCliConfigPath:r,additionalUrls:n,signal:o}){const i=["board","details","-b",t.toString(),"--format","json"];return r&&i.push("--config-file",r),n&&i.push("--additional-urls",n),(0,s.m)(e,i,{signal:o})}({arduinoCliPath:t,fqbn:e,arduinoCliConfigPath:r,additionalUrls:n,signal:o?.signal}),{build_properties:a}=JSON.parse(i);return a.reduce(((t,e)=>{const r=function(t){const e=t.split(v);if(e.length<2)return void console.warn(`Could not parse build property: ${t}.`);const[r,...n]=e;return r?[r,n.join(v)]:void console.warn(`Could not determine property key from raw: ${t}.`)}(e);if(r){const[e,n]=r;t[e]=n}return t}),{})}const d=["esp32c2","esp32c3","esp32c6","esp32h2","esp32h4","esp32p4"],l="xtensa";function u(t){return"string"==typeof t&&d.includes(t)}const f="build.mcu";function h({buildProperties:t}){const e=t[f];return u(e)?e:l}const p="esp32",g=new Set([p,"esp8266"]),m="xtensa",b="lx106",w="build.tarch",A="build.target";async function y({fqbn:t,buildProperties:e}){const{arch:r}=t;if(!g.has(r))throw new Error(`Unsupported board architecture: '${t}'`);let s=m,a=b;r===p&&(s=e[w]??m,a=e[A]??b);const c=`${s}-${a}-elf`,d=`${s}-esp-elf-gdb`,l=(0,i.c)(`${c}-gdb`);async function u(t){const r=e[t];if(r){const t=o.join(r,"bin",l);try{return await n.access(t),t}catch{}}}const f=`tools.${d}.path`,h=`tools.${c}-gcc.path`,y=(await Promise.all([u(`runtime.${f}`),u(`runtime.${h}`),u(f),u(h)])).find((t=>t));if(!y)throw new Error(`Could not find GDB tool for '${t}'`);return y}const v="="},8057:(t,e,r)=>{r.d(e,{$:()=>o,l:()=>n});class n extends Error{constructor(){super("User abort"),this.name="AbortError",this.code="ABORT_ERR"}}const o=(new AbortController).signal},8161:t=>{t.exports=require("node:os")}},e={};function r(n){var o=e[n];if(void 0!==o)return o.exports;var s=e[n]={exports:{}};return t[n](s,s.exports,r),s.exports}r.d=(t,e)=>{for(var n in e)r.o(e,n)&&!r.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},r.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})};var n={};r.r(n),r.d(n,{AbortError:()=>o.l,arches:()=>s.tI,createDecodeParams:()=>i.j,decode:()=>s.D4,defaultTargetArch:()=>s.Br,findTargetArch:()=>A.bU,findToolPath:()=>A.xR,isDecodeTarget:()=>s.M4,isGDBLine:()=>s.aV,isParsedGDBLine:()=>s.jp,isRiscvTargetArch:()=>A.Hx,resolveToolPath:()=>A.mv,stringifyDecodeResult:()=>p});var o=r(8057),s=r(6217),i=r(2872),a=Object.entries({reset:[0,0],bold:[1,22,""],dim:[2,22,""],italic:[3,23],underline:[4,24],inverse:[7,27],hidden:[8,28],strikethrough:[9,29],black:[30,39],red:[31,39],green:[32,39],yellow:[33,39],blue:[34,39],magenta:[35,39],cyan:[36,39],white:[37,39],gray:[90,39],bgBlack:[40,49],bgRed:[41,49],bgGreen:[42,49],bgYellow:[43,49],bgBlue:[44,49],bgMagenta:[45,49],bgCyan:[46,49],bgWhite:[47,49],blackBright:[90,39],redBright:[91,39],greenBright:[92,39],yellowBright:[93,39],blueBright:[94,39],magentaBright:[95,39],cyanBright:[96,39],whiteBright:[97,39],bgBlackBright:[100,49],bgRedBright:[101,49],bgGreenBright:[102,49],bgYellowBright:[103,49],bgBlueBright:[104,49],bgMagentaBright:[105,49],bgCyanBright:[106,49],bgWhiteBright:[107,49]});function c(t){return String(t)}function d(t=!1){let e=function(t=!1){let e="undefined"!=typeof process?process:void 0,r=(null==e?void 0:e.env)||{},n=(null==e?void 0:e.argv)||[];return!("NO_COLOR"in r||n.includes("--no-color"))&&("FORCE_COLOR"in r||n.includes("--color")||"win32"===(null==e?void 0:e.platform)||t&&"dumb"!==r.TERM||"CI"in r)||"undefined"!=typeof window&&!!window.chrome}(t),r=(t,e,r=t)=>{let n=n=>{let o=String(n),s=o.indexOf(e,t.length);return~s?t+((t,e,r,n)=>{let o="",s=0;do{o+=t.substring(s,n)+r,s=n+e.length,n=t.indexOf(e,s)}while(~n);return o+t.substring(s)})(o,e,r,s)+e:t+o+e};return n.open=t,n.close=e,n},n={isColorSupported:e},o=t=>`[${t}m`;for(let[t,s]of a)n[t]=e?r(o(s[0]),o(s[1]),s[2]):c;return n}c.open="",c.close="";var l=r(2018),u=void 0!==process.env.FORCE_TTY||(0,l.isatty)(1),f=d(u);const h={forceColor:!1,lineSeparator:"\r\n"};function p(t,e=h){e={...h,...e};const{colorizeFn:r,resetColor:n}=function(t){const e=(t,e,r)=>(n,o)=>{switch(o){case"red":return t(n);case"green":return e(n);case"blue":return r(n);default:return n}};let r=()=>{};if("disable"===t.color)return{colorizeFn:t=>t,resetColor:r};if("force"===t.color){process.env.FORCE_COLOR||(process.env.FORCE_COLOR="1",r=()=>{delete process.env.FORCE_COLOR});const{red:t,green:n,blue:o}=d(u);return{colorizeFn:e(t,n,o),resetColor:r}}const{red:n,green:o,blue:s}=f;return{colorizeFn:e(n,o,s),resetColor:r}}(e);try{const n=Array.isArray(t)?function(t,e){const r=[...g(t,e),""];for(let n=0;n<t.length;n++){const o=t[n];r.push(m(o),...b(o,e)),n<t.length-1&&r.push("")}return r}(t,r):function(t,e){const r=[];if("number"==typeof t.faultInfo?.faultCode){let n=`${t.faultInfo.coreId}`;t.faultInfo.faultMessage&&(n+=` | ${t.faultInfo.faultMessage}`),n+=` | ${t.faultInfo.faultCode}`,r.push(e(n,"red"))}const n=t.faultInfo?.programCounter.location;n&&(r.length&&r.push(""),r.push(`${e("PC -> ","red")}${w(n,e)}`));const o=t.faultInfo?.faultAddr?.location;o&&r.push(`${e("Fault -> ","red")}${w(o,e)}`),t.stacktraceLines.length&&r.length&&r.push("");for(const n of t.stacktraceLines)r.push(w(n,e));return t.allocInfo&&(r.length&&r.push(""),r.push(`${e(`Memory allocation of ${t.allocInfo.allocSize} bytes failed`,"red")}${e(" at ")}${w(t.allocInfo.allocAddr,e)}`)),r}(t,r);return n.join(e.lineSeparator)}finally{n()}}function g(t,e){const r=[];r.push("==================== THREADS INFO ===================="),r.push(" ID Target ID Frame");for(const n of t){const t=n.current?"*":" ",o=n.threadId.toString().padStart(2),s=n.TCB.toString().padEnd(12),i=n.result.stacktraceLines?.[0];r.push(` ${t}${o} process ${s} ${w(i,e)}`)}return r}function m(t){return`==================== THREAD ${t.threadId} (TCB: 0x${(+t.TCB).toString(16)}) ====================`}function b(t,e){return t.result.stacktraceLines.map((t=>w(t,e)))}function w(t,e){if("string"==typeof t)return e(t);if(!(0,s.jp)(t))return`${e(t.regAddr,"green")}${e(`: ${t.lineNumber}`)}`;const r=t.args?.map((t=>`${t.name}${t.value?`=${t.value}`:""}`)).join(", ")??"",n=`${t.method} (${r})`;return`${e(t.regAddr,"green")}${e(": ")}${e(n,"blue")}${e(` at ${t.file}:${t.lineNumber}`)}`}var A=r(7121);module.exports=n})(); //# sourceMappingURL=lib.cjs.map