FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

feat(coredump): crash-dump inspection component + WebUSB/Web Serial inspector webapp by finger563 · Pull Request #743 · esp-cpp/espp · GitHub

/ espp Public

feat(coredump): crash-dump inspection component + WebUSB/Web Serial inspector webapp - #743

Open
finger563 wants to merge 9 commits into
mainfrom
feat/coredump-component
Open

feat(coredump): crash-dump inspection component + WebUSB/Web Serial inspector webapp#743
finger563 wants to merge 9 commits into
mainfrom
feat/coredump-component

Conversation

Copy link
Copy Markdown
Contributor

Summary

New coredump component: post-mortem crash inspection over USB (WebUSB vendor or CDC/Web Serial) with a self-contained browser inspector. Generalizes the crash reporting added to the bldc_haptics example (#742).

  • espp::CoreDump (header-only, BaseComponent): has_core_dump(), summary(), format_report() — reset reason, panic reason, crashed task + PC, raw backtrace with the right addr2line toolchain prefix per CONFIG_IDF_TARGET; brownout/WDT resets (no core dump) reported by reason with hints; raw image access (image_size/read_image) for downloading the full core, erase(). Degrades gracefully when core dump support is disabled.
  • espp::CoreDumpService: transport-agnostic service on the proven ota_stream framing — construct with a send function, feed() bytes from any stream (USB vendor callback, CDC RX, socket). Unknown frame types are ignored so it coexists with other protocols (e.g. the haptics protocol) on one stream. Dedicated code ranges: requests 0x40–0x43 (GET_SUMMARY/GET_SIZE/READ/ERASE), replies 0xC0–0xC4.
  • Webapp (web/coredump_console.html, docs-hosted): connect via WebUSB or Web Serial; over serial it splits console text from protocol frames, so the page doubles as a live serial monitor (with input row). Crash summary, chunked core.elf download (ELF-magic located inside the flash image; raw fallback), erase, auto-filled espcoredump.py/addr2line command lines, and client-side nearest-symbol resolution from a locally-picked app .elf (symtab/strtab parse, labelled as approximate).
  • Example (esp32s3, native USB): composite WebUSB vendor + CDC with the system console routed to it; service mounted on both streams; test-crash commands (crash|assert|divzero|hang|report) typeable from the webapp, BOOT-button crash trigger; coredump partition + sdkconfig wired.
  • Docs (doc/en/coredump/), Doxyfile, CI build matrix + component-registry entries.

Needs hardware verification

Full crash → dump → next-boot report → download/erase flow on a real S3 (especially CDC console/frame interleaving under load); espcoredump.py acceptance of the extracted core.elf (raw-image fallback exists); the BOOT-button and INT_WDT (hang) paths; RISC-V report path compiles but was only built for Xtensa.

Testing

  • idf.py set-target esp32s3 && idf.py build clean (IDF 6.0.1); webapp JS node --check clean.

🤖 Generated with Claude Code

finger563 and others added 4 commits August 28, 2026 13:21
espp::CoreDump wraps the ESP-IDF flash core dump (espcoredump) in an
idiomatic espp API: has_core_dump(), summary() (esp_core_dump_summary_t),
format_report() (reset reason, panic reason, crashed task + PC, raw
backtrace addresses / RISC-V stack dump, addr2line decode hint with the
right toolchain prefix for CONFIG_IDF_TARGET, and brownout/watchdog hints
for resets that write no dump), plus raw image access (image_size(),
read_image(), erase()) for downloading the full ELF core dump over any
transport. All failures via std::error_code; degrades gracefully when
core-dump-to-flash is disabled.

espp::CoreDumpService serves that over any byte stream by reusing the ota
component's CRC-32 stream framing, with message types in a dedicated range
(0x40..0x43 requests / 0xC0..0xC4 replies: GET_SUMMARY/GET_SIZE/READ/ERASE
-> SUMMARY/SIZE/DATA/OK/ERROR). Construct with a send function; feed(bytes)
runs a resynchronizing parser (so the stream can also carry console text)
and handle_frame() supports an external parser. Unknown frame types are
ignored so the service coexists with other protocols on one stream.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…onsole)

Composite espp::UsbDevice: a vendor/WebUSB interface carrying the framed
core-dump protocol and a CDC port carrying the system console
(tinyusb_console_init) plus the same protocol on one stream. A
CoreDumpService instance is mounted on BOTH streams (shared CoreDump),
with RX queued out of the TinyUSB task into a worker.

Prints the previous-boot crash report at startup (re-logged on each CDC
connect) and offers deliberate test crashes from the CDC console
(crash / assert / divzero / hang / report / help) or the BOOT button:
null-pointer write, failed assert, divide-by-zero (core dump + backtrace)
and an interrupts-off hang (INT_WDT reset, reset-reason-only report).

sdkconfig: CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH=y + TinyUSB vendor/CDC on a
4MB flash; partitions.csv adds a 64K coredump data partition; main
REQUIRES espcoredump explicitly for its header/Kconfig symbols on IDF 6.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Single-file, offline, dependency-free browser tool for the coredump
stream service. Connects over WebUSB (vendor interface) or Web Serial
(CDC): over serial the parser separates console text from protocol frames
on the shared stream, so the app doubles as a serial monitor with a
console input row (type 'crash' to exercise the flow).

Features: crash summary display, chunked core-dump download saved as
core.elf (ELF located inside the flash image; raw image download too),
erase, copy-paste espcoredump.py / addr2line command lines (addresses
filled in from the report), and client-side nearest-symbol backtrace
resolution by parsing the user-picked app ELF's symtab/strtab (no DWARF;
labelled as approximate). Dark/light aware; served automatically at
esp-cpp.github.io/espp/apps/coredump_console.html by the docs workflow.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- doc/en/coredump/{index,coredump,coredump_example}: component docs
  following the ota pattern, wired into the Core & RTOS toctree
- web_apps.rst: Core Dump Console highlight
- Doxyfile: coredump headers + example inputs
- build.yml: build the coredump example for esp32s3
- upload_components.yml: publish components/coredump

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings August 28, 2026 18:23

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Pull request overview

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Introduces a new coredump component (device-side crash dump access + framed stream service) along with a self-contained WebUSB/Web Serial browser console, plus documentation and CI wiring to build/publish the new component.

Changes:

  • Added espp::CoreDump + espp::CoreDumpService (header-only) for crash reporting, core dump image access, and a transport-agnostic framed protocol.
  • Added an offline-capable single-file web inspector (coredump_console.html) supporting WebUSB and Web Serial (including console/protocol interleaving).
  • Added docs + Doxygen/CI/component-registry updates and a full ESP32-S3 native-USB example.

Reviewed changes

Copilot reviewed 20 out of 20 changed files in this pull request and generated 13 comments.

Show a summary per file
File Description
doc/en/web_apps.rst Lists the new Core Dump Console web app in documentation highlights.
doc/en/index.rst Adds coredump docs section to the main docs toctree.
doc/en/coredump/index.rst New coredump docs index page and toctree.
doc/en/coredump/coredump_example.md Includes the example README into the docs build.
doc/en/coredump/coredump.rst New component documentation and API includes for CoreDump/CoreDumpService.
doc/Doxyfile Adds coredump headers and example file to Doxygen input/example paths.
components/coredump/web/coredump_console.html New single-file WebUSB/Web Serial crash inspector + serial monitor.
components/coredump/include/coredump_service.hpp New transport-agnostic framed protocol service for core dump operations.
components/coredump/include/coredump.hpp New CoreDump wrapper around ESP-IDF flash coredump APIs + report formatting.
components/coredump/idf_component.yml New IDF component manifest for publishing/consumption.
components/coredump/example/sdkconfig.defaults Example config enabling native USB + flash coredumps on ESP32-S3.
components/coredump/example/partitions.csv Example custom partitions with a dedicated coredump partition.
components/coredump/example/main/coredump_example.cpp New ESP32-S3 native USB example mounting protocol on vendor + CDC streams.
components/coredump/example/main/CMakeLists.txt Example main component deps (explicit espcoredump, USB, GPIO, etc.).
components/coredump/example/README.md Example usage instructions and typical crash→download→decode flow.
components/coredump/example/CMakeLists.txt Example project wiring with narrowed EXTRA_COMPONENT_DIRS.
components/coredump/README.md Component README describing APIs, protocol, and web console usage.
components/coredump/CMakeLists.txt Component registration as header-only with required public deps.
.github/workflows/upload_components.yml Adds components/coredump to component upload workflow.
.github/workflows/build.yml Adds components/coredump/example to the CI build matrix.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

- coredump.hpp: explicitly include format.hpp (fmt::format is used in the
  header) and add the format component to REQUIRES
- coredump.hpp: validate the core-dump image address range lies within the
  coredump partition before computing the partition-relative offset, so an
  inconsistent address cannot underflow or read the wrong flash region
- coredump_service.hpp: normalize non-generic-category error codes to a
  std::errc value (default_error_condition, io_error fallback) so the
  on-wire ERROR code always matches the wire spec
- web console: default WebUSB filter now matches VID and PID (the 'show all
  USB devices' checkbox still lifts the filter), removing the unused
  DEFAULT_PID
- web console: extractAddresses() now includes the faulting PC first
  (deduplicated) alongside the backtrace addresses, matching its comment

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

github-actions Bot commented Aug 28, 2026
edited
Loading

Copy link
Copy Markdown

✅Static analysis result - no issues found! ✅

…config-constant findings

The static-analysis CI flagged: the example's INTENTIONAL crash triggers
(null-pointer store, divide-by-zero - crashing is their purpose), two
knownConditionTrueFalse findings that are constants only in the
coredump-disabled configuration cppcheck analyzes, and the
CONFIG_IDF_TARGET string-paste it cannot resolve. All suppressed inline
with justifications; cppcheck now reports 0 findings on the component and
the example still builds clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 6 comments.

Comment thread components/coredump/example/README.md Outdated
Comment thread components/coredump/README.md Outdated
…utside lock, README API names)

- CoreDump::format_report(): report ALL abnormal reset reasons even when no
  core dump image is present (PANIC with a missing dump, UNKNOWN, power
  glitch, CPU lockup, ... in addition to the existing brownout/watchdog
  hints); empty string is now reserved for genuinely clean reasons
  (power-on / EXT / SW / deep-sleep / SDIO / USB / JTAG) via a new
  is_clean_reset_reason() helper, and the docs state precisely which.
- CoreDumpService: never invoke the user send callback under the internal
  mutex. handle_frame_locked() now performs the flash access and BUILDS the
  reply frame under the lock (send_error -> build_error); feed()/
  handle_frame() transmit the collected replies after unlocking, so a
  re-entrant transport (send path that triggers RX -> feed()) cannot
  deadlock. Documented the threading / send-callback contract.
- READMEs: the example routes the console with
  tinyusb_console_init(TINYUSB_CDC_ACM_0), not esp_tusb_init_console.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 3 comments.

Suppressed comments (1)

Previously missed (1) — in code that hasn't changed since the last review.

components/coredump/web/coredump_console.html:267

  • This label says the checksum is stripped, but extractElf() only slices off bytes before the ELF magic and deliberately retains the trailing padding/checksum. Update the text so downloaded-file semantics are accurate.
        <span class="muted">core.elf strips the flash header/checksum; the raw image is the whole stored blob.</span>

Comment thread components/coredump/idf_component.yml Outdated
…B FIFO sizing, IDF >=5.2, webapp label)

- CoreDump: serialize all flash-touching methods (has_core_dump / summary /
  format_report / image_size / read_image / erase) with an internal mutex so
  one CoreDump can be shared by several CoreDumpService instances /
  transports without a READ on one racing an ERASE on the other; documented
  on the class and in CoreDumpService's shared-CoreDump note.
- example sdkconfig.defaults: size the TinyUSB vendor RX/TX and CDC TX FIFOs
  (4096) to hold a complete DATA reply frame (2,063 bytes with the web
  console's 2 KiB read chunks) so the stock write path cannot truncate
  replies; PR #742 additionally makes write_vendor wait-for-drain.
- idf_component.yml: require idf >=5.2 (first release with
  esp_core_dump_get_panic_reason(), used for the ELF crash report).
- example: replace the now-stale knownConditionTrueFalse inline suppression
  (which CI reports as unmatched since b7871e9) with a
  CONFIG_ESP_COREDUMP_ENABLE_TO_FLASH guard, robust across cppcheck versions.
- CoreDumpService: make build_error() const (cppcheck functionConst).
- webapp: correct the download-panel label — core.elf drops the flash header
  before the ELF magic; the trailing checksum bytes are retained.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copy link
Copy Markdown
Contributor Author

Addressing Copilot's suppressed comment on components/coredump/web/coredump_console.html:267 (the download-panel label said "core.elf strips the flash header/checksum", but extractElf() only slices off the bytes before the ELF magic and deliberately keeps the trailing padding/checksum, which ELF readers ignore since they follow the internal offsets): fixed in 2e02a9c by correcting the label to "core.elf drops the flash header before the ELF magic (trailing checksum bytes remain; ELF tools ignore them); the raw image is the whole stored blob." — the extraction behavior itself is intentional and unchanged.

finger563 requested a balanced review from Copilot August 29, 2026 02:53

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 4 comments.

…ough marker, handle_frame doc)

- webapp: navigator.usb.requestDevice() has no acceptAllDevices option
  (that's Web Bluetooth); use the required filters member with an empty
  list to show all devices
- example: end the Assert case with an explicit __builtin_unreachable()
  so there is no implicit fallthrough into DivideByZero
- coredump_service: handle_frame() @return doc now states the reply is
  only delivered when a send callback is configured (dropped otherwise)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Pull request overview

Copilot reviewed 20 out of 20 changed files in this pull request and generated 1 comment.

Suppressed comments (3)

Previously missed (3) — in code that hasn't changed since the last review.

components/coredump/include/coredump.hpp:142

  • A stored core dump is not necessarily from the latest reset: ESP-IDF keeps it until explicit erase, so a later software or brownout reset can leave an older panic image here (and no-overwrite mode can preserve one across another panic). This then reports last reset: SW/BROWNOUT alongside task/PC data from a different crash. Label the current reset reason and the stored dump as separate events, and update the “previous boot” documentation accordingly.
      report = fmt::format("last reset: {} ({})", reason_name, static_cast<int>(reset_reason));

components/coredump/web/coredump_console.html:602

  • transferOut() may return status === "ok" with bytesWritten smaller than the supplied buffer. Treating that as success truncates the request frame, which leaves the device parser waiting and causes a timeout. Continue sending the unsent suffix (and reject a zero-progress result).
          async send(bytes) {
            const result = await device.transferOut(epOut, bytes);
            if (result.status === "stall") {
              try { await device.clearHalt("out", epOut); } catch (_) {}
              throw new Error("OUT endpoint stalled");

components/coredump/include/coredump.hpp:231

  • has_core_dump_locked() runs esp_core_dump_image_check(), which rereads and checksums the entire image. Calling it for every chunk makes the advertised chunked download quadratic: a 64 KiB image read in 2 KiB chunks scans roughly 2 MiB before the actual chunk reads, and larger partitions scale much worse. Validate once per download/session (while preserving erase synchronization), then use the validated address/size for bounded chunk reads.
    if (!has_core_dump_locked() || esp_core_dump_image_get(&addr, &size) != ESP_OK) {

Comment on lines +163 to +177
void feed(std::span<const uint8_t> data) {
std::vector<std::vector<uint8_t>> replies;
{
std::lock_guard<std::mutex> lock(mutex_);
for (const auto &frame : parser_.feed(data)) {
std::vector<uint8_t> reply;
if (handle_frame_locked(static_cast<uint8_t>(frame.type), frame.payload, reply) &&
!reply.empty())
replies.push_back(std::move(reply));
}
}
// send outside the lock so a re-entrant transport cannot deadlock
for (const auto &reply : replies)
send(reply);
}
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants


Back | FazBrowse Home | New Git URL