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

RFC: Embed configuration definitions in debug binary. by agatti · Pull Request #18907 · micropython/micropython · GitHub

RFC: Embed configuration definitions in debug binary. - #18907

Open
agatti wants to merge 1 commit into
micropython:masterfrom
agatti:gcc-embed-debug-info
Open

agatti wants to merge 1 commit into
micropython:masterfrom
agatti:gcc-embed-debug-info

Conversation

agatti commented Mar 9, 2026
edited
Loading

Copy link
Copy Markdown
Contributor

Summary

This PR introduces the ability to record selected configuration settings used to build the binary in debug mode, and embed the encoded representation of said information in the produced executable binary itself.

GDB can parse special sections as containers for either references to external debug scripts or as embedded python/scheme code. Since there are some configuration settings that are not persisted in the MicroPython binary, GDB helper scripts would have to either guess the values of some configuration definitions or prompt the user for the values themselves. For example, the chosen object representation scheme is not tracked anywhere in the binary for space reasons, and the value of the appropriate preprocessor definition is lost once the build process ends.

The changes in this PR encode a few definitions used by GDB helper scripts into a dictionary called "MPY_BINARY_DEBUG_INFO", which can be queried from a GDB session via GDB's Python API.

GDB doesn't load the encoded contents unless it is explicitly configured to either ignore any safeguards regarding foreign scripts, or if the currently debugged executable is in the "safe" script sources.

GDB documents this facility here: https://sourceware.org/gdb/current/onlinedocs/gdb.html/dotdebug_005fgdb_005fscripts-section.html

Right now this is used by the Unix port and the debug information gets embedded only for debug builds if the "EMBED_DEBUG_INFO" variable is set in the make command line.


This came up during a discussion between @AJMansfield and I - as we both wrote our own GDB helper scripts/printers to decode container objects, QSTRs, raw mp_obj_t payloads and so on - and we both ended up having the same pain points regarding how to find out configuration settings that were lost in the build process (like the chosen object representation).

Even though this PR does not embed configuration information on anything but the Unix port when compiled for Linux, this method is also safe for embedded targets. Board deployment programs/flashers/etc already ignore non-relevant sections, so an ELF size increase does not correspond to an on-flash size increase.

The configuration encoding mechanism can also be changed to also be available for non-debug builds, but the main use case is to augment GDB helper scripts - which greatly benefit from having debug symbols in.

That said, this can also be the starting point for an official GDB printers/helpers script that could be either provided in a separate repo or shipped with MicroPython itself (like other projects do, including CPython).

Testing

Debug information was retrieved from a GDB session with this commands sequence:

$ make -C ports/unix DEBUG=1 EMBED_DEBUG_INFO=1
$ gdb \
	-q \
	-iex "set auto-load safe-path $(pwd)/ports/unix/build-standard/micropython" \
	ports/unix/build-standard/micropython

Reading symbols from ports/unix/build-standard/micropython...
(gdb) python print(MPY_BINARY_DEBUG_INFO)
{'float_impl': 2, 'longint_impl': 2, 'mpz_dig_size': 16, 'obj_immediate_objs': True, 'obj_repr': 0, 'timestamp_impl': 2}
(gdb)

Trade-offs and Alternatives

There may be some security concerns related to the mechanisms used to generate and load the encoded data.

For data generation, since these changes interact directly with the preprocessor and use Python's eval to clean data up, this functionality is enabled only in response to explicit user input, at which point an eventual attacker already has full control of the execution environment.

Data consumption events only occur in rather specialised situations and they also require an explicit configuration from the user or a general misconfiguration of the GDB installation. In the latter case, literally any other malicious binary would already have exploited all that's available to exploit.

An alternative could be to generate a json/yaml/etc. version of the collected debug information and store it in the build directory, however that's one more file to keep track of when having to debug certain issues reported by third parties - where an ELF file is usually provided but not even core files are a given.

Generative AI

I did not use generative AI tools when creating this PR.

codecov Bot commented Mar 9, 2026
edited
Loading

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 98.59%. Comparing base (09f5bb4) to head (58a56ac).

Additional details and impacted files
@@           Coverage Diff           @@
##           master   #18907   +/-   ##
=======================================
  Coverage   98.59%   98.59%           
=======================================
  Files         182      182           
  Lines       23335    23335           
  Branches        5        5           
=======================================
  Hits        23006    23006           
  Misses        328      328           
  Partials        1        1           
Flag Coverage Δ
unix-coverage-32bit 98.59% <ø> (ø)
unix-coverage-64bit 98.52% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

github-actions Bot commented Mar 9, 2026
edited
Loading

Copy link
Copy Markdown

Code size report:

Reference:  mimxrt/modmachine: Fix machine.deepsleep(ms) for the MIMXRT1176 port. [09f5bb4]
Comparison: py: Embed configuration definitions in debug binary. [merge of 58a56ac]
  mpy-cross:    +0 +0.000% 
   bare-arm:    +0 +0.000% 
minimal x86:    +0 +0.000% 
   unix x64:    +0 +0.000% standard
      stm32:    +0 +0.000% PYBV10
      esp32:    +0 +0.000% ESP32_GENERIC
     mimxrt:    +0 +0.000% TEENSY40
        rp2:    +0 +0.000% RPI_PICO_W
       samd:    +0 +0.000% ADAFRUIT_ITSYBITSY_M4_EXPRESS
  qemu rv32:    +0 +0.000% VIRT_RV32

agatti added rfc Request for Comment tools Relates to tools/ directory in source, or other tooling labels May 18, 2026
agatti marked this pull request as ready for review June 1, 2026 10:12
agatti force-pushed the gcc-embed-debug-info branch from 714f682 to fb91c9b Compare August 25, 2026 23:41

octoprobe-bot commented Aug 26, 2026
edited
Loading

Copy link
Copy Markdown

Octoprobe PR report

Test Tests
passed
Tests
skipped
Tests
xfailed
Tests
failed
format flash 9 8
run-tests.py 22287 3203 15 12
run-tests.py --via-mpy --emit native 30514 5481 30 24
run-tests.py --via-mpy 31632 4271 18 29
run-perfbench.py 394 14
run-natmodtests.py 778 167 16
run-mpremote-tests.sh 173 9 7
run-tests.py --test-dirs=extmod_hardware 181 309 71
run-tests.py --test-dirs=extmod_hardware --emit-native 173 267 66
Total 86141 13729 216 72
Failures

Group: run-mpremote-tests.sh

Test esp32
0c30-
ESP32_C3_DEVKIT
esp32
5d21-
ESP32_DEVKIT
esp32
472b-
ESP32_S3_DEVKIT
esp32
1830-
LOLIN_C3_MINI
esp8266
7921-
LOLIN_D1_MINI
mimxrt
1133-
TEENSY40
nrf
3c2a-
ARDUINO_NANO_33
rp2
5334-
RPI_PICO2
rp2
5334-
RPI_PICO2-
RISCV
rp2
552b-
RPI_PICO2_W
rp2
6038-
RPI_PICO_W
samd
5f2a-
ADA_ITSYBITSY_M0
stm32
2b35-
NUCLEO_WB55
stm32
7b21-
PYBV11
stm32
7b21-
PYBV11-
DP
stm32
7b21-
PYBV11-
DP_THREAD
stm32
3a21-
PYBV11-
THREAD
test_unicode.sh pass pass pass pass FAIL FAIL FAIL pass pass pass skip pass pass pass pass skip pass pass pass pass pass
test_filesystem.sh pass pass pass pass FAIL FAIL FAIL pass pass pass skip pass pass pass pass skip pass pass pass pass pass
test_eval_exec_run.sh pass pass pass pass pass pass pass FAIL pass pass pass pass pass pass pass pass pass pass pass pass pass

Group: run-tests.py

Test esp32
0c30-
ESP32_C3_DEVKIT
esp32
5d21-
ESP32_DEVKIT
esp32
472b-
ESP32_S3_DEVKIT
esp32
1830-
LOLIN_C3_MINI
esp8266
7921-
LOLIN_D1_MINI
mimxrt
1133-
TEENSY40
nrf
3c2a-
ARDUINO_NANO_33
rp2
5334-
RPI_PICO2
rp2
5334-
RPI_PICO2-
RISCV
rp2
552b-
RPI_PICO2_W
rp2
5f2c-
RPI_PICO_W
samd
5f2a-
ADA_ITSYBITSY_M0
stm32
2b35-
NUCLEO_WB55
stm32
7b21-
PYBV11
stm32
7b21-
PYBV11-
DP
stm32
7b21-
PYBV11-
DP_THREAD
stm32
3a21-
PYBV11-
THREAD
basics/try_finally_break.py pass pass pass pass pass pass FAIL pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass
basics/try_finally_break2.py pass pass pass pass pass pass FAIL pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass
basics/try_finally_continue.py pass pass pass pass pass pass FAIL pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass
basics/try_finally_loops.py pass pass pass pass pass pass FAIL pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass
extmod/json_dumps_separators.py pass pass pass pass FAIL pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass
extmod/json_load.py pass pass pass pass FAIL pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass
extmod/json_loads.py pass pass pass pass FAIL pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass
extmod/json_loads_bytes.py pass pass pass pass FAIL pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass
extmod/json_loads_float.py pass pass pass pass FAIL pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass pass
extmod/machine_mem_backup_slice.py pass pass pass pass skip skip FAIL FAIL FAIL skip skip skip skip skip skip skip skip pass pass pass pass pass pass

Group: run-tests.py --via-mpy --emit native

Test esp32
0c30-
ESP32_C3_DEVKIT
esp32
5d21-
ESP32_DEVKIT
esp32
472b-
ESP32_S3_DEVKIT
esp32
1830-
LOLIN_C3_MINI
esp8266
7921-
LOLIN_D1_MINI
mimxrt
1133-
TEENSY40
nrf
3c2a-
ARDUINO_NANO_33
rp2
5334-
RPI_PICO2
rp2
5334-
RPI_PICO2-
RISCV
rp2
552b-
RPI_PICO2_W
rp2
5f2c-
RPI_PICO_W
samd
5f2a-
ADA_ITSYBITSY_M0
stm32
2b35-
NUCLEO_WB55
stm32
3a21-
PYBV11
stm32
7b21-
PYBV11-
DP
stm32
7b21-
PYBV11-
DP_THREAD
stm32
3a21-
PYBV11-
THREAD
extmod/machine_mem_backup_slice.py pass pass pass pass skip skip skip FAIL FAIL FAIL skip skip skip skip skip skip skip skip skip skip skip skip skip skip skip skip pass pass pass pass pass pass pass pass
extmod/machine_timer.py pass pass pass pass skip skip pass skip skip skip pass pass pass pass pass pass pass pass pass pass pass pass FAIL FAIL FAIL pass pass pass pass pass pass pass pass pass
micropython/viper_ptr8_load_boundary.py pass pass pass pass skip skip pass pass pass pass pass pass pass pass pass [pass](https://reports.octoprobe.org/github\_selfhosted\_testrun\_773/RUN-TESTS\_STANDARD\_NATIVE@5334-RPI\_PICO2-RISCV,c/logger\_20\_info.l...*[Comment body truncated]

This commit introduces the ability to record selected configuration
settings used to build the binary in debug mode, and embed the encoded
representation of said information in the produced executable binary
itself.

GDB can parse special sections as containers for either references to
external debug scripts or as embedded python/scheme code.  Since there
are some configuration settings that are not persisted in the
MicroPython binary, GDB helper scripts would have to either guess the
values of some configuration definitions or prompt the user for the
values themselves.  For example, the chosen object representation
scheme is not tracked anywhere in the binary for space reasons, and the
value of the appropriate preprocessor definition is lost once the build
process ends.

The changes in this commit encode a few definitions used by GDB helper
scripts into a dictionary called "MPY_BINARY_DEBUG_INFO", which can be
queried from a GDB session via GDB's Python API.

GDB doesn't load the encoded contents unless it is explicitly configured
to either ignore any safeguards regarding foreign scripts, or if the
currently debugged executable is in the "safe" script sources.

GDB documents this facility here: https://sourceware.org/gdb/current/onlinedocs/gdb.html/dotdebug_005fgdb_005fscripts-section.html

Right now this is used by the Unix port and the debug information gets
embedded only for debug builds if the "EMBED_DEBUG_INFO" variable is set
in the make command line.

Signed-off-by: Alessandro Gatti <a.gatti@frob.it>
agatti force-pushed the gcc-embed-debug-info branch from fb91c9b to 58a56ac Compare September 21, 2026 15:41
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

rfc Request for Comment tools Relates to tools/ directory in source, or other tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants


Back | FazBrowse Home | New Git URL