mirror of
https://github.com/polpo/picogus.git
synced 2026-10-25 21:40:16 +00:00
Check for panic-causing printfs when compiling without PGDEBUG
This commit is contained in:
1 parent
9470719b32
commit
d5fc6e0559
3 files changed
+118
-7
No files matched your search
@@ -136,12 +136,28 @@ jobs:
|
||||
run: |
|
||||
mkdir -p $STAGING_DIR
|
||||
cp pgusinit/README.md $STAGING_DIR/README.md
|
||||
- name: Get Tags
|
||||
id: tag
|
||||
uses: ildug/get-tag-action@v1
|
||||
- name: Generate release body
|
||||
- name: Classify release
|
||||
id: relinfo
|
||||
shell: bash
|
||||
run: |
|
||||
awk '/^# v${{ steps.tag.outputs.version }}/{a=1;next}/^# /{a=0}a' sw/CHANGELOG.md > release-body.md
|
||||
VERSION="${GITHUB_REF_NAME#v}"
|
||||
echo "version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
if [[ "$VERSION" == *-* ]]; then
|
||||
echo "prerelease=true" >> "$GITHUB_OUTPUT"
|
||||
echo "base_version=${VERSION%%-*}" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "prerelease=false" >> "$GITHUB_OUTPUT"
|
||||
echo "base_version=$VERSION" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
- name: Generate release body
|
||||
shell: bash
|
||||
run: |
|
||||
VERSION="${{ steps.relinfo.outputs.version }}"
|
||||
BASE="${{ steps.relinfo.outputs.base_version }}"
|
||||
awk -v ver="$VERSION" '$0 ~ "^# v" ver "$" {a=1;next} /^# /{a=0} a' sw/CHANGELOG.md > release-body.md
|
||||
if [ ! -s release-body.md ] && [ "$VERSION" != "$BASE" ]; then
|
||||
awk -v ver="$BASE" '$0 ~ "^# v" ver "$" {a=1;next} /^# /{a=0} a' sw/CHANGELOG.md > release-body.md
|
||||
fi
|
||||
- name: Download firmware artifact
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
@@ -156,11 +172,12 @@ jobs:
|
||||
uses: montudor/action-zip@v1
|
||||
- name: Zip release
|
||||
run: |
|
||||
zip -9 -r ../picogus-v${{ steps.tag.outputs.version }}.zip .
|
||||
zip -9 -r ../picogus-v${{ steps.relinfo.outputs.version }}.zip .
|
||||
working-directory: ${{env.STAGING_DIR}}
|
||||
- name: Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
body_path: release-body.md
|
||||
files: picogus-v${{ steps.tag.outputs.version }}.zip
|
||||
files: picogus-v${{ steps.relinfo.outputs.version }}.zip
|
||||
draft: true
|
||||
prerelease: ${{ steps.relinfo.outputs.prerelease }}
|
||||
@@ -56,6 +56,7 @@ endfunction()
|
||||
|
||||
|
||||
option(PGDEBUG "Enable debug printf framework" OFF)
|
||||
find_package(Python3 COMPONENTS Interpreter QUIET)
|
||||
|
||||
# Global definitions across all targets
|
||||
add_compile_definitions(
|
||||
@@ -246,6 +247,18 @@ function(config_target TARGET_NAME MULTIFW)
|
||||
endif()
|
||||
pico_set_printf_implementation(${TARGET_NAME} none)
|
||||
endif()
|
||||
if(NOT PGDEBUG AND Python3_FOUND)
|
||||
# With printf stripped, __wrap_snprintf is the panic stub, so any
|
||||
# stray printf call dead-loops the firmware. Fail the build if we
|
||||
# find one.
|
||||
add_custom_command(TARGET ${TARGET_NAME} POST_BUILD
|
||||
COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_SOURCE_DIR}/scripts/check_printf_leak.py
|
||||
${CMAKE_OBJDUMP} ${CMAKE_ADDR2LINE}
|
||||
$<TARGET_FILE:${TARGET_NAME}>
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
pico_enable_stdio_semihosting(${TARGET_NAME} 0)
|
||||
endfunction()
|
||||
|
||||
@@ -518,6 +531,7 @@ function(build_psg TARGET_NAME MULTIFW)
|
||||
)
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
audio/volctrl.cpp
|
||||
audio/audio_i2s_minimal.c
|
||||
square/square.cpp
|
||||
)
|
||||
target_sources(${TARGET_NAME} PRIVATE psgplay.cpp)
|
||||
@@ -534,9 +548,12 @@ function(build_usb TARGET_NAME MULTIFW)
|
||||
pico_set_program_name(${TARGET_NAME} "picogus-usb")
|
||||
target_compile_definitions(${TARGET_NAME} PRIVATE
|
||||
USB_ONLY=1
|
||||
USE_CD_AUDIO_FIFO=1
|
||||
)
|
||||
target_sources(${TARGET_NAME} PRIVATE
|
||||
audio/volctrl.cpp
|
||||
audio/audio_fifo.c
|
||||
audio/audio_i2s_minimal.c
|
||||
usbplay.cpp
|
||||
)
|
||||
endfunction()
|
||||
@@ -665,6 +682,15 @@ if(PROJECT_TYPE STREQUAL "MULTIFW")
|
||||
if(NOT PGDEBUG)
|
||||
pico_set_printf_implementation(bootloader none)
|
||||
endif()
|
||||
if(NOT PGDEBUG AND Python3_FOUND)
|
||||
add_custom_command(TARGET bootloader POST_BUILD
|
||||
COMMAND ${Python3_EXECUTABLE}
|
||||
${CMAKE_SOURCE_DIR}/scripts/check_printf_leak.py
|
||||
${CMAKE_OBJDUMP} ${CMAKE_ADDR2LINE}
|
||||
$<TARGET_FILE:bootloader>
|
||||
VERBATIM
|
||||
)
|
||||
endif()
|
||||
add_dependencies(bootloader generate_flash_firmware_h)
|
||||
|
||||
if (NOT UF2CREATE_FOUND)
|
||||
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Used to fail the build if any non-panic code calls the raw printf-family
|
||||
# wrappers that route to printf_none_assert.
|
||||
|
||||
import re
|
||||
import subprocess
|
||||
import sys
|
||||
|
||||
|
||||
def main(argv: list[str]) -> int:
|
||||
if len(argv) != 4:
|
||||
print(
|
||||
"usage: check_printf_leak.py <objdump> <addr2line> <elf>",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 2
|
||||
|
||||
objdump, addr2line, elf = argv[1:4]
|
||||
|
||||
dis = subprocess.run(
|
||||
[objdump, "-d", elf], check=True, capture_output=True, text=True
|
||||
).stdout
|
||||
|
||||
offenders = []
|
||||
call_re = re.compile(
|
||||
r"^\s*([0-9a-f]+):\s.*\bbl\s+[0-9a-f]+\s+<(__wrap_v?s?n?printf)>"
|
||||
)
|
||||
for line in dis.splitlines():
|
||||
m = call_re.match(line)
|
||||
if not m:
|
||||
continue
|
||||
call_site, wrap = m.group(1), m.group(2)
|
||||
res = subprocess.run(
|
||||
[addr2line, "-fe", elf, call_site],
|
||||
check=True,
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
lines = res.stdout.strip().splitlines()
|
||||
if not lines:
|
||||
continue
|
||||
caller = lines[0].strip()
|
||||
# Skip pico_stdio wrappers calling each other internally
|
||||
# (__wrap_printf -> __wrap_vprintf etc)
|
||||
if caller.startswith("__wrap_"):
|
||||
continue
|
||||
location = lines[1].strip() if len(lines) > 1 else "<unknown>"
|
||||
offenders.append((call_site, wrap, caller, location))
|
||||
|
||||
if not offenders:
|
||||
return 0
|
||||
|
||||
print(
|
||||
f"error: {elf} contains printf call(s) that will panic:",
|
||||
file=sys.stderr,
|
||||
)
|
||||
for addr, wrap, caller, loc in offenders:
|
||||
print(f" {loc}: {caller}() -> {wrap} [@0x{addr}]", file=sys.stderr)
|
||||
print(
|
||||
"Replace with DBG_PRINTF from sw/include/pg_debug.h (no-ops when PGDEBUG is off).",
|
||||
file=sys.stderr,
|
||||
)
|
||||
return 1
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv))
|
||||
Reference in new issue
Block a user