From: Renz Bagaporo Date: Wed, 18 Apr 2018 02:57:45 +0000 (+0800) Subject: tools: implement linker script generation X-Git-Tag: v3.3-beta1~101^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=63411fc556fb2e71985db50dacbf42a6532b3993;p=esp-idf tools: implement linker script generation --- diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 73c2cf577e..4bfea8f647 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -441,6 +441,13 @@ test_fatfs_on_host: - cd components/fatfs/test_fatfs_host/ - make test +test_ldgen_on_host: + <<: *host_test_template + script: + - cd tools/ldgen/test + - ./test_fragments.py + - ./test_generation.py + .host_fuzzer_test_template: &host_fuzzer_test_template stage: host_test image: $CI_DOCKER_REGISTRY/afl-fuzzer-test diff --git a/components/app_trace/CMakeLists.txt b/components/app_trace/CMakeLists.txt index 151015021a..ffd6095098 100644 --- a/components/app_trace/CMakeLists.txt +++ b/components/app_trace/CMakeLists.txt @@ -18,6 +18,7 @@ endif() set(COMPONENT_REQUIRES) set(COMPONENT_PRIV_REQUIRES xtensa-debug-module) +set(COMPONENT_ADD_LDFRAGMENTS linker.lf) register_component() diff --git a/components/app_trace/component.mk b/components/app_trace/component.mk index b53e27d307..bfe77da43a 100644 --- a/components/app_trace/component.mk +++ b/components/app_trace/component.mk @@ -26,4 +26,6 @@ COMPONENT_SRCDIRS += \ sys_view/esp32 else COMPONENT_SRCDIRS += gcov + +COMPONENT_ADD_LDFRAGMENTS += linker.lf endif diff --git a/components/app_trace/linker.lf b/components/app_trace/linker.lf new file mode 100644 index 0000000000..d615324119 --- /dev/null +++ b/components/app_trace/linker.lf @@ -0,0 +1,5 @@ +[mapping] +archive: libapp_trace.a +entries: + * (noflash) + diff --git a/components/esp32/CMakeLists.txt b/components/esp32/CMakeLists.txt index daa000c4f1..880278508e 100644 --- a/components/esp32/CMakeLists.txt +++ b/components/esp32/CMakeLists.txt @@ -71,6 +71,8 @@ else() app_trace bootloader_support ethernet log mbedtls nvs_flash pthread smartconfig_ack spi_flash vfs wpa_supplicant xtensa-debug-module) + set(COMPONENT_ADD_LDFRAGMENTS linker.lf ld/esp32_fragments.lf) + register_component() target_link_libraries(esp32 "-L ${CMAKE_CURRENT_SOURCE_DIR}/lib") @@ -84,7 +86,16 @@ else() target_linker_script(esp32 "ld/esp32.extram.bss.ld") endif() - target_linker_script(esp32 "ld/esp32.common.ld") + # Process the template file through the linker script generation mechanism, and use the output for linking the + # final binary + set(esp32_common_script "${CMAKE_CURRENT_BINARY_DIR}/esp32.common.ld") + set(esp32_common_template "${CMAKE_CURRENT_LIST_DIR}/ld/esp32.common.ld.in") + + ldgen_process_template(${esp32_common_template} ${esp32_common_script}) + + target_link_libraries(esp32 "-T ${esp32_common_script}") + + set_property(TARGET ${PROJECT_NAME}.elf APPEND PROPERTY LINK_DEPENDS ${esp32_common_script}) target_linker_script(esp32 "ld/esp32.rom.ld" @@ -146,7 +157,7 @@ else() endif() - # Enable dynamic esp_timer overflow value if building unit tests + # Enable dynamic esp_timer overflow value if building unit tests if(NOT "${BUILD_TEST_COMPONENTS}" EQUAL "") add_definitions(-DESP_TIMER_DYNAMIC_OVERFLOW_VAL) endif() diff --git a/components/esp32/Makefile.projbuild b/components/esp32/Makefile.projbuild index 9a51d80b3e..a17591ff01 100644 --- a/components/esp32/Makefile.projbuild +++ b/components/esp32/Makefile.projbuild @@ -42,3 +42,9 @@ endif ifneq ("$(TEST_COMPONENTS_LIST)","") CPPFLAGS += -DESP_TIMER_DYNAMIC_OVERFLOW_VAL endif +ESP32_LINKER_SCRIPT_TEMPLATE := $(COMPONENT_PATH)/ld/esp32.common.ld.in +ESP32_LINKER_SCRIPT_OUTPUT_DIR := $(abspath $(BUILD_DIR_BASE)/esp32) + +# Target to generate linker script generator from fragments presented by each of +# the components +$(eval $(call ldgen_process_template, $(ESP32_LINKER_SCRIPT_TEMPLATE), $(ESP32_LINKER_SCRIPT_OUTPUT_DIR)/esp32.common.ld)) diff --git a/components/esp32/component.mk b/components/esp32/component.mk index 605bb56373..54d4a2a5c5 100644 --- a/components/esp32/component.mk +++ b/components/esp32/component.mk @@ -16,7 +16,7 @@ endif #Linker scripts used to link the final application. #Warning: These linker scripts are only used when the normal app is compiled; the bootloader #specifies its own scripts. -LINKER_SCRIPTS += esp32.common.ld esp32.rom.ld esp32.peripherals.ld +LINKER_SCRIPTS += $(COMPONENT_BUILD_DIR)/esp32.common.ld esp32.rom.ld esp32.peripherals.ld #Force pure functions from libgcc.a to be linked from ROM LINKER_SCRIPTS += esp32.rom.libgcc.ld @@ -35,7 +35,7 @@ ifndef CONFIG_SPI_FLASH_ROM_DRIVER_PATCH LINKER_SCRIPTS += esp32.rom.spiflash.ld endif -#ld_include_panic_highint_hdl is added as an undefined symbol because otherwise the +#ld_include_panic_highint_hdl is added as an undefined symbol because otherwise the #linker will ignore panic_highint_hdl.S as it has no other files depending on any #symbols in it. COMPONENT_ADD_LDFLAGS += $(COMPONENT_PATH)/libhal.a \ @@ -44,7 +44,9 @@ COMPONENT_ADD_LDFLAGS += $(COMPONENT_PATH)/libhal.a \ -L $(COMPONENT_PATH)/ld \ -T esp32_out.ld \ -u ld_include_panic_highint_hdl \ - $(addprefix -T ,$(LINKER_SCRIPTS)) + $(addprefix -T ,$(LINKER_SCRIPTS)) \ + +COMPONENT_ADD_LDFRAGMENTS += ld/esp32_fragments.lf linker.lf ALL_LIB_FILES := $(patsubst %,$(COMPONENT_PATH)/lib/lib%.a,$(LIBS)) @@ -52,7 +54,9 @@ COMPONENT_SUBMODULES += lib # final linking of project ELF depends on all binary libraries, and # all linker scripts (except esp32_out.ld, as this is code generated here.) -COMPONENT_ADD_LINKER_DEPS := $(ALL_LIB_FILES) $(addprefix ld/,$(LINKER_SCRIPTS)) +COMPONENT_ADD_LINKER_DEPS := $(ALL_LIB_FILES) \ + $(addprefix ld/, $(filter-out $(COMPONENT_BUILD_DIR)/esp32.common.ld, $(LINKER_SCRIPTS))) \ + $(COMPONENT_BUILD_DIR)/esp32.common.ld # Preprocess esp32.ld linker script into esp32_out.ld # @@ -63,7 +67,7 @@ $(COMPONENT_LIBRARY): esp32_out.ld esp32_out.ld: $(COMPONENT_PATH)/ld/esp32.ld ../include/sdkconfig.h $(CC) -I ../include -C -P -x c -E $< -o $@ -COMPONENT_EXTRA_CLEAN := esp32_out.ld +COMPONENT_EXTRA_CLEAN := esp32_out.ld $(COMPONENT_BUILD_DIR)/esp32.common.ld # disable stack protection in files which are involved in initialization of that feature stack_check.o: CFLAGS := $(filter-out -fstack-protector%, $(CFLAGS)) diff --git a/components/esp32/ld/esp32.common.ld b/components/esp32/ld/esp32.common.ld.in similarity index 84% rename from components/esp32/ld/esp32.common.ld rename to components/esp32/ld/esp32.common.ld.in index 744fbc2116..a05d829830 100644 --- a/components/esp32/ld/esp32.common.ld +++ b/components/esp32/ld/esp32.common.ld.in @@ -9,7 +9,9 @@ SECTIONS .rtc.text : { . = ALIGN(4); - *(.rtc.literal .rtc.text) + + mapping[rtc_text] + *rtc_wake_stub*.*(.literal .text .literal.* .text.*) _rtc_text_end = ABSOLUTE(.); } > rtc_iram_seg @@ -49,8 +51,9 @@ SECTIONS .rtc.data : { _rtc_data_start = ABSOLUTE(.); - *(.rtc.data) - *(.rtc.rodata) + + mapping[rtc_data] + *rtc_wake_stub*.*(.data .rodata .data.* .rodata.* .bss .bss.*) _rtc_data_end = ABSOLUTE(.); } > rtc_data_location @@ -61,7 +64,9 @@ SECTIONS _rtc_bss_start = ABSOLUTE(.); *rtc_wake_stub*.*(.bss .bss.*) *rtc_wake_stub*.*(COMMON) - *(.rtc.bss) + + mapping[rtc_bss] + _rtc_bss_end = ABSOLUTE(.); } > rtc_data_location @@ -152,22 +157,9 @@ SECTIONS { /* Code marked as runnning out of IRAM */ _iram_text_start = ABSOLUTE(.); - *(.iram1 .iram1.*) - *libesp_ringbuf.a:(.literal .text .literal.* .text.*) - *libfreertos.a:(.literal .text .literal.* .text.*) - *libheap.a:multi_heap.*(.literal .text .literal.* .text.*) - *libheap.a:multi_heap_poisoning.*(.literal .text .literal.* .text.*) - *libesp32.a:panic.*(.literal .text .literal.* .text.*) - *libesp32.a:core_dump.*(.literal .text .literal.* .text.*) - *libapp_trace.a:(.literal .text .literal.* .text.*) - *libxtensa-debug-module.a:eri.*(.literal .text .literal.* .text.*) - *librtc.a:(.literal .text .literal.* .text.*) - *libsoc.a:rtc_*.*(.literal .text .literal.* .text.*) - *libsoc.a:cpu_util.*(.literal .text .literal.* .text.*) - *libhal.a:(.literal .text .literal.* .text.*) - *libgcc.a:lib2funcs.*(.literal .text .literal.* .text.*) - *libspi_flash.a:spi_flash_rom_patch.*(.literal .text .literal.* .text.*) - *libgcov.a:(.literal .text .literal.* .text.*) + + mapping[iram0_text] + INCLUDE esp32.spiram.rom-functions-iram.ld _iram_text_end = ABSOLUTE(.); _iram_end = ABSOLUTE(.); @@ -187,8 +179,6 @@ SECTIONS *libbtdm_app.a:(.data .data.*) . = ALIGN (4); _btdm_data_end = ABSOLUTE(.); - *(.data) - *(.data.*) *(.gnu.linkonce.d.*) *(.data1) *(.sdata) @@ -198,14 +188,9 @@ SECTIONS *(.sdata2.*) *(.gnu.linkonce.s2.*) *(.jcr) - *(.dram1 .dram1.*) - *libesp32.a:panic.*(.rodata .rodata.*) - *libphy.a:(.rodata .rodata.*) - *libsoc.a:rtc_clk.*(.rodata .rodata.*) - *libapp_trace.a:(.rodata .rodata.*) - *libgcov.a:(.rodata .rodata.*) - *libheap.a:multi_heap.*(.rodata .rodata.*) - *libheap.a:multi_heap_poisoning.*(.rodata .rodata.*) + + mapping[dram0_data] + INCLUDE esp32.spiram.rom-functions-dram.ld _data_end = ABSOLUTE(.); . = ALIGN(4); @@ -239,6 +224,9 @@ SECTIONS *libbtdm_app.a:(.bss .bss.* COMMON) . = ALIGN (4); _btdm_bss_end = ABSOLUTE(.); + + mapping[dram0_bss] + *(.dynsbss) *(.sbss) *(.sbss.*) @@ -248,11 +236,9 @@ SECTIONS *(.sbss2.*) *(.gnu.linkonce.sb2.*) *(.dynbss) - *(.bss) - *(.bss.*) *(.share.mem) *(.gnu.linkonce.b.*) - *(COMMON) + . = ALIGN (8); _bss_end = ABSOLUTE(.); /* The heap starts right after end of this section */ @@ -265,8 +251,9 @@ SECTIONS .flash.rodata : { _rodata_start = ABSOLUTE(.); - *(.rodata) - *(.rodata.*) + + mapping[flash_rodata] + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ *(.gnu.linkonce.r.*) *(.rodata1) @@ -324,7 +311,10 @@ SECTIONS { _stext = .; _text_start = ABSOLUTE(.); - *(.literal .text .literal.* .text.* .stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + + mapping[flash_text] + + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ *(.fini.literal) *(.fini) diff --git a/components/esp32/ld/esp32_fragments.lf b/components/esp32/ld/esp32_fragments.lf new file mode 100644 index 0000000000..65063f5bcb --- /dev/null +++ b/components/esp32/ld/esp32_fragments.lf @@ -0,0 +1,80 @@ +[sections:text] +entries: + .text+ + .literal+ + +[sections:data] +entries: + .data+ + +[sections:bss] +entries: + .bss+ + +[sections:common] +entries: + COMMON + +[sections:rodata] +entries: + .rodata+ + +[sections:rtc_text] +entries: + .rtc.text + .rtc.literal + +[sections:rtc_data] +entries: + .rtc.data + +[sections:rtc_rodata] +entries: + .rtc.rodata + +[sections:rtc_bss] +entries: + .rtc.bss + +[sections:iram] +entries: + .iram1+ + +[sections:dram] +entries: + .dram1+ + +[scheme:default] +entries: + text -> flash_text + rodata -> flash_rodata + data -> dram0_data + bss -> dram0_bss + common -> dram0_bss + iram -> iram0_text + dram -> dram0_data + rtc_text -> rtc_text + rtc_data -> rtc_data + rtc_rodata -> rtc_data + rtc_bss -> rtc_bss + +[scheme:rtc] +entries: + text -> rtc_text + data -> rtc_data + rodata -> rtc_data + bss -> rtc_bss + common -> rtc_bss + +[scheme:noflash] +entries: + text -> iram0_text + rodata -> dram0_data + +[scheme:noflash_data] +entries: + rodata -> dram0_data + +[scheme:noflash_text] +entries: + text -> iram0_text diff --git a/components/esp32/linker.lf b/components/esp32/linker.lf new file mode 100644 index 0000000000..53f4501af8 --- /dev/null +++ b/components/esp32/linker.lf @@ -0,0 +1,30 @@ +[mapping] +archive: libesp32.a +entries: + core_dump (noflash_text) + panic (noflash) + +[mapping] +archive: libphy.a +entries: + * (noflash_data) + +[mapping] +archive: libhal.a +entries: + * (noflash_text) + +[mapping] +archive: librtc.a +entries: + * (noflash_text) + +[mapping] +archive: libgcc.a +entries: + lib2funcs (noflash_text) + +[mapping] +archive: libgcov.a +entries: + * (noflash) diff --git a/components/esp_ringbuf/CMakeLists.txt b/components/esp_ringbuf/CMakeLists.txt index 9117521a27..bba1dfd6d8 100644 --- a/components/esp_ringbuf/CMakeLists.txt +++ b/components/esp_ringbuf/CMakeLists.txt @@ -1,5 +1,6 @@ set(COMPONENT_ADD_INCLUDEDIRS "include") set(COMPONENT_SRCS "ringbuf.c") +set(COMPONENT_ADD_LDFRAGMENTS linker.lf) set(COMPONENT_REQUIRES) diff --git a/components/esp_ringbuf/component.mk b/components/esp_ringbuf/component.mk index e69de29bb2..cb3a3456bd 100644 --- a/components/esp_ringbuf/component.mk +++ b/components/esp_ringbuf/component.mk @@ -0,0 +1 @@ +COMPONENT_ADD_LDFRAGMENTS += linker.lf diff --git a/components/esp_ringbuf/linker.lf b/components/esp_ringbuf/linker.lf new file mode 100644 index 0000000000..374aa4ce72 --- /dev/null +++ b/components/esp_ringbuf/linker.lf @@ -0,0 +1,4 @@ +[mapping] +archive: libesp_ringbuf.a +entries: + * (noflash_text) \ No newline at end of file diff --git a/components/freertos/CMakeLists.txt b/components/freertos/CMakeLists.txt index 1017fc310d..3b0886529f 100644 --- a/components/freertos/CMakeLists.txt +++ b/components/freertos/CMakeLists.txt @@ -20,7 +20,7 @@ set(COMPONENT_SRCS "FreeRTOS-openocd.c" # app_trace is required by FreeRTOS headers only when CONFIG_SYSVIEW_ENABLE=y, # but requirements can't depend on config options, so always require it. set(COMPONENT_REQUIRES app_trace) - +set(COMPONENT_ADD_LDFRAGMENTS linker.lf) register_component() target_link_libraries(freertos "-Wl,--undefined=uxTopUsedPriority") diff --git a/components/freertos/component.mk b/components/freertos/component.mk index 375ee5ae81..dae672e85e 100644 --- a/components/freertos/component.mk +++ b/components/freertos/component.mk @@ -7,3 +7,4 @@ COMPONENT_ADD_INCLUDEDIRS := include COMPONENT_PRIV_INCLUDEDIRS := include/freertos tasks.o event_groups.o timers.o queue.o: CFLAGS += -D_ESP_FREERTOS_INTERNAL +COMPONENT_ADD_LDFRAGMENTS += linker.lf diff --git a/components/freertos/linker.lf b/components/freertos/linker.lf new file mode 100644 index 0000000000..93092b7e80 --- /dev/null +++ b/components/freertos/linker.lf @@ -0,0 +1,5 @@ +[mapping] +archive: libfreertos.a +entries: + * (noflash_text) + diff --git a/components/heap/CMakeLists.txt b/components/heap/CMakeLists.txt index 073635b7a5..c2ff4d50a6 100644 --- a/components/heap/CMakeLists.txt +++ b/components/heap/CMakeLists.txt @@ -12,7 +12,7 @@ if(CONFIG_HEAP_TASK_TRACKING) endif() set(COMPONENT_ADD_INCLUDEDIRS "include") - +set(COMPONENT_ADD_LDFRAGMENTS linker.lf) set(COMPONENT_REQUIRES "") register_component() diff --git a/components/heap/component.mk b/components/heap/component.mk index 77fd799717..7d8ef920af 100644 --- a/components/heap/component.mk +++ b/components/heap/component.mk @@ -20,3 +20,5 @@ WRAP_ARGUMENT := -Wl,--wrap= COMPONENT_ADD_LDFLAGS = -l$(COMPONENT_NAME) $(addprefix $(WRAP_ARGUMENT),$(WRAP_FUNCTIONS)) endif + +COMPONENT_ADD_LDFRAGMENTS += linker.lf diff --git a/components/heap/linker.lf b/components/heap/linker.lf new file mode 100644 index 0000000000..fc79148acc --- /dev/null +++ b/components/heap/linker.lf @@ -0,0 +1,5 @@ +[mapping] +archive: libheap.a +entries: + multi_heap (noflash) + multi_heap_poisoning (noflash) \ No newline at end of file diff --git a/components/soc/CMakeLists.txt b/components/soc/CMakeLists.txt index 0188244a2f..ec532ad872 100644 --- a/components/soc/CMakeLists.txt +++ b/components/soc/CMakeLists.txt @@ -11,5 +11,8 @@ endif() list(APPEND COMPONENT_ADD_INCLUDEDIRS include) list(APPEND COMPONENT_SRCS "src/memory_layout_utils.c") +set(COMPONENT_ADD_LDFRAGMENTS linker.lf) + set(COMPONENT_REQUIRES) + register_component() diff --git a/components/soc/component.mk b/components/soc/component.mk index 99fae13864..e2d9225327 100644 --- a/components/soc/component.mk +++ b/components/soc/component.mk @@ -5,3 +5,4 @@ COMPONENT_SRCDIRS := $(SOC_NAME) src/ COMPONENT_ADD_INCLUDEDIRS := $(SOC_NAME)/include include -include $(COMPONENT_PATH)/$(SOC_NAME)/component.mk +COMPONENT_ADD_LDFRAGMENTS += linker.lf diff --git a/components/soc/linker.lf b/components/soc/linker.lf new file mode 100644 index 0000000000..f9526f1c6a --- /dev/null +++ b/components/soc/linker.lf @@ -0,0 +1,12 @@ +[mapping] +archive: libsoc.a +entries: + cpu_util (noflash_text) + rtc_clk (noflash) + rtc_clk_init (noflash_text) + rtc_init (noflash_text) + rtc_periph (noflash_text) + rtc_pm (noflash_text) + rtc_sleep (noflash_text) + rtc_time (noflash_text) + rtc_wdt (noflash_text) \ No newline at end of file diff --git a/components/spi_flash/CMakeLists.txt b/components/spi_flash/CMakeLists.txt index 0445b53347..fb3ff44eab 100644 --- a/components/spi_flash/CMakeLists.txt +++ b/components/spi_flash/CMakeLists.txt @@ -15,4 +15,6 @@ endif() set(COMPONENT_ADD_INCLUDEDIRS include) set(COMPONENT_REQUIRES) +set(COMPONENT_ADD_LDFRAGMENTS linker.lf) + register_component() diff --git a/components/spi_flash/component.mk b/components/spi_flash/component.mk index d511eedb8e..2ff786e2d5 100644 --- a/components/spi_flash/component.mk +++ b/components/spi_flash/component.mk @@ -1,7 +1,8 @@ COMPONENT_ADD_INCLUDEDIRS := include +COMPONENT_ADD_LDFRAGMENTS += linker.lf + ifdef IS_BOOTLOADER_BUILD # Bootloader needs updated SPIUnlock from this file COMPONENT_OBJS := spi_flash_rom_patch.o endif - diff --git a/components/spi_flash/linker.lf b/components/spi_flash/linker.lf new file mode 100644 index 0000000000..35ad334ba0 --- /dev/null +++ b/components/spi_flash/linker.lf @@ -0,0 +1,5 @@ +[mapping] +archive: libspi_flash.a +entries: + spi_flash_rom_patch (noflash_text) + diff --git a/components/xtensa-debug-module/CMakeLists.txt b/components/xtensa-debug-module/CMakeLists.txt index 465690d822..d485366ce4 100644 --- a/components/xtensa-debug-module/CMakeLists.txt +++ b/components/xtensa-debug-module/CMakeLists.txt @@ -4,4 +4,6 @@ set(COMPONENT_ADD_INCLUDEDIRS "include") set(COMPONENT_REQUIRES "") +set(COMPONENT_ADD_LDFRAGMENTS linker.lf) + register_component() diff --git a/components/xtensa-debug-module/component.mk b/components/xtensa-debug-module/component.mk index 308f64f0ea..5d39676e29 100644 --- a/components/xtensa-debug-module/component.mk +++ b/components/xtensa-debug-module/component.mk @@ -2,3 +2,4 @@ # Component Makefile # # (Uses default behaviour of compiling all source files in directory, adding 'include' to include path.) +COMPONENT_ADD_LDFRAGMENTS += linker.lf diff --git a/components/xtensa-debug-module/linker.lf b/components/xtensa-debug-module/linker.lf new file mode 100644 index 0000000000..44dea6263d --- /dev/null +++ b/components/xtensa-debug-module/linker.lf @@ -0,0 +1,4 @@ +[mapping] +archive: libxtensa-debug-module.a +entries: + eri (noflash_text) diff --git a/docs/en/api-guides/build-system-cmake.rst b/docs/en/api-guides/build-system-cmake.rst index 0d8b0a07c0..3cd1465e8d 100644 --- a/docs/en/api-guides/build-system-cmake.rst +++ b/docs/en/api-guides/build-system-cmake.rst @@ -350,6 +350,7 @@ The following variables can be set inside ``component.mk`` to control the build ``*.c``, ``*.S``). Source files are globbed from the listed directories and compiled as part of the component in place of ``COMPONENT_SRCS``, i.e. setting this will cause ``COMPONENT_SRCS`` to be ignored. This can be a convenient way of including source files to the components en masse, but is generally not recommended due to caveats attached to CMake globbing (see `File Globbing & Incremental Builds`). - ``COMPONENT_SRCEXCLUDE``: Paths to source files to exclude from component. Can be set in conjunction with ``COMPONENT_SRCDIRS`` if there is a directory with a large number of source files to include in the component but one or more source files which should not be. Paths can be specified relative to the component directory or absolute. +- ``COMPONENT_ADD_LDFRAGMENTS``: Paths to linker fragment files for the linker script generation functionality. See :doc:`Linker Script Generation `. .. note:: @@ -688,6 +689,14 @@ Place this line after the ``project()`` line in your project CMakeLists.txt file For an example of using this technique, see :example:`protocols/https_request` - the certificate file contents are loaded from the text .pem file at compile time. +Code and Data Placements +------------------------ + +ESP-IDF has a feature called linker script generation that enables components to define where its code and data will be placed in memory through +linker fragment files. These files are processed by the build system, and is used to augment the linker script used for linking +app binary. See :doc:`Linker Script Generation ` for a quick start guide as well as a detailed discussion +of the mechanism. + .. _component-build-full-override: Fully Overriding The Component Build Process diff --git a/docs/en/api-guides/build-system.rst b/docs/en/api-guides/build-system.rst index e1c0c045eb..240ae4bc31 100644 --- a/docs/en/api-guides/build-system.rst +++ b/docs/en/api-guides/build-system.rst @@ -274,6 +274,8 @@ The following variables can be set inside ``component.mk`` to control the build settings. Component-specific additions can be made via ``CXXFLAGS +=``. It is also possible (although not recommended) to override this variable completely for a component. +- ``COMPONENT_ADD_LDFRAGMENTS``: Paths to linker fragment files for the linker + script generation functionality. See :doc:`Linker Script Generation `. To apply compilation flags to a single source file, you can add a variable override as a target, ie:: @@ -570,6 +572,13 @@ The names are generated from the full name of the file, as given in COMPONENT_EM For an example of using this technique, see :example:`protocols/https_request` - the certificate file contents are loaded from the text .pem file at compile time. +Code and Data Placements +------------------------ + +ESP-IDF has a feature called linker script generation that enables components to define where its code and data will be placed in memory through +linker fragment files. These files are processed by the build system, and is used to augment the linker script used for linking +app binary. See :doc:`Linker Script Generation ` for a quick start guide as well as a detailed discussion +of the mechanism. Fully Overriding The Component Makefile --------------------------------------- diff --git a/docs/en/api-guides/index.rst b/docs/en/api-guides/index.rst index cf10446864..0283f555b1 100644 --- a/docs/en/api-guides/index.rst +++ b/docs/en/api-guides/index.rst @@ -30,3 +30,4 @@ API Guides ESP-MESH BluFi External SPI-connected RAM + Linker Script Generation \ No newline at end of file diff --git a/docs/en/api-guides/linker-script-generation.rst b/docs/en/api-guides/linker-script-generation.rst new file mode 100644 index 0000000000..5ec246ffd9 --- /dev/null +++ b/docs/en/api-guides/linker-script-generation.rst @@ -0,0 +1,546 @@ +Linker Script Generation +======================== + +Overview +-------- + +There are several :ref:`memory regions` where code and data can be placed. Usually, code and read-only data are placed in flash regions, +writable data in RAM, etc. A common action is changing where code/data are mapped by default, say placing critical code/rodata in RAM for performance +reasons or placing code/data/rodata in RTC memory for use in a wake stub or the ULP coprocessor. + +IDF provides the ability for defining these placements at the component level using the linker script generation mechanism. The component presents +how it would like to map the input sections of its object files (or even functions/data) through :ref:`linker fragment files`. During app build, +the linker fragment files are collected, parsed and processed; and the :ref:`linker script template` is augmented with +information generated from the fragment files to produce the final linker script. This linker script is then used for the linking +the final app binary. + +Quick Start +------------ + +This section presents a guide for quickly placing code/data to RAM and RTC memory; as well as demonstrating how to make these placements +dependent on project configuration values. In a true quick start fashion, this section glosses over terms and concepts that will be discussed +at a later part of the document. However, whenever it does so, it provides a link to the relevant section on the first mention. + +.. _ldgen-add-fragment-file : + +Preparation +^^^^^^^^^^^ + +Make +"""" + +Create a linker fragment file inside the component directory, which is just a text file with a .lf extension. In order for the build system to collect your fragment file, +add an entry to it from the component, set the variable ``COMPONENT_ADD_LDFRAGMENTS`` to your linker file/s before the ``register_component`` call. + +.. code-block:: make + + # file paths relative to component Makefile + COMPONENT_ADD_LDFRAGMENTS += "path/to/linker_fragment_file.lf" "path/to/another_linker_fragment_file.lf" + +CMake +""""" + +For CMake set the variable ``COMPONENT_ADD_LDFRAGMENTS`` to your linker file/s before the ``register_component`` call. + +.. code-block:: cmake + + # file paths relative to CMakeLists.txt + set(COMPONENT_ADD_LDFRAGMENTS "path/to/linker_fragment_file.lf" "path/to/another_linker_fragment_file.lf") + + register_component() + + +Specifying placements +^^^^^^^^^^^^^^^^^^^^^ + +This mechanism allows specifying placement of the following entities: + + - one or multiple object files within the component + - one or multiple function/variable using their names + - the entire component library + +For the following text, suppose we have the following: + + - a component named ``component`` that is archived as library ``libcomponent.a`` during build + - three object files archived under the library, ``object1.o``, ``object2.o`` and ``object3.o`` + - under ``object1.o``, the function ``function1`` is defined; under ``object2.o``, the function ``function2`` is defined + - there exists configuration ``PERFORMANCE_MODE`` and ``PERFORMANCE_LEVEL`` in one of the IDF KConfig files, with the set value indicated by entries ``CONFIG_PERFORMANCE_MODE`` and ``CONFIG_PERFORMANCE_LEVEL`` in the project sdkconfig + +In the created linker fragment file, we write: + +.. code-block:: none + + [mapping] + archive: libcomponent.a + entries: + +This creates an empty :ref:`mapping fragment`, which doesn't do anything yet. During linking the :ref:`default placements` +will still be used for ``libcomponent.a``, unless the ``entries`` key is populated. + +.. _ldgen-placing-object-files : + +Placing object files +"""""""""""""""""""" + +Suppose the entirety of ``object1.o`` is performance-critical, so it is desirable to place it in RAM. On the other hand, all of ``object2.o`` +contains things to be executed coming out of deep sleep, so it needs to be put under RTC memory. We can write: + +.. code-block:: none + + [mapping] + archive: libcomponent.a + entries: + object1 (noflash) # places all code / read-only data under IRAM/ DRAM + object2 (rtc) # places all code/ data and read-only data under RTC fast memory/ RTC slow memory + +What happens to ``object3.o``? Since it is not specified, default placements are used for ``object3.o``. + +Placing functions/data using their names +"""""""""""""""""""""""""""""""""""""""" + +Continuing our example, suppose that among functions defined under ``object1.o``, only ``function1`` is performance-critical; and under ``object2.o``, +only ``function2`` needs to execute after the chip comes out of deep sleep. This could be accomplished by writing: + +.. code-block:: none + + [mapping] + archive: libcomponent.a + entries: + object1:function1 (noflash) + object2:function2 (rtc) + +The default placements are used for the rest of the functions in ``object1.o`` and ``object2.o`` and the entire ``object3.o``. Something similar +can be achieved for placing data by writing the variable name instead of the function name after ``:``. + +.. warning:: + + There are :ref:`limitations` in placing code/data using their symbol names. In order to ensure proper placements, an alternative would be to group + relevant code and data into source files, and :ref:`use object file placement`. + +Placing entire component +"""""""""""""""""""""""" + +In this example, suppose that the entire component needs to be placed in RAM. This can be written as: + +.. code-block:: none + + [mapping] + archive: libcomponent.a + entries: + * (noflash) + +Similarly, this places the entire component in RTC memory: + +.. code-block:: none + + [mapping] + archive: libcomponent.a + entries: + * (rtc) + +Configuration-dependent placements +"""""""""""""""""""""""""""""""""" + +Suppose that the entire component library should only be placed when ``CONFIG_PERFORMANCE_MODE == y`` in the sdkconfig. This could be written as: + +.. code-block:: none + + [mapping] + archive: libcomponent.a + entries: + : PERFORMANCE_MODE = y + * (noflash) + +In pseudocode, this translates to: + +.. code-block:: none + + if PERFORMANCE_MODE = y + place entire libcomponent.a in RAM + else + use default placements + +It is also possible to have multiple conditions to test. Suppose the following requirements: when ``CONFIG_PERFORMANCE_LEVEL == 1``, only ``object1.o`` is put in RAM; +when ``CONFIG_PERFORMANCE_LEVEL == 2``, ``object1.o`` and ``object2.o``; and when ``CONFIG_PERFORMANCE_LEVEL == 3`` all object files under the archive +are to be put into RAM. When these three are false however, put entire library in RTC memory. This scenario is a bit contrived, but, +it can be written as: + +.. code-block:: none + + [mapping] + archive: libcomponent.a + entries: + : PERFORMANCE_LEVEL = 3 + * (noflash) + : PERFORMANCE_LEVEL = 2 + object1 (noflash) + object2 (noflash) + : PERFORMANCE_LEVEL = 1 + object1 (noflash) + : default + * (rtc) + +Which reads: + +.. code-block:: none + + if CONFIG_PERFORMANCE_LEVEL == 3 + place entire libcomponent.a in RAM + else if CONFIG_PERFORMANCE_LEVEL == 2 + only place object1.o and object2.o in RAM + else if CONFIG_PERFORMANCE_LEVEL == 1 + only place object1.o in RAM + else + place entire libcomponent.a in RTC memory + +The conditions test :ref:`support other operations`. + +.. _ldgen-default-placements: + +The 'default' placements +^^^^^^^^^^^^^^^^^^^^^^^^ + +Up until this point, the term 'default placements' has been mentioned as fallback placements for when the +placement rules ``rtc`` and ``noflash`` are not specified. The tokens ``noflash`` or ``rtc`` are not merely keywords known by the mechanism, but are actually +objects called :ref:`scheme fragments` that are specified by the user. Due to the commonness of these placement use cases, +they are pre-defined in IDF. + +Similarly, there exists a ``default`` scheme fragment which defines what the default placement rules should be, which is discussed :ref:`here`. + +.. note:: + For an example of an IDF component using this feature, see :component_file:`freertos/CMakeLists.txt`. The ``freertos`` component uses this + mechanism to place all code, literal and rodata of all of its object files to the instruction RAM memory region for performance reasons. + +This marks the end of the quick start guide. The following text discusses this mechanism in a little bit more detail, such its components, essential concepts, +the syntax, how it is integrated with the build system, etc. The following sections should be helpful in creating custom mappings or modifying default +behavior. + +Components +---------- + +.. _ldgen-fragment-files : + +Linker Fragment Files +^^^^^^^^^^^^^^^^^^^^^ + +The fragment files contain objects called 'fragments'. These fragments contain pieces of information which, when put together, form +placement rules that tell where to place sections of object files in the output binary. + +Another way of putting it is that processing linker fragment files aims to create the section placement rules inside GNU LD ``SECTIONS`` command. +Where to collect and put these section placement rules is represented internally as a ``target`` token. + +The three types of fragments are discussed below. + +.. note:: + + Fragments have a name property (except mapping fragments) and are known globally. + Fragment naming follows C variable naming rules, i.e. case sensitive, must begin with a letter or underscore, alphanumeric/underscore after + initial characters are allowed, no spaces/special characters. Each type of fragment has its own namespace. In cases where multiple fragments + of the same type and name are encountered, an exception is thrown. + +.. _ldgen-sections-fragment : + +I. Sections +""""""""""" + +Sections fragments defines a list of object file sections that the GCC compiler emits. It may be a default section (e.g. ``.text``, ``.data``) or +it may be user defined section through the ``__attribute__`` keyword. + +The use of an optional '+' indicates the inclusion of the section in the list, as well as sections that start with it. This is the preferred method over listing both explicitly. + +**Syntax** + +.. code-block:: none + + [sections:name] + entries: + .section+ + .section + ... + +**Example** + +.. code-block:: none + + # Non-preferred + [sections:text] + entries: + .text + .text.* + .literal + .literal.* + + # Preferred, equivalent to the one above + [sections:text] + entries: + .text+ # means .text and .text.* + .literal+ # means .literal and .literal.* + +.. _ldgen-scheme-fragment : + +II. Scheme +"""""""""" + +Scheme fragments define what ``target`` a sections fragment is assigned to. + +**Syntax** + +.. code-block:: none + + [scheme:name] + entries: + sections -> target + sections -> target + ... + +**Example** + +.. code-block:: none + + [scheme:noflash] + entries: + text -> iram0_text # the entries under the sections fragment named text will go to iram0_text + rodata -> dram0_data # the entries under the sections fragment named rodata will go to dram0_data + +.. _ldgen-default-scheme: + +**The** ``default`` **scheme** + +There exists a special scheme with the name ``default``. This scheme is special because catch-all placement rules are generated from +its entries. This means that, if one of its entries is ``text -> flash_text``, the placement rule + +.. code-block:: none + + *(.literal .literal.* .text .text.*) + +will be generated for the target ``flash_text``. + +These catch-all rules then effectively serve as fallback rules for those whose mappings were not specified. + +.. note:: + + The ``default scheme`` is defined in :component:`esp32/ld/esp32_fragments.lf`. The ``noflash`` and ``rtc`` scheme fragments which are + built-in schemes referenced in the quick start guide are also defined in this file. + +.. _ldgen-mapping-fragment : + +III. Mapping +"""""""""""" + +Mapping fragments define what scheme fragment to use for mappable entities, i.e. object files, function names, variable names. There are two types of entries +for this fragment: mapping entries and condition entries. + +.. note:: + + Mapping fragments have no explicit name property. Internally, the name is constructed from the value of the archive entry. + +**Syntax** + +.. code-block:: none + + [mapping] + archive: archive # output archive file name, as built (i.e. libxxx.a) + entries: + : condition # condition entry, non-default + object:symbol (scheme) # mapping entry, Type I + object (scheme) # mapping entry, Type II + * (scheme) # mapping entry, Type III + + # optional separation/comments, for readability + + : default # condition entry, default + * (scheme) # mapping entry, Type III + +.. _ldgen-mapping-entries : + +**Mapping Entries** + +There are three types of mapping entries: + + ``Type I`` + The object file name and symbol name are specified. The symbol name can be a function name or a variable name. + + ``Type II`` + Only the object file name is specified. + + ``Type III`` + ``*`` is specified, which is a short-hand for all the object files under the archive. + +To know what a mapping entry means, let us expand a ``Type II`` entry. Originally: + +.. code-block:: none + + object (scheme) + +Then expanding the scheme fragment from its entries definitions, we have: + +.. code-block:: none + + object (sections -> target, + sections -> target, + ...) + +Expanding the sections fragment with its entries definition: + +.. code-block:: none + + object (.section, # given this object file + .section, # put its sections listed here at this + ... -> target, # target + + .section, + .section, # same should be done for these sections + ... -> target, + + ...) # and so on + +.. _ldgen-type3-limitations : + +**On** ``Type I`` **Mapping Entries** + +``Type I`` mapping entry is possible due to compiler flags ``-ffunction-sections`` and ``-ffdata-sections``. If the user opts to remove these flags, then +the ``Type I`` mapping will not work. Furthermore, even if the user does not opt to compile without these flags, there are still limitations +as the implementation is dependent on the emitted output sections. + +For example, with ``-ffunction-sections``, separate sections are emitted for each function; with section names predictably constructed i.e. ``.text.{func_name}`` +and ``.literal.{func_name}``. This is not the case for string literals within the function, as they go to pooled or generated section names. + +With ``-fdata-sections``, for global scope data the compiler predictably emits either ``.data.{var_name}``, ``.rodata.{var_name}`` or ``.bss.{var_name}``; and so ``Type I`` mapping entry works for these. +However, this is not the case for static data declared in function scope, as the generated section name is a result of mangling the variable name with some other information. + +.. _ldgen-condition-entries : + +**Condition Entries** + +Condition entries enable the linker script generation to be configuration-aware. Depending on whether expressions involving configuration values +are true or not, a particular set of mapping entries can be used. The evaluation uses ``eval_string`` from ``:idf_file:`tools/kconfig_new/kconfiglib.py``` and adheres to its required syntax and limitations. + +All mapping entries defined after a condition entry until the next one or the end of the mapping fragment belongs to that condition entry. During processing +conditions are tested sequentially, and the mapping entries under the first condition that evaluates to ``TRUE`` are used. + +A default condition can be defined (though every mapping contains an implicit, empty one), whose mapping entries get used in the event no conditions evaluates to ``TRUE``. + +**Example** + +.. code-block:: none + + [scheme:noflash] + entries: + text -> iram0_text + rodata -> dram0_data + + [mapping:lwip] + archive: liblwip.a + entries: + : LWIP_IRAM_OPTIMIZATION = y # if CONFIG_LWIP_IRAM_OPTIMIZATION is set to 'y' in sdkconfig + ip4:ip4_route_src_hook (noflash) # map ip4.o:ip4_route_src_hook, ip4.o:ip4_route_src and + ip4:ip4_route_src (noflash) # ip4.o:ip4_route using the noflash scheme, which puts + ip4:ip4_route (noflash) # them in RAM + + : default # else no special mapping rules apply + +.. _ldgen-script-templates : + +Linker Script Template +^^^^^^^^^^^^^^^^^^^^^^ + +The linker script template is the skeleton in which the generated placement rules are put into. It is an otherwise ordinary linker script, with a specific marker syntax +that indicates where the generated placement rules are placed. + +**Syntax** + +To reference the placement rules collected under a ``target`` token, the following syntax is used: + +.. code-block:: none + + mapping[target] + +**Example** + +The example below is an excerpt from a possible linker script template. It defines an output section ``.iram0.text``, and inside is a marker referencing +the target ``iram0_text``. + +.. code-block:: none + + .iram0.text : + { + /* Code marked as runnning out of IRAM */ + _iram_text_start = ABSOLUTE(.); + + /* Marker referencing iram0_text */ + mapping[iram0_text] + + INCLUDE esp32.spiram.rom-functions-iram.ld + _iram_text_end = ABSOLUTE(.); + } > iram0_0_seg + +Suppose the generator collected the fragment definitions below: + +.. code-block:: none + + [sections:text] + .text+ + .literal+ + + [sections:iram] + .iram1+ + + [scheme:default] + entries: + text -> flash_text + iram -> iram0_text + + [scheme:noflash] + entries: + text -> iram0_text + + [mapping:freertos] + archive: libfreertos.a + entries: + * (noflash) + +Then the corresponding excerpt from the generated linker script will be as follows: + +.. code-block:: c + + .iram0.text : + { + /* Code marked as runnning out of IRAM */ + _iram_text_start = ABSOLUTE(.); + + /* Placement rules generated from the processed fragments, placed where the marker was in the template */ + *(.iram1 .iram1.*) + *libfreertos.a:(.literal .text .literal.* .text.*) + + INCLUDE esp32.spiram.rom-functions-iram.ld + _iram_text_end = ABSOLUTE(.); + } > iram0_0_seg + +``*libfreertos.a:(.literal .text .literal.* .text.*)`` + + Rule generated from the entry ``* (noflash)`` of the ``freertos`` mapping fragment. All ``text`` sections of all + object files under the archive ``libfreertos.a`` will be collected under the target ``iram0_text`` (as per the ``noflash`` scheme) + and placed wherever in the template ``iram0_text`` is referenced by a marker. + +``*(.iram1 .iram1.*)`` + + Rule generated from the default scheme entry ``iram -> iram0_text``. Since the default scheme specifies an ``iram -> iram0_text`` entry, + it too is placed wherever ``iram0_text`` is referenced by a marker. Since it is a rule generated from the default scheme, it comes first + among all other rules collected under the same target name. + + +Integration with Build System +----------------------------- + +The linker script generation occurs during application build, before the final output binary is linked. The tool that implements the mechanism +lives under ``$(IDF_PATH)/tools/ldgen``. + +Linker Script Template +^^^^^^^^^^^^^^^^^^^^^^ +Currently, the linker script template used is :component:`esp32/ld/esp32.common.ld.in`, and is used only for the app build. The generated output script is +put under the build directory of the same component. Modifying this linker script template triggers a re-link of the app binary. + +Linker Fragment File +^^^^^^^^^^^^^^^^^^^^ +Any component can add a fragment file to the build. In order to add a fragment file to process, use the command ``ldgen_add_fragment_file`` as mentioned :ref:`here`. +Modifying any fragment file presented to the build system triggers a re-link of the app binary. diff --git a/docs/zh_CN/api-guides/index.rst b/docs/zh_CN/api-guides/index.rst index bd4d6ee5c5..6509721289 100644 --- a/docs/zh_CN/api-guides/index.rst +++ b/docs/zh_CN/api-guides/index.rst @@ -30,3 +30,4 @@ API 指南 ESP-MESH BluFi External SPI-connected RAM + Linker Script Generation diff --git a/docs/zh_CN/api-guides/linker-script-generation.rst b/docs/zh_CN/api-guides/linker-script-generation.rst new file mode 100644 index 0000000000..00802895c7 --- /dev/null +++ b/docs/zh_CN/api-guides/linker-script-generation.rst @@ -0,0 +1 @@ +.. include:: ../../en/api-guides/linker-script-generation.rst diff --git a/make/component_wrapper.mk b/make/component_wrapper.mk index a545074728..449ad9fc73 100644 --- a/make/component_wrapper.mk +++ b/make/component_wrapper.mk @@ -46,6 +46,10 @@ COMPONENT_EMBED_TXTFILES ?= COMPONENT_ADD_INCLUDEDIRS = include COMPONENT_ADD_LDFLAGS = -l$(COMPONENT_NAME) +# Name of the linker fragment files this component presents to the Linker +# script generator +COMPONENT_ADD_LDFRAGMENTS ?= + # Define optional compiling macros define compile_exclude COMPONENT_OBJEXCLUDE += $(1) @@ -151,6 +155,8 @@ OWN_INCLUDES:=$(abspath $(addprefix $(COMPONENT_PATH)/,$(COMPONENT_PRIV_INCLUDED COMPONENT_INCLUDES := $(OWN_INCLUDES) $(filter-out $(OWN_INCLUDES),$(COMPONENT_INCLUDES)) +include $(IDF_PATH)/make/ldgen.mk + ################################################################################ # 4) Define a target to generate component_project_vars.mk Makefile which # contains common per-component settings which are included directly in the @@ -193,8 +199,8 @@ component_project_vars.mk:: @echo 'COMPONENT_LINKER_DEPS += $(call MakeVariablePath,$(call resolvepath,$(COMPONENT_ADD_LINKER_DEPS),$(COMPONENT_PATH)))' >> $@ @echo 'COMPONENT_SUBMODULES += $(call MakeVariablePath,$(abspath $(addprefix $(COMPONENT_PATH)/,$(COMPONENT_SUBMODULES))))' >> $@ @echo 'COMPONENT_LIBRARIES += $(COMPONENT_NAME)' >> $@ + @echo 'COMPONENT_LDFRAGMENTS += $(call MakeVariablePath,$(abspath $(addprefix $(COMPONENT_PATH)/,$(COMPONENT_ADD_LDFRAGMENTS))))' >> $@ @echo 'component-$(COMPONENT_NAME)-build: $(addprefix component-,$(addsuffix -build,$(COMPONENT_DEPENDS)))' >> $@ - ################################################################################ # 5) Where COMPONENT_OWNBUILDTARGET / COMPONENT_OWNCLEANTARGET # is not set by component.mk, define default build, clean, etc. targets @@ -212,7 +218,7 @@ build: $(COMPONENT_LIBRARY) $(COMPONENT_LIBRARY): $(COMPONENT_OBJS) $(COMPONENT_EMBED_OBJS) $(summary) AR $(patsubst $(PWD)/%,%,$(CURDIR))/$@ rm -f $@ - $(AR) $(ARFLAGS) $@ $^ + $(AR) $(ARFLAGS) $@ $(COMPONENT_OBJS) $(COMPONENT_EMBED_OBJS) endif # If COMPONENT_OWNCLEANTARGET is not set, define a phony clean target @@ -332,7 +338,7 @@ clean: $(summary) RM component_project_vars.mk rm -f component_project_vars.mk -component_project_vars.mk:: # no need to add variables via component.mk +component_project_vars.mk:: # no need to add variables via component.mk @echo '# COMPONENT_CONFIG_ONLY target sets no variables here' > $@ endif # COMPONENT_CONFIG_ONLY diff --git a/make/ldgen.mk b/make/ldgen.mk new file mode 100644 index 0000000000..8e9e8e78a0 --- /dev/null +++ b/make/ldgen.mk @@ -0,0 +1,37 @@ +# Makefile to support the linker script generation mechanism + +LDGEN_SECTIONS_INFO_FILES = $(foreach lib, $(COMPONENT_LIBRARIES), $(BUILD_DIR_BASE)/$(lib)/lib$(lib).a.sections_info) +LDGEN_FRAGMENT_FILES = $(COMPONENT_LDFRAGMENTS) + +# Target to generate linker script generator from fragments presented by each of +# the components +define ldgen_process_template +$(2): $(1) $(LDGEN_FRAGMENT_FILES) $(SDKCONFIG) $(LDGEN_SECTIONS_INFO_FILES) + @echo 'Generating $(notdir $(2))' + $(PYTHON) $(IDF_PATH)/tools/ldgen/ldgen.py \ + --input $(1) \ + --config $(SDKCONFIG) \ + --fragments $(LDGEN_FRAGMENT_FILES) \ + --output $(2) \ + --sections $(LDGEN_SECTIONS_INFO_FILES) \ + --kconfig $(IDF_PATH)/Kconfig \ + --env "COMPONENT_KCONFIGS=$(COMPONENT_KCONFIGS)" \ + --env "COMPONENT_KCONFIGS_PROJBUILD=$(COMPONENT_KCONFIGS_PROJBUILD)" \ + --env "IDF_CMAKE=n" + --env "IDF_TARGET=$(IDF_TARGET)" +endef + +define ldgen_create_commands +$(foreach lib, $(COMPONENT_LIBRARIES), \ + $(eval $(call ldgen_generate_target_sections_info, $(BUILD_DIR_BASE)/$(lib)/lib$(lib).a))) + +ldgen-clean: + rm -f $(LDGEN_SECTIONS_INFO_FILES) +endef + +# Target to generate sections info file from objdump of component archive +define ldgen_generate_target_sections_info +$(1).sections_info: $(1) + @echo 'Generating $(notdir $(1).sections_info)' + $(OBJDUMP) -h $(1) > $(1).sections_info +endef diff --git a/make/project.mk b/make/project.mk index be7521b589..cf5548c0ce 100644 --- a/make/project.mk +++ b/make/project.mk @@ -204,6 +204,7 @@ COMPONENT_INCLUDES := COMPONENT_LDFLAGS := COMPONENT_SUBMODULES := COMPONENT_LIBRARIES := +COMPONENT_LDFRAGMENTS := # COMPONENT_PROJECT_VARS is the list of component_project_vars.mk generated makefiles # for each component. @@ -381,6 +382,7 @@ CC ?= gcc LD ?= ld AR ?= ar OBJCOPY ?= objcopy +OBJDUMP ?= objdump SIZE ?= size # Set host compiler and binutils @@ -398,8 +400,9 @@ CXX := $(call dequote,$(CONFIG_TOOLPREFIX))c++ LD := $(call dequote,$(CONFIG_TOOLPREFIX))ld AR := $(call dequote,$(CONFIG_TOOLPREFIX))ar OBJCOPY := $(call dequote,$(CONFIG_TOOLPREFIX))objcopy +OBJDUMP := $(call dequote,$(CONFIG_TOOLPREFIX))objdump SIZE := $(call dequote,$(CONFIG_TOOLPREFIX))size -export CC CXX LD AR OBJCOPY SIZE +export CC CXX LD AR OBJCOPY OBJDUMP SIZE COMPILER_VERSION_STR := $(shell $(CC) -dumpversion) COMPILER_VERSION_NUM := $(subst .,,$(COMPILER_VERSION_STR)) @@ -416,6 +419,18 @@ APP_ELF:=$(BUILD_DIR_BASE)/$(PROJECT_NAME).elf APP_MAP:=$(APP_ELF:.elf=.map) APP_BIN:=$(APP_ELF:.elf=.bin) +# once we know component paths, we can include the config generation targets +# +# (bootloader build doesn't need this, config is exported from top-level) +ifndef IS_BOOTLOADER_BUILD +include $(IDF_PATH)/make/project_config.mk +endif + +# include linker script generation utils makefile +include $(IDF_PATH)/make/ldgen.mk + +$(eval $(call ldgen_create_commands)) + # Include any Makefile.projbuild file letting components add # configuration at the project level define includeProjBuildMakefile @@ -427,13 +442,6 @@ $(foreach componentpath,$(COMPONENT_PATHS), \ $(if $(wildcard $(componentpath)/Makefile.projbuild), \ $(eval $(call includeProjBuildMakefile,$(componentpath))))) -# once we know component paths, we can include the config generation targets -# -# (bootloader build doesn't need this, config is exported from top-level) -ifndef IS_BOOTLOADER_BUILD -include $(IDF_PATH)/make/project_config.mk -endif - # ELF depends on the library archive files for COMPONENT_LIBRARIES # the rules to build these are emitted as part of GenerateComponentTarget below # @@ -538,7 +546,7 @@ endif # _config-clean), so config remains valid during all component clean # targets config-clean: app-clean bootloader-clean -clean: app-clean bootloader-clean config-clean +clean: app-clean bootloader-clean config-clean ldgen-clean # phony target to check if any git submodule listed in COMPONENT_SUBMODULES are missing # or out of date, and exit if so. Components can add paths to this variable. diff --git a/tools/ci/executable-list.txt b/tools/ci/executable-list.txt index 729edc2cf4..65f765fe2e 100644 --- a/tools/ci/executable-list.txt +++ b/tools/ci/executable-list.txt @@ -64,3 +64,6 @@ docs/gen-dxd.py tools/ci/multirun_with_pyenv.sh components/espcoredump/test/test_espcoredump.py components/espcoredump/test/test_espcoredump.sh +tools/ldgen/ldgen.py +tools/ldgen/test/test_fragments.py +tools/ldgen/test/test_generation.py \ No newline at end of file diff --git a/tools/ci/test_build_system.sh b/tools/ci/test_build_system.sh index efc3703b18..394aba510c 100755 --- a/tools/ci/test_build_system.sh +++ b/tools/ci/test_build_system.sh @@ -157,9 +157,16 @@ function run_tests() make assert_rebuilt ${APP_BINS} ${BOOTLOADER_BINS} - print_status "Touching app-only ld file should only re-link app" + print_status "Touching app-only template ld file should only re-link app" take_build_snapshot - touch ${IDF_PATH}/components/esp32/ld/esp32.common.ld + touch ${IDF_PATH}/components/esp32/ld/esp32.common.ld.in + make + assert_rebuilt ${APP_BINS} + assert_not_rebuilt ${BOOTLOADER_BINS} + + print_status "Touching a linker fragment file should trigger re-link of app" # only app linker script is generated by tool for now + take_build_snapshot + touch ${IDF_PATH}/components/esp32/linker.lf make assert_rebuilt ${APP_BINS} assert_not_rebuilt ${BOOTLOADER_BINS} diff --git a/tools/ci/test_build_system_cmake.sh b/tools/ci/test_build_system_cmake.sh index 60efc2f326..1e38e18900 100755 --- a/tools/ci/test_build_system_cmake.sh +++ b/tools/ci/test_build_system_cmake.sh @@ -143,13 +143,23 @@ function run_tests() print_status "Updating app-only ld file should only re-link app" take_build_snapshot - cp ${IDF_PATH}/components/esp32/ld/esp32.common.ld . + cp ${IDF_PATH}/components/esp32/ld/esp32.common.ld.in . sleep 1 # ninja may ignore if the timestamp delta is too low - echo "/* (Build test comment) */" >> ${IDF_PATH}/components/esp32/ld/esp32.common.ld + echo "/* (Build test comment) */" >> ${IDF_PATH}/components/esp32/ld/esp32.common.ld.in idf.py build || failure "Failed to rebuild with modified linker script" assert_rebuilt ${APP_BINS} assert_not_rebuilt ${BOOTLOADER_BINS} - mv esp32.common.ld ${IDF_PATH}/components/esp32/ld/ + mv esp32.common.ld.in ${IDF_PATH}/components/esp32/ld/ + + print_status "Updating fragment file should only re-link app" # only app linker script is generated by tool for now + take_build_snapshot + cp ${IDF_PATH}/components/esp32/ld/esp32_fragments.lf . + sleep 1 # ninja may ignore if the timestamp delta is too low + echo "# (Build test comment)" >> ${IDF_PATH}/components/esp32/ld/esp32_fragments.lf + idf.py build || failure "Failed to rebuild with modified linker fragment file" + assert_rebuilt ${APP_BINS} + assert_not_rebuilt ${BOOTLOADER_BINS} + mv esp32_fragments.lf ${IDF_PATH}/components/esp32/ld/ print_status "sdkconfig update triggers full recompile" clean_build_dir diff --git a/tools/cmake/components.cmake b/tools/cmake/components.cmake index 0a3570518e..8da2c284fa 100644 --- a/tools/cmake/components.cmake +++ b/tools/cmake/components.cmake @@ -107,6 +107,11 @@ function(register_component) target_link_libraries(${component} "-L${CMAKE_CURRENT_BINARY_DIR}") target_link_libraries(${component} "-Wl,--whole-archive -l${component} -Wl,--no-whole-archive") endif() + + if(COMPONENT_ADD_LDFRAGMENTS) + spaces2list(COMPONENT_ADD_LDFRAGMENTS) + ldgen_add_fragment_files(${component} "${COMPONENT_ADD_LDFRAGMENTS}") + endif() endfunction() function(register_config_only_component) diff --git a/tools/cmake/ldgen.cmake b/tools/cmake/ldgen.cmake new file mode 100644 index 0000000000..26ec26f16b --- /dev/null +++ b/tools/cmake/ldgen.cmake @@ -0,0 +1,72 @@ +# Utilities for supporting linker script generation in the build system + +# ldgen_create_target +# +# Create the custom target to attach the fragment files and template files +# for the build to. +function(ldgen_set_variables) + add_custom_target(ldgen_section_infos) + add_custom_target(ldgen DEPENDS ldgen_section_infos) +endfunction() + +# ldgen_add_fragment_file +# +# Add one or more linker fragment files, and append it to the list of fragment +# files found so far. +function(ldgen_add_fragment_files target fragment_files) + spaces2list(fragment_files) + + foreach(fragment_file ${fragment_files}) + get_filename_component(fragment_file_abs_dir ${fragment_file} ABSOLUTE BASE_DIR ${component_dir}) + list(APPEND fragment_files_full_path ${fragment_file_abs_dir}) + endforeach() + + set_property(TARGET ldgen APPEND PROPERTY FRAGMENT_FILES ${fragment_files_full_path}) + + get_filename_component(target_sections_info ${CMAKE_CURRENT_BINARY_DIR}/${target}.sections_info ABSOLUTE) + + add_custom_command( + OUTPUT ${target_sections_info} + COMMAND ${CMAKE_OBJDUMP} $ -h > ${target_sections_info} + DEPENDS ${target} + ) + + add_custom_target(${target}_sections_info DEPENDS ${target_sections_info}) + add_dependencies(ldgen_section_infos ${target}_sections_info) + + set_property(TARGET ldgen_section_infos APPEND PROPERTY SECTIONS_INFO_FILES ${target_sections_info}) +endfunction() + +# ldgen_process_template +# +# Passes a linker script template to the linker script generation tool for +# processing +function(ldgen_process_template template output) + # Create command to invoke the linker script generator tool. + add_custom_command( + OUTPUT ${output} + COMMAND ${IDF_PATH}/tools/ldgen/ldgen.py + --config ${SDKCONFIG} + --fragments "$,\t>" + --input ${template} + --output ${output} + --sections "$,\t>" + --kconfig ${IDF_PATH}/Kconfig + --env "COMPONENT_KCONFIGS=${COMPONENT_KCONFIGS}" + --env "COMPONENT_KCONFIGS_PROJBUILD=${COMPONENT_KCONFIGS_PROJBUILD}" + --env "IDF_CMAKE=y" + --env "IDF_TARGET=${IDF_TARGET}" + DEPENDS ${template} $ ${SDKCONFIG} ldgen_section_infos + ) + + get_filename_component(output_name ${output} NAME) + add_custom_target(ldgen_${output_name}_script DEPENDS ${output}) + add_dependencies(ldgen ldgen_${output_name}_script) +endfunction() + +# ldgen_create_commands +# +# Create the command to generate the output scripts from templates presented. +function(ldgen_add_dependencies executable_name) + add_dependencies(${executable_name} ldgen) +endfunction() \ No newline at end of file diff --git a/tools/cmake/project.cmake b/tools/cmake/project.cmake index 94ea567bb5..74042fd07f 100644 --- a/tools/cmake/project.cmake +++ b/tools/cmake/project.cmake @@ -27,6 +27,7 @@ include(targets) include(kconfig) include(git_submodules) include(idf_functions) +include(ldgen) set_default(PYTHON "python") @@ -131,6 +132,16 @@ macro(project name) ## if project uses git, retrieve revision git_describe(PROJECT_VER "${CMAKE_CURRENT_SOURCE_DIR}") + # + # Add the app executable to the build (has name of PROJECT.elf) + # + idf_add_executable() + + # + # Setup variables for linker script generation + # + ldgen_set_variables() + # Include any top-level project_include.cmake files from components foreach(component ${BUILD_COMPONENT_PATHS}) set(COMPONENT_PATH "${component}") @@ -156,10 +167,9 @@ macro(project name) unset(COMPONENT_NAME) unset(COMPONENT_PATH) - # - # Add the app executable to the build (has name of PROJECT.elf) - # - idf_add_executable() + # At this point the fragment files have been collected, generate + # the commands needed to generate the output linker scripts + ldgen_add_dependencies(${PROJECT_NAME}.elf) # Write project description JSON file make_json_list("${BUILD_COMPONENTS}" build_components_json) diff --git a/tools/cmake/scripts/expand_requirements.cmake b/tools/cmake/scripts/expand_requirements.cmake index f92f62da12..55e293bdd2 100644 --- a/tools/cmake/scripts/expand_requirements.cmake +++ b/tools/cmake/scripts/expand_requirements.cmake @@ -85,6 +85,9 @@ function(require_idf_targets) endif() endfunction() +# Dummy call for ldgen_add_fragment_file +function(ldgen_add_fragment_file files) +endfunction() # expand_component_requirements: Recursively expand a component's requirements, # setting global properties BUILD_COMPONENTS & BUILD_COMPONENT_PATHS and diff --git a/tools/ldgen/__init__.py b/tools/ldgen/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/tools/ldgen/fragments.py b/tools/ldgen/fragments.py new file mode 100644 index 0000000000..f088515299 --- /dev/null +++ b/tools/ldgen/fragments.py @@ -0,0 +1,249 @@ +#!/usr/bin/env python +# +# Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import re +import collections +import sys +import os + +from sdkconfig import SDKConfig +from pyparsing import * + +""" +Fragment file internal representation. Parses and stores instances of the fragment definitions +contained within the file. +""" +class FragmentFileModel(): + + def __init__(self, fragment_file): + path = os.path.realpath(fragment_file.name) + + sections = Sections.get_fragment_grammar() + scheme = Scheme.get_fragment_grammar() + mapping = Mapping.get_fragment_grammar() + + # Each fragment file is composed of sections, scheme or mapping fragments. The grammar + # for each of those objects are defined it the respective classes + parser = OneOrMore(sections | scheme | mapping) + + # Set any text beginnning with # as comment + parser.ignore("#" + restOfLine) + + self.fragments = parser.parseFile(fragment_file, parseAll=True) + + for fragment in self.fragments: + fragment.path = path + +""" +Encapsulates a fragment as defined in the generator syntax. Sets values common to all fragment and performs processing +such as checking the validity of the fragment name and getting the entry values. +""" +class Fragment: + + IDENTIFIER = Word(alphas+"_", alphanums+"_") + ENTITY = Word(alphanums + ".-_$") + + def __init__(self, name, entries): + self.path = None + self.name = name + self.entries = entries + +class Sections(Fragment): + + def __init__(self, name, entries): + Fragment.__init__(self, name, entries) + self._process_entries() + + def _process_entries(self): + # Quietly ignore duplicate entries + self.entries = set(self.entries) + self.entries = list(self.entries) + + """ + Utility function that returns a list of sections given a sections fragment entry, + with the '+' notation and symbol concatenation handled automatically. + """ + @staticmethod + def get_section_data_from_entry(sections_entry, symbol=None): + if not symbol: + sections = list() + sections.append(sections_entry.replace("+", "")) + sections.append(sections_entry.replace("+", ".*")) + return sections + else: + if sections_entry.endswith("+"): + section = sections_entry.replace("+", ".*") + expansion = section.replace(".*", "." + symbol) + return (section, expansion) + else: + return (sections_entry, None) + + @staticmethod + def get_fragment_grammar(): + name = Fragment.IDENTIFIER + header = Suppress("[") + Suppress("sections") + Suppress(":") + name.setResultsName("name") + Suppress("]") + entry = Word(alphanums + "+" + ".") + entries = Suppress("entries") + Suppress(":") + Group(OneOrMore(entry)).setResultsName("entries") + + sections = Group(header + entries) + + sections.setParseAction(lambda t: Sections(t[0].name, t[0].entries)) + + sections.ignore("#" + restOfLine) + + return sections + +""" +Encapsulates a scheme fragment, which defines what target input sections are placed under. +""" +class Scheme(Fragment): + + def __init__(self, name, items): + Fragment.__init__(self, name, items) + self._process_entries() + + def _process_entries(self): + processed = set() + + # Store entries as a set of tuples. Quietly ignores duplicate entries. + for entry in self.entries: + processed.add((entry.sections, entry.target)) + + self.entries = processed + + @staticmethod + def get_fragment_grammar(): + name = Fragment.IDENTIFIER + header = Suppress("[") + Suppress("scheme") + Suppress(":") + name.setResultsName("name") + Suppress("]") + + # Scheme entry in the form 'sections -> target' + sections = Fragment.IDENTIFIER + target = Fragment.IDENTIFIER + entry = Group(sections.setResultsName("sections") + Suppress("->") + target.setResultsName("target")) + + entries = Suppress("entries") + Suppress(":") + Group(OneOrMore(entry)).setResultsName("entries") + + scheme = Group(header + entries) + + scheme.setParseAction(lambda t: Scheme(t[0].name, t[0].entries)) + + scheme.ignore("#" + restOfLine) + + return scheme + +""" +Encapsulates a mapping fragment, which defines what targets the input sections of mappable entties are placed under. +""" +class Mapping(Fragment): + + # Name of the default condition entry + DEFAULT_CONDITION = "default" + MAPPING_ALL_OBJECTS = "*" + + def __init__(self, archive, entries): + self.archive = archive + + # Generate name from archive value by replacing all non-alphanumeric + # characters with underscore + name = Mapping.get_mapping_name_from_archive(self.archive) + Fragment.__init__(self, name, entries) + + self._process_entries() + + def _create_mappings_set(self, mappings): + mapping_set = set() + + for mapping in mappings: + obj = mapping.object + symbol = mapping.symbol + scheme = mapping.scheme + + if symbol == "": + symbol = None + + # Quietly handle duplicate definitions under the same condition + mapping_set.add((obj, symbol, scheme)) + + return mapping_set + + def _process_entries(self): + processed = [] + + for normal_group in self.entries.normal_groups: + # Get the original string of the condition + condition = next(iter(normal_group.condition.asList())).strip() + mappings = self._create_mappings_set(normal_group.mappings) + + processed.append((condition, mappings)) + + default_group = self.entries.default_group + mappings = self._create_mappings_set(default_group.mappings) + processed.append(("default", mappings)) + + self.entries = processed + + @staticmethod + def get_mapping_name_from_archive(archive): + return re.sub(r"[^0-9a-zA-Z]+", "_", archive) + + @staticmethod + def get_fragment_grammar(): + + # Match header [mapping] + header = Suppress("[") + Suppress("mapping") + Suppress("]") + + # Define possbile values for input archive and object file + filename = Word(alphanums + "-" + "_") + + # There are three possible patterns for mapping entries: + # obj:symbol (scheme) + # obj (scheme) + # * (scheme) + obj = Fragment.ENTITY.setResultsName("object") + symbol = Suppress(":") + Fragment.IDENTIFIER.setResultsName("symbol") + scheme = Suppress("(") + Fragment.IDENTIFIER.setResultsName("scheme") + Suppress(")") + + pattern1 = Group(obj + symbol + scheme) + pattern2 = Group(obj + scheme) + pattern3 = Group(Literal(Mapping.MAPPING_ALL_OBJECTS).setResultsName("object") + scheme) + + mapping_entry = pattern1 | pattern2 | pattern3 + + # To simplify parsing, classify groups of condition-mapping entry into two types: normal and default + # A normal grouping is one with a non-default condition. The default grouping is one which contains the + # default condition + mapping_entries = Group(ZeroOrMore(mapping_entry)).setResultsName("mappings") + + normal_condition = Suppress(":") + originalTextFor(SDKConfig.get_expression_grammar()) + default_condition = Optional(Suppress(":") + Literal(Mapping.DEFAULT_CONDITION)) + + normal_group = Group(normal_condition.setResultsName("condition") + mapping_entries) + default_group = Group(default_condition + mapping_entries).setResultsName("default_group") + + normal_groups = Group(ZeroOrMore(normal_group)).setResultsName("normal_groups") + + # Any mapping fragment definition can have zero or more normal group and only one default group as a last entry. + archive = Suppress("archive") + Suppress(":") + Fragment.ENTITY.setResultsName("archive") + entries = Suppress("entries") + Suppress(":") + (normal_groups + default_group).setResultsName("entries") + + mapping = Group(header + archive + entries) + + mapping.setParseAction(lambda t: Mapping(t[0].archive, t[0].entries)) + + mapping.ignore("#" + restOfLine) + + return mapping diff --git a/tools/ldgen/generation.py b/tools/ldgen/generation.py new file mode 100644 index 0000000000..f3ee5f2c88 --- /dev/null +++ b/tools/ldgen/generation.py @@ -0,0 +1,643 @@ +#!/usr/bin/env python +# +# Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import re +import collections +import itertools +import os +import subprocess +import fnmatch + +from sdkconfig import SDKConfig +from fragments import FragmentFileModel, Sections, Scheme, Mapping, Fragment +from pyparsing import * + +""" +Encapsulates a generated placement rule placed under a target +""" +class PlacementRule(): + + DEFAULT_SPECIFICITY = 0 + ARCHIVE_SPECIFICITY = 1 + OBJECT_SPECIFICITY = 2 + SYMBOL_SPECIFICITY = 3 + + class __container(): + def __init__(self, content): + self.content = content + + __metadata = collections.namedtuple("__metadata", "excludes expansions expanded") + + def __init__(self, archive, obj, symbol, sections, target): + if archive == "*": + archive = None + + if obj == "*": + obj = None + + self.archive = archive + self.obj = obj + self.symbol = symbol + self.target = target + self.sections = dict() + + self.specificity = 0 + self.specificity += 1 if self.archive else 0 + self.specificity += 1 if (self.obj and not self.obj == '*') else 0 + self.specificity += 1 if self.symbol else 0 + + for section in sections: + section_data = Sections.get_section_data_from_entry(section, self.symbol) + + if not self.symbol: + for s in section_data: + metadata = self.__metadata(self.__container([]), self.__container([]), self.__container(False)) + self.sections[s] = metadata + else: + (section, expansion) = section_data + if expansion: + metadata = self.__metadata(self.__container([]), self.__container([expansion]), self.__container(True)) + self.sections[section] = metadata + + def get_section_names(self): + return self.sections.keys() + + def add_exclusion(self, other, sections_infos = None): + # Utility functions for this method + def do_section_expansion(rule, section): + if section in rule.get_section_names(): + sections_in_obj = sections_infos.get_obj_sections(rule.archive, rule.obj) + + expansions = fnmatch.filter(sections_in_obj, section) + return expansions + + def remove_section_expansions(rule, section, expansions): + existing_expansions = self.sections[section].expansions.content + self.sections[section].expansions.content = [e for e in existing_expansions if e not in expansions] + + # Exit immediately if the exclusion to be added is more general than this rule. + if not other.is_more_specific_rule_of(self): + return + + for section in self.get_sections_intersection(other): + if(other.specificity == PlacementRule.SYMBOL_SPECIFICITY): + # If this sections has not been expanded previously, expand now and keep track. + previously_expanded = self.sections[section].expanded.content + if not previously_expanded: + expansions = do_section_expansion(self, section) + if expansions: + self.sections[section].expansions.content = expansions + self.sections[section].expanded.content = True + previously_expanded = True + + # Remove the sections corresponding to the symbol name + remove_section_expansions(self, section, other.sections[section].expansions.content) + + # If it has been expanded previously but now the expansions list is empty, + # it means adding exclusions has exhausted the list. Remove the section entirely. + if previously_expanded and not self.sections[section].expanded.content: + del self.sections[section] + else: + # A rule section can have multiple rule sections excluded from it. Get the + # most specific rule from the list, and if an even more specific rule is found, + # replace it entirely. Otherwise, keep appending. + exclusions = self.sections[section].excludes + exclusions_list = exclusions.content if exclusions.content != None else [] + exclusions_to_remove = filter(lambda r: r.is_more_specific_rule_of(other), exclusions_list) + + remaining_exclusions = [e for e in exclusions_list if e not in exclusions_to_remove] + remaining_exclusions.append(other) + + self.sections[section].excludes.content = remaining_exclusions + + def get_sections_intersection(self, other): + return set(self.sections.keys()).intersection(set(other.sections.keys())) + + def is_more_specific_rule_of(self, other): + if (self.specificity <= other.specificity): + return False + + # Compare archive, obj and target + for entity_index in range (1, other.specificity + 1): + if self[entity_index] != other[entity_index] and other[entity_index] != None: + return False + + return True + + def maps_same_entities_as(self, other): + if self.specificity != other.specificity: + return False + + # Compare archive, obj and target + for entity_index in range (1, other.specificity + 1): + if self[entity_index] != other[entity_index] and other[entity_index] != None: + return False + + return True + + def __getitem__(self, key): + if key == PlacementRule.ARCHIVE_SPECIFICITY: + return self.archive + elif key == PlacementRule.OBJECT_SPECIFICITY: + return self.obj + elif key == PlacementRule.SYMBOL_SPECIFICITY: + return self.symbol + else: + return None + + def __str__(self): + sorted_sections = sorted(self.get_section_names()) + + sections_string = list() + + for section in sorted_sections: + exclusions = self.sections[section].excludes.content + + exclusion_string = None + + if exclusions: + exclusion_string = " ".join(map(lambda e: "*" + e.archive + (":" + e.obj + ".*" if e.obj else ""), exclusions)) + exclusion_string = "EXCLUDE_FILE(" + exclusion_string + ")" + else: + exclusion_string = "" + + section_string = None + exclusion_section_string = None + + section_expansions = self.sections[section].expansions.content + section_expanded = self.sections[section].expanded.content + + if section_expansions and section_expanded: + section_string = " ".join(section_expansions) + exclusion_section_string = section_string + else: + section_string = section + exclusion_section_string = exclusion_string + " " + section_string + + sections_string.append(exclusion_section_string) + + sections_string = " ".join(sections_string) + + archive = str(self.archive) if self.archive else "" + obj = (str(self.obj) + (".*" if self.obj else "")) if self.obj else "" + + # Handle output string generation based on information available + if self.specificity == PlacementRule.DEFAULT_SPECIFICITY: + rule_string = "*(%s)" % (sections_string) + elif self.specificity == PlacementRule.ARCHIVE_SPECIFICITY: + rule_string = "*%s:(%s)" % (archive, sections_string) + else: + rule_string = "*%s:%s(%s)" % (archive, obj, sections_string) + + return rule_string + + def __eq__(self, other): + if id(self) == id(other): + return True + + def exclusions_set(exclusions): + exclusions_set = {(e.archive, e.obj, e.symbol, e.target) for e in exclusions} + return exclusions_set + + if self.archive != other.archive: + return False + + if self.obj != other.obj: + return False + + if self.symbol != other.symbol: + return False + + if set(self.sections.keys()) != set(other.sections.keys()): + return False + + for (section, metadata) in self.sections.items(): + + self_meta = metadata + other_meta = other.sections[section] + + if exclusions_set(self_meta.excludes.content) != exclusions_set(other_meta.excludes.content): + return False + + if set(self_meta.expansions.content) != set(other_meta.expansions.content): + return False + + return True + + def __ne__(self, other): + return not self.__eq__(other) + + def __iter__(self): + yield self.archive + yield self.obj + yield self.symbol + raise StopIteration + +""" +Implements generation of placement rules based on collected sections, scheme and mapping fragment. +""" +class GenerationModel: + + DEFAULT_SCHEME = "default" + + def __init__(self): + self.schemes = {} + self.sections = {} + self.mappings = {} + + def _add_mapping_rules(self, archive, obj, symbol, scheme_name, scheme_dict, rules): + # Use an ordinary dictionary to raise exception on non-existing keys + temp_dict = dict(scheme_dict) + + sections_bucket = temp_dict[scheme_name] + + for (target, sections) in sections_bucket.items(): + section_entries = [] + + for section in sections: + section_entries.extend(section.entries) + + rule = PlacementRule(archive, obj, symbol, section_entries, target) + + if not rule in rules: + rules.append(rule) + + def _build_scheme_dictionary(self): + scheme_dictionary = collections.defaultdict(dict) + + # Collect sections into buckets based on target name + for scheme in self.schemes.values(): + sections_bucket = collections.defaultdict(list) + + for (sections_name, target_name) in scheme.entries: + # Get the sections under the bucket 'target_name'. If this bucket does not exist + # is is created automatically + sections_in_bucket = sections_bucket[target_name] + + try: + sections = self.sections[sections_name] + except KeyError: + message = GenerationException.UNDEFINED_REFERENCE + " to sections '" + sections + "'." + raise GenerationException(message, scheme) + + sections_in_bucket.append(sections) + + scheme_dictionary[scheme.name] = sections_bucket + + # Search for and raise exception on first instance of sections mapped to multiple targets + for (scheme_name, sections_bucket) in scheme_dictionary.items(): + for sections_a, sections_b in itertools.combinations(sections_bucket.values(), 2): + set_a = set() + set_b = set() + + for sections in sections_a: + set_a.update(sections.entries) + + for sections in sections_b: + set_b.update(sections.entries) + + intersection = set_a.intersection(set_b) + + # If the intersection is a non-empty set, it means sections are mapped to multiple + # targets. Raise exception. + if intersection: + scheme = self.schemes[scheme_name] + message = "Sections " + str(intersection) + " mapped to multiple targets." + raise GenerationException(message, scheme) + + return scheme_dictionary + + def generate_rules(self, sdkconfig, sections_infos): + placement_rules = collections.defaultdict(list) + + scheme_dictionary = self._build_scheme_dictionary() + + # Generate default rules + default_rules = list() + self._add_mapping_rules(None, None, None, GenerationModel.DEFAULT_SCHEME, scheme_dictionary, default_rules) + + all_mapping_rules = collections.defaultdict(list) + + # Generate rules based on mapping fragments + for mapping in self.mappings.values(): + for (condition, entries) in mapping.entries: + condition_true = False + + # Only non-default condition are evaluated agains sdkconfig model + if condition != Mapping.DEFAULT_CONDITION: + try: + condition_true = sdkconfig.evaluate_expression(condition) + except Exception as e: + raise GenerationException(e.message, mapping) + else: + condition_true = True + + if condition_true: + + mapping_rules = list() + + archive = mapping.archive + for (obj, symbol, scheme_name) in entries: + try: + self._add_mapping_rules(archive, obj, symbol, scheme_name, scheme_dictionary, mapping_rules) + except KeyError: + message = GenerationException.UNDEFINED_REFERENCE + " to scheme '" + scheme_name + "'." + raise GenerationException(message, mapping) + + all_mapping_rules[mapping.name] = mapping_rules + + break # Exit on first condition that evaluates to true + + # Detect rule conflicts + for mapping_rules in all_mapping_rules.items(): + self._detect_conflicts(mapping_rules) + + # Add exclusions + for mapping_rules in all_mapping_rules.values(): + self._create_exclusions(mapping_rules, default_rules, sections_infos) + + # Add the default rules grouped by target + for default_rule in default_rules: + existing_rules = placement_rules[default_rule.target] + if default_rule.get_section_names(): + existing_rules.append(default_rule) + + for mapping_rules in all_mapping_rules.values(): + # Add the mapping rules grouped by target + for mapping_rule in mapping_rules: + existing_rules = placement_rules[mapping_rule.target] + if mapping_rule.get_section_names(): + existing_rules.append(mapping_rule) + + return placement_rules + + def _detect_conflicts(self, rules): + (archive, rules_list) = rules + + for specificity in range(0, PlacementRule.OBJECT_SPECIFICITY + 1): + rules_with_specificity = filter(lambda r: r.specificity == specificity, rules_list) + + for rule_a, rule_b in itertools.combinations(rules_with_specificity, 2): + intersections = rule_a.get_sections_intersection(rule_b) + + if intersections and rule_a.maps_same_entities_as(rule_b): + rules_string = str([str(rule_a), str(rule_b)]) + message = "Rules " + rules_string + " map sections " + str(list(intersections)) + " into multiple targets." + mapping = self.mappings[Mapping.get_mapping_name_from_archive(archive)] + raise GenerationException(message, mapping) + + def _create_extra_rules(self, rules): + # This function generates extra rules for symbol specific rules. The reason for generating extra rules is to isolate, + # as much as possible, rules that require expansion. Particularly, object specific extra rules are generated. + rules_to_process = sorted(rules, key = lambda r: r.specificity) + symbol_specific_rules = list(filter(lambda r: r.specificity == PlacementRule.SYMBOL_SPECIFICITY, rules_to_process)) + + extra_rules = dict() + + for symbol_specific_rule in symbol_specific_rules: + extra_rule_candidate = {s: None for s in symbol_specific_rule.get_section_names()} + + super_rules = filter(lambda r: symbol_specific_rule.is_more_specific_rule_of(r), rules_to_process) + + # Take a look at the existing rules that are more general than the current symbol-specific rule. + # Only generate an extra rule if there is no existing object specific rule for that section + for super_rule in super_rules: + intersections = symbol_specific_rule.get_sections_intersection(super_rule) + for intersection in intersections: + if super_rule.specificity != PlacementRule.OBJECT_SPECIFICITY: + extra_rule_candidate[intersection] = super_rule + else: + extra_rule_candidate[intersection] = None + + # Generate the extra rules for the symbol specific rule section, keeping track of the generated extra rules + for (section, section_rule) in extra_rule_candidate.items(): + if section_rule: + extra_rule = None + extra_rules_key = (symbol_specific_rule.archive, symbol_specific_rule.obj, section_rule.target) + + try: + extra_rule = extra_rules[extra_rules_key] + + if section not in extra_rule.get_section_names(): + new_rule = PlacementRule(extra_rule.archive, extra_rule.obj, extra_rule.symbol, list(extra_rule.get_section_names()) + [section] , extra_rule.target) + extra_rules[extra_rules_key] = new_rule + except KeyError: + extra_rule = PlacementRule(symbol_specific_rule.archive, symbol_specific_rule.obj, None, [section], section_rule.target) + extra_rules[extra_rules_key] = extra_rule + + return extra_rules.values() + + def _create_exclusions(self, mapping_rules, default_rules, sections_info): + rules = list(default_rules) + rules.extend(mapping_rules) + + extra_rules = self._create_extra_rules(rules) + + mapping_rules.extend(extra_rules) + rules.extend(extra_rules) + + # Sort the rules by means of how specific they are. Sort by specificity from lowest to highest + # * -> lib:* -> lib:obj -> lib:obj:symbol + sorted_rules = sorted(rules, key = lambda r: r.specificity) + + # Now that the rules have been sorted, loop through each rule, and then loop + # through rules below it (higher indeces), adding exclusions whenever appropriate. + for general_rule in sorted_rules: + for specific_rule in reversed(sorted_rules): + if (specific_rule.specificity > general_rule.specificity and \ + specific_rule.specificity != PlacementRule.SYMBOL_SPECIFICITY) or \ + (specific_rule.specificity == PlacementRule.SYMBOL_SPECIFICITY and \ + general_rule.specificity == PlacementRule.OBJECT_SPECIFICITY): + general_rule.add_exclusion(specific_rule, sections_info) + + def add_fragments_from_file(self, fragment_file): + for fragment in fragment_file.fragments: + dict_to_append_to = None + + if isinstance(fragment, Scheme): + dict_to_append_to = self.schemes + elif isinstance(fragment, Sections): + dict_to_append_to = self.sections + else: + dict_to_append_to = self.mappings + + # Raise exception when the fragment of the same type is already in the stored fragments + if fragment.name in dict_to_append_to.keys(): + stored = dict_to_append_to[fragment.name].path + new = fragment.path + message = "Duplicate definition of fragment '%s' found in %s and %s." % (fragment.name, stored, new) + raise GenerationException(message) + + dict_to_append_to[fragment.name] = fragment + +""" +Encapsulates a linker script template file. Finds marker syntax and handles replacement to generate the +final output. +""" +class TemplateModel: + + Marker = collections.namedtuple("Marker", "target indent rules") + + def __init__(self, template_file): + self.members = [] + self.file = os.path.realpath(template_file.name) + + self._generate_members(template_file) + + def _generate_members(self, template_file): + lines = template_file.readlines() + + target = Fragment.IDENTIFIER + reference = Suppress("mapping") + Suppress("[") + target.setResultsName("target") + Suppress("]") + pattern = White(" \t").setResultsName("indent") + reference + + # Find the markers in the template file line by line. If line does not match marker grammar, + # set it as a literal to be copied as is to the output file. + for line in lines: + try: + parsed = pattern.parseString(line) + + indent = parsed.indent + target = parsed.target + + marker = TemplateModel.Marker(target, indent, []) + + self.members.append(marker) + except ParseException: + # Does not match marker syntax + self.members.append(line) + + def fill(self, mapping_rules, sdkconfig): + for member in self.members: + target = None + try: + target = member.target + indent = member.indent + rules = member.rules + + del rules[:] + + rules.extend(mapping_rules[target]) + except KeyError: + message = GenerationException.UNDEFINED_REFERENCE + " to target '" + target + "'." + raise GenerationException(message) + except AttributeError as a: + pass + + def write(self, output_file): + # Add information that this is a generated file. + output_file.write("/* Automatically generated file; DO NOT EDIT */\n") + output_file.write("/* Espressif IoT Development Framework Linker Script */\n") + output_file.write("/* Generated from: %s */\n" % self.file) + output_file.write("\n") + + # Do the text replacement + for member in self.members: + try: + indent = member.indent + rules = member.rules + + for rule in rules: + generated_line = "".join([indent, str(rule), '\n']) + output_file.write(generated_line) + except AttributeError: + output_file.write(member) + +""" +Exception for linker script generation failures such as undefined references/ failure to +evaluate conditions, duplicate mappings, etc. +""" +class GenerationException(Exception): + + UNDEFINED_REFERENCE = "Undefined reference" + + def __init__(self, message, fragment=None): + self.fragment = fragment + self.message = message + + def __str__(self): + if self.fragment: + return "%s\nIn fragment '%s' defined in '%s'." % (self.message, self.fragment.name, self.fragment.path) + else: + return self.message + +""" +Encapsulates an output of objdump. Contains information about the static library sections +and names +""" +class SectionsInfo(dict): + + PATH = Optional("/") + ZeroOrMore(Regex(r"[^/.]+") + Literal("/")) + + __info = collections.namedtuple("__info", "filename content") + + def __init__(self): + self.sections = dict() + + def add_sections_info(self, sections_info_file): + first_line = sections_info_file.readline() + + archive = Literal("In archive").suppress() + SectionsInfo.PATH.suppress() + Fragment.ENTITY.setResultsName("archive") + Literal(":").suppress() + parser = archive + + results = None + + try: + results = parser.parseString(first_line) + except ParseException as p: + raise ParseException("File " + sections_info_file.name + " is not a valid sections info file. " + p.message) + + self.sections[results.archive] = SectionsInfo.__info(sections_info_file.name, sections_info_file.read()) + + def _get_infos_from_file(self, info): + # Object file line: '{object}: file format elf32-xtensa-le' + object = Fragment.ENTITY.setResultsName("object") + Literal(":").suppress() + Literal("file format elf32-xtensa-le").suppress() + + # Sections table + header = Suppress(Literal("Sections:") + Literal("Idx") + Literal("Name") + Literal("Size") + Literal("VMA") + Literal("LMA") + Literal("File off") + Literal("Algn")) + entry = Word(nums).suppress() + Fragment.ENTITY + Suppress(OneOrMore(Word(alphanums, exact=8)) + Word(nums + "*") + ZeroOrMore(Word(alphas.upper()) + Optional(Literal(",")))) + + # Content is object file line + sections table + content = Group(object + header + Group(ZeroOrMore(entry)).setResultsName("sections")) + + parser = Group(ZeroOrMore(content)).setResultsName("contents") + + sections_info_text = info.content + results = None + + try: + results = parser.parseString(sections_info_text) + except ParseException as p: + raise ParseException("Unable to parse section info file " + info.filename + ". " + p.message) + + return results + + def get_obj_sections(self, archive, obj): + stored = self.sections[archive] + + # Parse the contents of the sections file + if not isinstance(stored, dict): + parsed = self._get_infos_from_file(stored) + stored = dict() + for content in parsed.contents: + sections = list(map(lambda s: s, content.sections)) + stored[content.object] = sections + self.sections[archive] = stored + + for obj_key in stored.keys(): + if obj_key == obj + ".o" or obj_key == obj + ".c.obj": + return stored[obj_key] diff --git a/tools/ldgen/ldgen.py b/tools/ldgen/ldgen.py new file mode 100755 index 0000000000..bb70950d11 --- /dev/null +++ b/tools/ldgen/ldgen.py @@ -0,0 +1,101 @@ +#!/usr/bin/env python +# +# Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import argparse +import os + +from fragments import FragmentFileModel +from sdkconfig import SDKConfig +from generation import GenerationModel, TemplateModel, SectionsInfo + +def main(): + + argparser = argparse.ArgumentParser(description = "ESP-IDF linker script generator") + + argparser.add_argument( + "--input", "-i", + help = "Linker template file", + type = argparse.FileType("r")) + + argparser.add_argument( + "--fragments", "-f", + type = argparse.FileType("r"), + help = "Input fragment files", + nargs = "+") + + argparser.add_argument( + "--sections", "-s", + type = argparse.FileType("r"), + help = "Library sections info", + nargs = "+") + + argparser.add_argument( + "--output", "-o", + help = "Output linker script", + type = argparse.FileType("w")) + + argparser.add_argument( + "--config", "-c", + help = "Project configuration", + type = argparse.FileType("r")) + + argparser.add_argument( + "--kconfig", "-k", + help = "IDF Kconfig file", + type = argparse.FileType("r")) + + argparser.add_argument( + "--env", "-e", + action='append', default=[], + help='Environment to set when evaluating the config file', metavar='NAME=VAL') + + args = argparser.parse_args() + + input_file = args.input + fragment_files = [] if not args.fragments else args.fragments + config_file = args.config + output_file = args.output + sections_info_files = [] if not args.sections else args.sections + kconfig_file = args.kconfig + + try: + sections_infos = SectionsInfo() + + for sections_info_file in sections_info_files: + sections_infos.add_sections_info(sections_info_file) + + generation_model = GenerationModel() + + for fragment_file in fragment_files: + fragment_file = FragmentFileModel(fragment_file) + generation_model.add_fragments_from_file(fragment_file) + + sdkconfig = SDKConfig(kconfig_file, config_file, args.env) + mapping_rules = generation_model.generate_rules(sdkconfig, sections_infos) + + script_model = TemplateModel(input_file) + script_model.fill(mapping_rules, sdkconfig) + + script_model.write(output_file) + + except Exception, e: + print("linker script generation failed for %s\nERROR: %s" % (input_file.name, e.message)) + # Delete the file so the entire build will fail; and not use an outdated script. + os.remove(output_file.name) + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/tools/ldgen/pyparsing.py b/tools/ldgen/pyparsing.py new file mode 100644 index 0000000000..892f339f75 --- /dev/null +++ b/tools/ldgen/pyparsing.py @@ -0,0 +1,5720 @@ +# module pyparsing.py +# +# Copyright (c) 2003-2016 Paul T. McGuire +# +# Permission is hereby granted, free of charge, to any person obtaining +# a copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sublicense, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice shall be +# included in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +# CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# + +__doc__ = \ +""" +pyparsing module - Classes and methods to define and execute parsing grammars + +The pyparsing module is an alternative approach to creating and executing simple grammars, +vs. the traditional lex/yacc approach, or the use of regular expressions. With pyparsing, you +don't need to learn a new syntax for defining grammars or matching expressions - the parsing module +provides a library of classes that you use to construct the grammar directly in Python. + +Here is a program to parse "Hello, World!" (or any greeting of the form +C{", !"}), built up using L{Word}, L{Literal}, and L{And} elements +(L{'+'} operator gives L{And} expressions, strings are auto-converted to +L{Literal} expressions):: + + from pyparsing import Word, alphas + + # define grammar of a greeting + greet = Word(alphas) + "," + Word(alphas) + "!" + + hello = "Hello, World!" + print (hello, "->", greet.parseString(hello)) + +The program outputs the following:: + + Hello, World! -> ['Hello', ',', 'World', '!'] + +The Python representation of the grammar is quite readable, owing to the self-explanatory +class names, and the use of '+', '|' and '^' operators. + +The L{ParseResults} object returned from L{ParserElement.parseString} can be accessed as a nested list, a dictionary, or an +object with named attributes. + +The pyparsing module handles some of the problems that are typically vexing when writing text parsers: + - extra or missing whitespace (the above program will also handle "Hello,World!", "Hello , World !", etc.) + - quoted strings + - embedded comments +""" + +__version__ = "2.2.0" +__versionTime__ = "06 Mar 2017 02:06 UTC" +__author__ = "Paul McGuire " + +import string +from weakref import ref as wkref +import copy +import sys +import warnings +import re +import sre_constants +import collections +import pprint +import traceback +import types +from datetime import datetime + +try: + from _thread import RLock +except ImportError: + from threading import RLock + +try: + from collections import OrderedDict as _OrderedDict +except ImportError: + try: + from ordereddict import OrderedDict as _OrderedDict + except ImportError: + _OrderedDict = None + +#~ sys.stderr.write( "testing pyparsing module, version %s, %s\n" % (__version__,__versionTime__ ) ) + +__all__ = [ +'And', 'CaselessKeyword', 'CaselessLiteral', 'CharsNotIn', 'Combine', 'Dict', 'Each', 'Empty', +'FollowedBy', 'Forward', 'GoToColumn', 'Group', 'Keyword', 'LineEnd', 'LineStart', 'Literal', +'MatchFirst', 'NoMatch', 'NotAny', 'OneOrMore', 'OnlyOnce', 'Optional', 'Or', +'ParseBaseException', 'ParseElementEnhance', 'ParseException', 'ParseExpression', 'ParseFatalException', +'ParseResults', 'ParseSyntaxException', 'ParserElement', 'QuotedString', 'RecursiveGrammarException', +'Regex', 'SkipTo', 'StringEnd', 'StringStart', 'Suppress', 'Token', 'TokenConverter', +'White', 'Word', 'WordEnd', 'WordStart', 'ZeroOrMore', +'alphanums', 'alphas', 'alphas8bit', 'anyCloseTag', 'anyOpenTag', 'cStyleComment', 'col', +'commaSeparatedList', 'commonHTMLEntity', 'countedArray', 'cppStyleComment', 'dblQuotedString', +'dblSlashComment', 'delimitedList', 'dictOf', 'downcaseTokens', 'empty', 'hexnums', +'htmlComment', 'javaStyleComment', 'line', 'lineEnd', 'lineStart', 'lineno', +'makeHTMLTags', 'makeXMLTags', 'matchOnlyAtCol', 'matchPreviousExpr', 'matchPreviousLiteral', +'nestedExpr', 'nullDebugAction', 'nums', 'oneOf', 'opAssoc', 'operatorPrecedence', 'printables', +'punc8bit', 'pythonStyleComment', 'quotedString', 'removeQuotes', 'replaceHTMLEntity', +'replaceWith', 'restOfLine', 'sglQuotedString', 'srange', 'stringEnd', +'stringStart', 'traceParseAction', 'unicodeString', 'upcaseTokens', 'withAttribute', +'indentedBlock', 'originalTextFor', 'ungroup', 'infixNotation','locatedExpr', 'withClass', +'CloseMatch', 'tokenMap', 'pyparsing_common', +] + +system_version = tuple(sys.version_info)[:3] +PY_3 = system_version[0] == 3 +if PY_3: + _MAX_INT = sys.maxsize + basestring = str + unichr = chr + _ustr = str + + # build list of single arg builtins, that can be used as parse actions + singleArgBuiltins = [sum, len, sorted, reversed, list, tuple, set, any, all, min, max] + +else: + _MAX_INT = sys.maxint + range = xrange + + def _ustr(obj): + """Drop-in replacement for str(obj) that tries to be Unicode friendly. It first tries + str(obj). If that fails with a UnicodeEncodeError, then it tries unicode(obj). It + then < returns the unicode object | encodes it with the default encoding | ... >. + """ + if isinstance(obj,unicode): + return obj + + try: + # If this works, then _ustr(obj) has the same behaviour as str(obj), so + # it won't break any existing code. + return str(obj) + + except UnicodeEncodeError: + # Else encode it + ret = unicode(obj).encode(sys.getdefaultencoding(), 'xmlcharrefreplace') + xmlcharref = Regex(r'&#\d+;') + xmlcharref.setParseAction(lambda t: '\\u' + hex(int(t[0][2:-1]))[2:]) + return xmlcharref.transformString(ret) + + # build list of single arg builtins, tolerant of Python version, that can be used as parse actions + singleArgBuiltins = [] + import __builtin__ + for fname in "sum len sorted reversed list tuple set any all min max".split(): + try: + singleArgBuiltins.append(getattr(__builtin__,fname)) + except AttributeError: + continue + +_generatorType = type((y for y in range(1))) + +def _xml_escape(data): + """Escape &, <, >, ", ', etc. in a string of data.""" + + # ampersand must be replaced first + from_symbols = '&><"\'' + to_symbols = ('&'+s+';' for s in "amp gt lt quot apos".split()) + for from_,to_ in zip(from_symbols, to_symbols): + data = data.replace(from_, to_) + return data + +class _Constants(object): + pass + +alphas = string.ascii_uppercase + string.ascii_lowercase +nums = "0123456789" +hexnums = nums + "ABCDEFabcdef" +alphanums = alphas + nums +_bslash = chr(92) +printables = "".join(c for c in string.printable if c not in string.whitespace) + +class ParseBaseException(Exception): + """base exception class for all parsing runtime exceptions""" + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, pstr, loc=0, msg=None, elem=None ): + self.loc = loc + if msg is None: + self.msg = pstr + self.pstr = "" + else: + self.msg = msg + self.pstr = pstr + self.parserElement = elem + self.args = (pstr, loc, msg) + + @classmethod + def _from_exception(cls, pe): + """ + internal factory method to simplify creating one type of ParseException + from another - avoids having __init__ signature conflicts among subclasses + """ + return cls(pe.pstr, pe.loc, pe.msg, pe.parserElement) + + def __getattr__( self, aname ): + """supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + """ + if( aname == "lineno" ): + return lineno( self.loc, self.pstr ) + elif( aname in ("col", "column") ): + return col( self.loc, self.pstr ) + elif( aname == "line" ): + return line( self.loc, self.pstr ) + else: + raise AttributeError(aname) + + def __str__( self ): + return "%s (at char %d), (line:%d, col:%d)" % \ + ( self.msg, self.loc, self.lineno, self.column ) + def __repr__( self ): + return _ustr(self) + def markInputline( self, markerString = ">!<" ): + """Extracts the exception line from the input string, and marks + the location of the exception with a special symbol. + """ + line_str = self.line + line_column = self.column - 1 + if markerString: + line_str = "".join((line_str[:line_column], + markerString, line_str[line_column:])) + return line_str.strip() + def __dir__(self): + return "lineno col line".split() + dir(type(self)) + +class ParseException(ParseBaseException): + """ + Exception thrown when parse expressions don't match class; + supported attributes by name are: + - lineno - returns the line number of the exception text + - col - returns the column number of the exception text + - line - returns the line containing the exception text + + Example:: + try: + Word(nums).setName("integer").parseString("ABC") + except ParseException as pe: + print(pe) + print("column: {}".format(pe.col)) + + prints:: + Expected integer (at char 0), (line:1, col:1) + column: 1 + """ + pass + +class ParseFatalException(ParseBaseException): + """user-throwable exception thrown when inconsistent parse content + is found; stops all parsing immediately""" + pass + +class ParseSyntaxException(ParseFatalException): + """just like L{ParseFatalException}, but thrown internally when an + L{ErrorStop} ('-' operator) indicates that parsing is to stop + immediately because an unbacktrackable syntax error has been found""" + pass + +#~ class ReparseException(ParseBaseException): + #~ """Experimental class - parse actions can raise this exception to cause + #~ pyparsing to reparse the input string: + #~ - with a modified input string, and/or + #~ - with a modified start location + #~ Set the values of the ReparseException in the constructor, and raise the + #~ exception in a parse action to cause pyparsing to use the new string/location. + #~ Setting the values as None causes no change to be made. + #~ """ + #~ def __init_( self, newstring, restartLoc ): + #~ self.newParseText = newstring + #~ self.reparseLoc = restartLoc + +class RecursiveGrammarException(Exception): + """exception thrown by L{ParserElement.validate} if the grammar could be improperly recursive""" + def __init__( self, parseElementList ): + self.parseElementTrace = parseElementList + + def __str__( self ): + return "RecursiveGrammarException: %s" % self.parseElementTrace + +class _ParseResultsWithOffset(object): + def __init__(self,p1,p2): + self.tup = (p1,p2) + def __getitem__(self,i): + return self.tup[i] + def __repr__(self): + return repr(self.tup[0]) + def setOffset(self,i): + self.tup = (self.tup[0],i) + +class ParseResults(object): + """ + Structured parse results, to provide multiple means of access to the parsed data: + - as a list (C{len(results)}) + - by list index (C{results[0], results[1]}, etc.) + - by attribute (C{results.} - see L{ParserElement.setResultsName}) + + Example:: + integer = Word(nums) + date_str = (integer.setResultsName("year") + '/' + + integer.setResultsName("month") + '/' + + integer.setResultsName("day")) + # equivalent form: + # date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + # parseString returns a ParseResults object + result = date_str.parseString("1999/12/31") + + def test(s, fn=repr): + print("%s -> %s" % (s, fn(eval(s)))) + test("list(result)") + test("result[0]") + test("result['month']") + test("result.day") + test("'month' in result") + test("'minutes' in result") + test("result.dump()", str) + prints:: + list(result) -> ['1999', '/', '12', '/', '31'] + result[0] -> '1999' + result['month'] -> '12' + result.day -> '31' + 'month' in result -> True + 'minutes' in result -> False + result.dump() -> ['1999', '/', '12', '/', '31'] + - day: 31 + - month: 12 + - year: 1999 + """ + def __new__(cls, toklist=None, name=None, asList=True, modal=True ): + if isinstance(toklist, cls): + return toklist + retobj = object.__new__(cls) + retobj.__doinit = True + return retobj + + # Performance tuning: we construct a *lot* of these, so keep this + # constructor as small and fast as possible + def __init__( self, toklist=None, name=None, asList=True, modal=True, isinstance=isinstance ): + if self.__doinit: + self.__doinit = False + self.__name = None + self.__parent = None + self.__accumNames = {} + self.__asList = asList + self.__modal = modal + if toklist is None: + toklist = [] + if isinstance(toklist, list): + self.__toklist = toklist[:] + elif isinstance(toklist, _generatorType): + self.__toklist = list(toklist) + else: + self.__toklist = [toklist] + self.__tokdict = dict() + + if name is not None and name: + if not modal: + self.__accumNames[name] = 0 + if isinstance(name,int): + name = _ustr(name) # will always return a str, but use _ustr for consistency + self.__name = name + if not (isinstance(toklist, (type(None), basestring, list)) and toklist in (None,'',[])): + if isinstance(toklist,basestring): + toklist = [ toklist ] + if asList: + if isinstance(toklist,ParseResults): + self[name] = _ParseResultsWithOffset(toklist.copy(),0) + else: + self[name] = _ParseResultsWithOffset(ParseResults(toklist[0]),0) + self[name].__name = name + else: + try: + self[name] = toklist[0] + except (KeyError,TypeError,IndexError): + self[name] = toklist + + def __getitem__( self, i ): + if isinstance( i, (int,slice) ): + return self.__toklist[i] + else: + if i not in self.__accumNames: + return self.__tokdict[i][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[i] ]) + + def __setitem__( self, k, v, isinstance=isinstance ): + if isinstance(v,_ParseResultsWithOffset): + self.__tokdict[k] = self.__tokdict.get(k,list()) + [v] + sub = v[0] + elif isinstance(k,(int,slice)): + self.__toklist[k] = v + sub = v + else: + self.__tokdict[k] = self.__tokdict.get(k,list()) + [_ParseResultsWithOffset(v,0)] + sub = v + if isinstance(sub,ParseResults): + sub.__parent = wkref(self) + + def __delitem__( self, i ): + if isinstance(i,(int,slice)): + mylen = len( self.__toklist ) + del self.__toklist[i] + + # convert int to slice + if isinstance(i, int): + if i < 0: + i += mylen + i = slice(i, i+1) + # get removed indices + removed = list(range(*i.indices(mylen))) + removed.reverse() + # fixup indices in token dictionary + for name,occurrences in self.__tokdict.items(): + for j in removed: + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position - (position > j)) + else: + del self.__tokdict[i] + + def __contains__( self, k ): + return k in self.__tokdict + + def __len__( self ): return len( self.__toklist ) + def __bool__(self): return ( not not self.__toklist ) + __nonzero__ = __bool__ + def __iter__( self ): return iter( self.__toklist ) + def __reversed__( self ): return iter( self.__toklist[::-1] ) + def _iterkeys( self ): + if hasattr(self.__tokdict, "iterkeys"): + return self.__tokdict.iterkeys() + else: + return iter(self.__tokdict) + + def _itervalues( self ): + return (self[k] for k in self._iterkeys()) + + def _iteritems( self ): + return ((k, self[k]) for k in self._iterkeys()) + + if PY_3: + keys = _iterkeys + """Returns an iterator of all named result keys (Python 3.x only).""" + + values = _itervalues + """Returns an iterator of all named result values (Python 3.x only).""" + + items = _iteritems + """Returns an iterator of all named result key-value tuples (Python 3.x only).""" + + else: + iterkeys = _iterkeys + """Returns an iterator of all named result keys (Python 2.x only).""" + + itervalues = _itervalues + """Returns an iterator of all named result values (Python 2.x only).""" + + iteritems = _iteritems + """Returns an iterator of all named result key-value tuples (Python 2.x only).""" + + def keys( self ): + """Returns all named result keys (as a list in Python 2.x, as an iterator in Python 3.x).""" + return list(self.iterkeys()) + + def values( self ): + """Returns all named result values (as a list in Python 2.x, as an iterator in Python 3.x).""" + return list(self.itervalues()) + + def items( self ): + """Returns all named result key-values (as a list of tuples in Python 2.x, as an iterator in Python 3.x).""" + return list(self.iteritems()) + + def haskeys( self ): + """Since keys() returns an iterator, this method is helpful in bypassing + code that looks for the existence of any defined results names.""" + return bool(self.__tokdict) + + def pop( self, *args, **kwargs): + """ + Removes and returns item at specified index (default=C{last}). + Supports both C{list} and C{dict} semantics for C{pop()}. If passed no + argument or an integer argument, it will use C{list} semantics + and pop tokens from the list of parsed tokens. If passed a + non-integer argument (most likely a string), it will use C{dict} + semantics and pop the corresponding value from any defined + results names. A second default return value argument is + supported, just as in C{dict.pop()}. + + Example:: + def remove_first(tokens): + tokens.pop(0) + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + print(OneOrMore(Word(nums)).addParseAction(remove_first).parseString("0 123 321")) # -> ['123', '321'] + + label = Word(alphas) + patt = label("LABEL") + OneOrMore(Word(nums)) + print(patt.parseString("AAB 123 321").dump()) + + # Use pop() in a parse action to remove named result (note that corresponding value is not + # removed from list form of results) + def remove_LABEL(tokens): + tokens.pop("LABEL") + return tokens + patt.addParseAction(remove_LABEL) + print(patt.parseString("AAB 123 321").dump()) + prints:: + ['AAB', '123', '321'] + - LABEL: AAB + + ['AAB', '123', '321'] + """ + if not args: + args = [-1] + for k,v in kwargs.items(): + if k == 'default': + args = (args[0], v) + else: + raise TypeError("pop() got an unexpected keyword argument '%s'" % k) + if (isinstance(args[0], int) or + len(args) == 1 or + args[0] in self): + index = args[0] + ret = self[index] + del self[index] + return ret + else: + defaultvalue = args[1] + return defaultvalue + + def get(self, key, defaultValue=None): + """ + Returns named result matching the given key, or if there is no + such name, then returns the given C{defaultValue} or C{None} if no + C{defaultValue} is specified. + + Similar to C{dict.get()}. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString("1999/12/31") + print(result.get("year")) # -> '1999' + print(result.get("hour", "not specified")) # -> 'not specified' + print(result.get("hour")) # -> None + """ + if key in self: + return self[key] + else: + return defaultValue + + def insert( self, index, insStr ): + """ + Inserts new element at location index in the list of parsed tokens. + + Similar to C{list.insert()}. + + Example:: + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + + # use a parse action to insert the parse location in the front of the parsed results + def insert_locn(locn, tokens): + tokens.insert(0, locn) + print(OneOrMore(Word(nums)).addParseAction(insert_locn).parseString("0 123 321")) # -> [0, '0', '123', '321'] + """ + self.__toklist.insert(index, insStr) + # fixup indices in token dictionary + for name,occurrences in self.__tokdict.items(): + for k, (value, position) in enumerate(occurrences): + occurrences[k] = _ParseResultsWithOffset(value, position + (position > index)) + + def append( self, item ): + """ + Add single element to end of ParseResults list of elements. + + Example:: + print(OneOrMore(Word(nums)).parseString("0 123 321")) # -> ['0', '123', '321'] + + # use a parse action to compute the sum of the parsed integers, and add it to the end + def append_sum(tokens): + tokens.append(sum(map(int, tokens))) + print(OneOrMore(Word(nums)).addParseAction(append_sum).parseString("0 123 321")) # -> ['0', '123', '321', 444] + """ + self.__toklist.append(item) + + def extend( self, itemseq ): + """ + Add sequence of elements to end of ParseResults list of elements. + + Example:: + patt = OneOrMore(Word(alphas)) + + # use a parse action to append the reverse of the matched strings, to make a palindrome + def make_palindrome(tokens): + tokens.extend(reversed([t[::-1] for t in tokens])) + return ''.join(tokens) + print(patt.addParseAction(make_palindrome).parseString("lskdj sdlkjf lksd")) # -> 'lskdjsdlkjflksddsklfjkldsjdksl' + """ + if isinstance(itemseq, ParseResults): + self += itemseq + else: + self.__toklist.extend(itemseq) + + def clear( self ): + """ + Clear all elements and results names. + """ + del self.__toklist[:] + self.__tokdict.clear() + + def __getattr__( self, name ): + try: + return self[name] + except KeyError: + return "" + + if name in self.__tokdict: + if name not in self.__accumNames: + return self.__tokdict[name][-1][0] + else: + return ParseResults([ v[0] for v in self.__tokdict[name] ]) + else: + return "" + + def __add__( self, other ): + ret = self.copy() + ret += other + return ret + + def __iadd__( self, other ): + if other.__tokdict: + offset = len(self.__toklist) + addoffset = lambda a: offset if a<0 else a+offset + otheritems = other.__tokdict.items() + otherdictitems = [(k, _ParseResultsWithOffset(v[0],addoffset(v[1])) ) + for (k,vlist) in otheritems for v in vlist] + for k,v in otherdictitems: + self[k] = v + if isinstance(v[0],ParseResults): + v[0].__parent = wkref(self) + + self.__toklist += other.__toklist + self.__accumNames.update( other.__accumNames ) + return self + + def __radd__(self, other): + if isinstance(other,int) and other == 0: + # useful for merging many ParseResults using sum() builtin + return self.copy() + else: + # this may raise a TypeError - so be it + return other + self + + def __repr__( self ): + return "(%s, %s)" % ( repr( self.__toklist ), repr( self.__tokdict ) ) + + def __str__( self ): + return '[' + ', '.join(_ustr(i) if isinstance(i, ParseResults) else repr(i) for i in self.__toklist) + ']' + + def _asStringList( self, sep='' ): + out = [] + for item in self.__toklist: + if out and sep: + out.append(sep) + if isinstance( item, ParseResults ): + out += item._asStringList() + else: + out.append( _ustr(item) ) + return out + + def asList( self ): + """ + Returns the parse results as a nested list of matching tokens, all converted to strings. + + Example:: + patt = OneOrMore(Word(alphas)) + result = patt.parseString("sldkj lsdkj sldkj") + # even though the result prints in string-like form, it is actually a pyparsing ParseResults + print(type(result), result) # -> ['sldkj', 'lsdkj', 'sldkj'] + + # Use asList() to create an actual list + result_list = result.asList() + print(type(result_list), result_list) # -> ['sldkj', 'lsdkj', 'sldkj'] + """ + return [res.asList() if isinstance(res,ParseResults) else res for res in self.__toklist] + + def asDict( self ): + """ + Returns the named parse results as a nested dictionary. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString('12/31/1999') + print(type(result), repr(result)) # -> (['12', '/', '31', '/', '1999'], {'day': [('1999', 4)], 'year': [('12', 0)], 'month': [('31', 2)]}) + + result_dict = result.asDict() + print(type(result_dict), repr(result_dict)) # -> {'day': '1999', 'year': '12', 'month': '31'} + + # even though a ParseResults supports dict-like access, sometime you just need to have a dict + import json + print(json.dumps(result)) # -> Exception: TypeError: ... is not JSON serializable + print(json.dumps(result.asDict())) # -> {"month": "31", "day": "1999", "year": "12"} + """ + if PY_3: + item_fn = self.items + else: + item_fn = self.iteritems + + def toItem(obj): + if isinstance(obj, ParseResults): + if obj.haskeys(): + return obj.asDict() + else: + return [toItem(v) for v in obj] + else: + return obj + + return dict((k,toItem(v)) for k,v in item_fn()) + + def copy( self ): + """ + Returns a new copy of a C{ParseResults} object. + """ + ret = ParseResults( self.__toklist ) + ret.__tokdict = self.__tokdict.copy() + ret.__parent = self.__parent + ret.__accumNames.update( self.__accumNames ) + ret.__name = self.__name + return ret + + def asXML( self, doctag=None, namedItemsOnly=False, indent="", formatted=True ): + """ + (Deprecated) Returns the parse results as XML. Tags are created for tokens and lists that have defined results names. + """ + nl = "\n" + out = [] + namedItems = dict((v[1],k) for (k,vlist) in self.__tokdict.items() + for v in vlist) + nextLevelIndent = indent + " " + + # collapse out indents if formatting is not desired + if not formatted: + indent = "" + nextLevelIndent = "" + nl = "" + + selfTag = None + if doctag is not None: + selfTag = doctag + else: + if self.__name: + selfTag = self.__name + + if not selfTag: + if namedItemsOnly: + return "" + else: + selfTag = "ITEM" + + out += [ nl, indent, "<", selfTag, ">" ] + + for i,res in enumerate(self.__toklist): + if isinstance(res,ParseResults): + if i in namedItems: + out += [ res.asXML(namedItems[i], + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + out += [ res.asXML(None, + namedItemsOnly and doctag is None, + nextLevelIndent, + formatted)] + else: + # individual token, see if there is a name for it + resTag = None + if i in namedItems: + resTag = namedItems[i] + if not resTag: + if namedItemsOnly: + continue + else: + resTag = "ITEM" + xmlBodyText = _xml_escape(_ustr(res)) + out += [ nl, nextLevelIndent, "<", resTag, ">", + xmlBodyText, + "" ] + + out += [ nl, indent, "" ] + return "".join(out) + + def __lookup(self,sub): + for k,vlist in self.__tokdict.items(): + for v,loc in vlist: + if sub is v: + return k + return None + + def getName(self): + r""" + Returns the results name for this token expression. Useful when several + different expressions might match at a particular location. + + Example:: + integer = Word(nums) + ssn_expr = Regex(r"\d\d\d-\d\d-\d\d\d\d") + house_number_expr = Suppress('#') + Word(nums, alphanums) + user_data = (Group(house_number_expr)("house_number") + | Group(ssn_expr)("ssn") + | Group(integer)("age")) + user_info = OneOrMore(user_data) + + result = user_info.parseString("22 111-22-3333 #221B") + for item in result: + print(item.getName(), ':', item[0]) + prints:: + age : 22 + ssn : 111-22-3333 + house_number : 221B + """ + if self.__name: + return self.__name + elif self.__parent: + par = self.__parent() + if par: + return par.__lookup(self) + else: + return None + elif (len(self) == 1 and + len(self.__tokdict) == 1 and + next(iter(self.__tokdict.values()))[0][1] in (0,-1)): + return next(iter(self.__tokdict.keys())) + else: + return None + + def dump(self, indent='', depth=0, full=True): + """ + Diagnostic method for listing out the contents of a C{ParseResults}. + Accepts an optional C{indent} argument so that this string can be embedded + in a nested display of other data. + + Example:: + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + result = date_str.parseString('12/31/1999') + print(result.dump()) + prints:: + ['12', '/', '31', '/', '1999'] + - day: 1999 + - month: 31 + - year: 12 + """ + out = [] + NL = '\n' + out.append( indent+_ustr(self.asList()) ) + if full: + if self.haskeys(): + items = sorted((str(k), v) for k,v in self.items()) + for k,v in items: + if out: + out.append(NL) + out.append( "%s%s- %s: " % (indent,(' '*depth), k) ) + if isinstance(v,ParseResults): + if v: + out.append( v.dump(indent,depth+1) ) + else: + out.append(_ustr(v)) + else: + out.append(repr(v)) + elif any(isinstance(vv,ParseResults) for vv in self): + v = self + for i,vv in enumerate(v): + if isinstance(vv,ParseResults): + out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),vv.dump(indent,depth+1) )) + else: + out.append("\n%s%s[%d]:\n%s%s%s" % (indent,(' '*(depth)),i,indent,(' '*(depth+1)),_ustr(vv))) + + return "".join(out) + + def pprint(self, *args, **kwargs): + """ + Pretty-printer for parsed results as a list, using the C{pprint} module. + Accepts additional positional or keyword args as defined for the + C{pprint.pprint} method. (U{http://docs.python.org/3/library/pprint.html#pprint.pprint}) + + Example:: + ident = Word(alphas, alphanums) + num = Word(nums) + func = Forward() + term = ident | num | Group('(' + func + ')') + func <<= ident + Group(Optional(delimitedList(term))) + result = func.parseString("fna a,b,(fnb c,d,200),100") + result.pprint(width=40) + prints:: + ['fna', + ['a', + 'b', + ['(', 'fnb', ['c', 'd', '200'], ')'], + '100']] + """ + pprint.pprint(self.asList(), *args, **kwargs) + + # add support for pickle protocol + def __getstate__(self): + return ( self.__toklist, + ( self.__tokdict.copy(), + self.__parent is not None and self.__parent() or None, + self.__accumNames, + self.__name ) ) + + def __setstate__(self,state): + self.__toklist = state[0] + (self.__tokdict, + par, + inAccumNames, + self.__name) = state[1] + self.__accumNames = {} + self.__accumNames.update(inAccumNames) + if par is not None: + self.__parent = wkref(par) + else: + self.__parent = None + + def __getnewargs__(self): + return self.__toklist, self.__name, self.__asList, self.__modal + + def __dir__(self): + return (dir(type(self)) + list(self.keys())) + +collections.MutableMapping.register(ParseResults) + +def col (loc,strg): + """Returns current column within a string, counting newlines as line separators. + The first column is number 1. + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{ParserElement.parseString}} for more information + on parsing strings containing C{}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + s = strg + return 1 if 0} for more information + on parsing strings containing C{}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + """ + return strg.count("\n",0,loc) + 1 + +def line( loc, strg ): + """Returns the line of text containing loc within a string, counting newlines as line separators. + """ + lastCR = strg.rfind("\n", 0, loc) + nextCR = strg.find("\n", loc) + if nextCR >= 0: + return strg[lastCR+1:nextCR] + else: + return strg[lastCR+1:] + +def _defaultStartDebugAction( instring, loc, expr ): + print (("Match " + _ustr(expr) + " at loc " + _ustr(loc) + "(%d,%d)" % ( lineno(loc,instring), col(loc,instring) ))) + +def _defaultSuccessDebugAction( instring, startloc, endloc, expr, toks ): + print ("Matched " + _ustr(expr) + " -> " + str(toks.asList())) + +def _defaultExceptionDebugAction( instring, loc, expr, exc ): + print ("Exception raised:" + _ustr(exc)) + +def nullDebugAction(*args): + """'Do-nothing' debug action, to suppress debugging output during parsing.""" + pass + +# Only works on Python 3.x - nonlocal is toxic to Python 2 installs +#~ 'decorator to trim function calls to match the arity of the target' +#~ def _trim_arity(func, maxargs=3): + #~ if func in singleArgBuiltins: + #~ return lambda s,l,t: func(t) + #~ limit = 0 + #~ foundArity = False + #~ def wrapper(*args): + #~ nonlocal limit,foundArity + #~ while 1: + #~ try: + #~ ret = func(*args[limit:]) + #~ foundArity = True + #~ return ret + #~ except TypeError: + #~ if limit == maxargs or foundArity: + #~ raise + #~ limit += 1 + #~ continue + #~ return wrapper + +# this version is Python 2.x-3.x cross-compatible +'decorator to trim function calls to match the arity of the target' +def _trim_arity(func, maxargs=2): + if func in singleArgBuiltins: + return lambda s,l,t: func(t) + limit = [0] + foundArity = [False] + + # traceback return data structure changed in Py3.5 - normalize back to plain tuples + if system_version[:2] >= (3,5): + def extract_stack(limit=0): + # special handling for Python 3.5.0 - extra deep call stack by 1 + offset = -3 if system_version == (3,5,0) else -2 + frame_summary = traceback.extract_stack(limit=-offset+limit-1)[offset] + return [(frame_summary.filename, frame_summary.lineno)] + def extract_tb(tb, limit=0): + frames = traceback.extract_tb(tb, limit=limit) + frame_summary = frames[-1] + return [(frame_summary.filename, frame_summary.lineno)] + else: + extract_stack = traceback.extract_stack + extract_tb = traceback.extract_tb + + # synthesize what would be returned by traceback.extract_stack at the call to + # user's parse action 'func', so that we don't incur call penalty at parse time + + LINE_DIFF = 6 + # IF ANY CODE CHANGES, EVEN JUST COMMENTS OR BLANK LINES, BETWEEN THE NEXT LINE AND + # THE CALL TO FUNC INSIDE WRAPPER, LINE_DIFF MUST BE MODIFIED!!!! + this_line = extract_stack(limit=2)[-1] + pa_call_line_synth = (this_line[0], this_line[1]+LINE_DIFF) + + def wrapper(*args): + while 1: + try: + ret = func(*args[limit[0]:]) + foundArity[0] = True + return ret + except TypeError: + # re-raise TypeErrors if they did not come from our arity testing + if foundArity[0]: + raise + else: + try: + tb = sys.exc_info()[-1] + if not extract_tb(tb, limit=2)[-1][:2] == pa_call_line_synth: + raise + finally: + del tb + + if limit[0] <= maxargs: + limit[0] += 1 + continue + raise + + # copy func name to wrapper for sensible debug output + func_name = "" + try: + func_name = getattr(func, '__name__', + getattr(func, '__class__').__name__) + except Exception: + func_name = str(func) + wrapper.__name__ = func_name + + return wrapper + +class ParserElement(object): + """Abstract base level parser element class.""" + DEFAULT_WHITE_CHARS = " \n\t\r" + verbose_stacktrace = False + + @staticmethod + def setDefaultWhitespaceChars( chars ): + r""" + Overrides the default whitespace chars + + Example:: + # default whitespace chars are space, and newline + OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def', 'ghi', 'jkl'] + + # change to just treat newline as significant + ParserElement.setDefaultWhitespaceChars(" \t") + OneOrMore(Word(alphas)).parseString("abc def\nghi jkl") # -> ['abc', 'def'] + """ + ParserElement.DEFAULT_WHITE_CHARS = chars + + @staticmethod + def inlineLiteralsUsing(cls): + """ + Set class to be used for inclusion of string literals into a parser. + + Example:: + # default literal class used is Literal + integer = Word(nums) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] + + + # change to Suppress + ParserElement.inlineLiteralsUsing(Suppress) + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + + date_str.parseString("1999/12/31") # -> ['1999', '12', '31'] + """ + ParserElement._literalStringClass = cls + + def __init__( self, savelist=False ): + self.parseAction = list() + self.failAction = None + #~ self.name = "" # don't define self.name, let subclasses try/except upcall + self.strRepr = None + self.resultsName = None + self.saveAsList = savelist + self.skipWhitespace = True + self.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + self.copyDefaultWhiteChars = True + self.mayReturnEmpty = False # used when checking for left-recursion + self.keepTabs = False + self.ignoreExprs = list() + self.debug = False + self.streamlined = False + self.mayIndexError = True # used to optimize exception handling for subclasses that don't advance parse index + self.errmsg = "" + self.modalResults = True # used to mark results names as modal (report only last) or cumulative (list all) + self.debugActions = ( None, None, None ) #custom debug actions + self.re = None + self.callPreparse = True # used to avoid redundant calls to preParse + self.callDuringTry = False + + def copy( self ): + """ + Make a copy of this C{ParserElement}. Useful for defining different parse actions + for the same parsing pattern, using copies of the original parse element. + + Example:: + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + integerK = integer.copy().addParseAction(lambda toks: toks[0]*1024) + Suppress("K") + integerM = integer.copy().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") + + print(OneOrMore(integerK | integerM | integer).parseString("5K 100 640K 256M")) + prints:: + [5120, 100, 655360, 268435456] + Equivalent form of C{expr.copy()} is just C{expr()}:: + integerM = integer().addParseAction(lambda toks: toks[0]*1024*1024) + Suppress("M") + """ + cpy = copy.copy( self ) + cpy.parseAction = self.parseAction[:] + cpy.ignoreExprs = self.ignoreExprs[:] + if self.copyDefaultWhiteChars: + cpy.whiteChars = ParserElement.DEFAULT_WHITE_CHARS + return cpy + + def setName( self, name ): + """ + Define name for this expression, makes debugging and exception messages clearer. + + Example:: + Word(nums).parseString("ABC") # -> Exception: Expected W:(0123...) (at char 0), (line:1, col:1) + Word(nums).setName("integer").parseString("ABC") # -> Exception: Expected integer (at char 0), (line:1, col:1) + """ + self.name = name + self.errmsg = "Expected " + self.name + if hasattr(self,"exception"): + self.exception.msg = self.errmsg + return self + + def setResultsName( self, name, listAllMatches=False ): + """ + Define name for referencing matching tokens as a nested attribute + of the returned parse results. + NOTE: this returns a *copy* of the original C{ParserElement} object; + this is so that the client can define a basic element, such as an + integer, and reference it in multiple places with different names. + + You can also set results names using the abbreviated syntax, + C{expr("name")} in place of C{expr.setResultsName("name")} - + see L{I{__call__}<__call__>}. + + Example:: + date_str = (integer.setResultsName("year") + '/' + + integer.setResultsName("month") + '/' + + integer.setResultsName("day")) + + # equivalent form: + date_str = integer("year") + '/' + integer("month") + '/' + integer("day") + """ + newself = self.copy() + if name.endswith("*"): + name = name[:-1] + listAllMatches=True + newself.resultsName = name + newself.modalResults = not listAllMatches + return newself + + def setBreak(self,breakFlag = True): + """Method to invoke the Python pdb debugger when this element is + about to be parsed. Set C{breakFlag} to True to enable, False to + disable. + """ + if breakFlag: + _parseMethod = self._parse + def breaker(instring, loc, doActions=True, callPreParse=True): + import pdb + pdb.set_trace() + return _parseMethod( instring, loc, doActions, callPreParse ) + breaker._originalParseMethod = _parseMethod + self._parse = breaker + else: + if hasattr(self._parse,"_originalParseMethod"): + self._parse = self._parse._originalParseMethod + return self + + def setParseAction( self, *fns, **kwargs ): + """ + Define one or more actions to perform when successfully matching parse element definition. + Parse action fn is a callable method with 0-3 arguments, called as C{fn(s,loc,toks)}, + C{fn(loc,toks)}, C{fn(toks)}, or just C{fn()}, where: + - s = the original string being parsed (see note below) + - loc = the location of the matching substring + - toks = a list of the matched tokens, packaged as a C{L{ParseResults}} object + If the functions in fns modify the tokens, they can return them as the return + value from fn, and the modified list of tokens will replace the original. + Otherwise, fn does not need to return any value. + + Optional keyword arguments: + - callDuringTry = (default=C{False}) indicate if parse action should be run during lookaheads and alternate testing + + Note: the default parsing behavior is to expand tabs in the input string + before starting the parsing process. See L{I{parseString}} for more information + on parsing strings containing C{}s, and suggested methods to maintain a + consistent view of the parsed string, the parse location, and line and column + positions within the parsed string. + + Example:: + integer = Word(nums) + date_str = integer + '/' + integer + '/' + integer + + date_str.parseString("1999/12/31") # -> ['1999', '/', '12', '/', '31'] + + # use parse action to convert to ints at parse time + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + date_str = integer + '/' + integer + '/' + integer + + # note that integer fields are now ints, not strings + date_str.parseString("1999/12/31") # -> [1999, '/', 12, '/', 31] + """ + self.parseAction = list(map(_trim_arity, list(fns))) + self.callDuringTry = kwargs.get("callDuringTry", False) + return self + + def addParseAction( self, *fns, **kwargs ): + """ + Add one or more parse actions to expression's list of parse actions. See L{I{setParseAction}}. + + See examples in L{I{copy}}. + """ + self.parseAction += list(map(_trim_arity, list(fns))) + self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) + return self + + def addCondition(self, *fns, **kwargs): + """Add a boolean predicate function to expression's list of parse actions. See + L{I{setParseAction}} for function call signatures. Unlike C{setParseAction}, + functions passed to C{addCondition} need to return boolean success/fail of the condition. + + Optional keyword arguments: + - message = define a custom message to be used in the raised exception + - fatal = if True, will raise ParseFatalException to stop parsing immediately; otherwise will raise ParseException + + Example:: + integer = Word(nums).setParseAction(lambda toks: int(toks[0])) + year_int = integer.copy() + year_int.addCondition(lambda toks: toks[0] >= 2000, message="Only support years 2000 and later") + date_str = year_int + '/' + integer + '/' + integer + + result = date_str.parseString("1999/12/31") # -> Exception: Only support years 2000 and later (at char 0), (line:1, col:1) + """ + msg = kwargs.get("message", "failed user-defined condition") + exc_type = ParseFatalException if kwargs.get("fatal", False) else ParseException + for fn in fns: + def pa(s,l,t): + if not bool(_trim_arity(fn)(s,l,t)): + raise exc_type(s,l,msg) + self.parseAction.append(pa) + self.callDuringTry = self.callDuringTry or kwargs.get("callDuringTry", False) + return self + + def setFailAction( self, fn ): + """Define action to perform if parsing fails at this expression. + Fail acton fn is a callable function that takes the arguments + C{fn(s,loc,expr,err)} where: + - s = string being parsed + - loc = location where expression match was attempted and failed + - expr = the parse expression that failed + - err = the exception thrown + The function returns no value. It may throw C{L{ParseFatalException}} + if it is desired to stop parsing immediately.""" + self.failAction = fn + return self + + def _skipIgnorables( self, instring, loc ): + exprsFound = True + while exprsFound: + exprsFound = False + for e in self.ignoreExprs: + try: + while 1: + loc,dummy = e._parse( instring, loc ) + exprsFound = True + except ParseException: + pass + return loc + + def preParse( self, instring, loc ): + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + + if self.skipWhitespace: + wt = self.whiteChars + instrlen = len(instring) + while loc < instrlen and instring[loc] in wt: + loc += 1 + + return loc + + def parseImpl( self, instring, loc, doActions=True ): + return loc, [] + + def postParse( self, instring, loc, tokenlist ): + return tokenlist + + #~ @profile + def _parseNoCache( self, instring, loc, doActions=True, callPreParse=True ): + debugging = ( self.debug ) #and doActions ) + + if debugging or self.failAction: + #~ print ("Match",self,"at loc",loc,"(%d,%d)" % ( lineno(loc,instring), col(loc,instring) )) + if (self.debugActions[0] ): + self.debugActions[0]( instring, loc, self ) + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = preloc + try: + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + except ParseBaseException as err: + #~ print ("Exception raised:", err) + if self.debugActions[2]: + self.debugActions[2]( instring, tokensStart, self, err ) + if self.failAction: + self.failAction( instring, tokensStart, self, err ) + raise + else: + if callPreParse and self.callPreparse: + preloc = self.preParse( instring, loc ) + else: + preloc = loc + tokensStart = preloc + if self.mayIndexError or loc >= len(instring): + try: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + except IndexError: + raise ParseException( instring, len(instring), self.errmsg, self ) + else: + loc,tokens = self.parseImpl( instring, preloc, doActions ) + + tokens = self.postParse( instring, loc, tokens ) + + retTokens = ParseResults( tokens, self.resultsName, asList=self.saveAsList, modal=self.modalResults ) + if self.parseAction and (doActions or self.callDuringTry): + if debugging: + try: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + except ParseBaseException as err: + #~ print "Exception raised in user parse action:", err + if (self.debugActions[2] ): + self.debugActions[2]( instring, tokensStart, self, err ) + raise + else: + for fn in self.parseAction: + tokens = fn( instring, tokensStart, retTokens ) + if tokens is not None: + retTokens = ParseResults( tokens, + self.resultsName, + asList=self.saveAsList and isinstance(tokens,(ParseResults,list)), + modal=self.modalResults ) + + if debugging: + #~ print ("Matched",self,"->",retTokens.asList()) + if (self.debugActions[1] ): + self.debugActions[1]( instring, tokensStart, loc, self, retTokens ) + + return loc, retTokens + + def tryParse( self, instring, loc ): + try: + return self._parse( instring, loc, doActions=False )[0] + except ParseFatalException: + raise ParseException( instring, loc, self.errmsg, self) + + def canParseNext(self, instring, loc): + try: + self.tryParse(instring, loc) + except (ParseException, IndexError): + return False + else: + return True + + class _UnboundedCache(object): + def __init__(self): + cache = {} + self.not_in_cache = not_in_cache = object() + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + + def clear(self): + cache.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + if _OrderedDict is not None: + class _FifoCache(object): + def __init__(self, size): + self.not_in_cache = not_in_cache = object() + + cache = _OrderedDict() + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + while len(cache) > size: + try: + cache.popitem(False) + except KeyError: + pass + + def clear(self): + cache.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + else: + class _FifoCache(object): + def __init__(self, size): + self.not_in_cache = not_in_cache = object() + + cache = {} + key_fifo = collections.deque([], size) + + def get(self, key): + return cache.get(key, not_in_cache) + + def set(self, key, value): + cache[key] = value + while len(key_fifo) > size: + cache.pop(key_fifo.popleft(), None) + key_fifo.append(key) + + def clear(self): + cache.clear() + key_fifo.clear() + + def cache_len(self): + return len(cache) + + self.get = types.MethodType(get, self) + self.set = types.MethodType(set, self) + self.clear = types.MethodType(clear, self) + self.__len__ = types.MethodType(cache_len, self) + + # argument cache for optimizing repeated calls when backtracking through recursive expressions + packrat_cache = {} # this is set later by enabledPackrat(); this is here so that resetCache() doesn't fail + packrat_cache_lock = RLock() + packrat_cache_stats = [0, 0] + + # this method gets repeatedly called during backtracking with the same arguments - + # we can cache these arguments and save ourselves the trouble of re-parsing the contained expression + def _parseCache( self, instring, loc, doActions=True, callPreParse=True ): + HIT, MISS = 0, 1 + lookup = (self, instring, loc, callPreParse, doActions) + with ParserElement.packrat_cache_lock: + cache = ParserElement.packrat_cache + value = cache.get(lookup) + if value is cache.not_in_cache: + ParserElement.packrat_cache_stats[MISS] += 1 + try: + value = self._parseNoCache(instring, loc, doActions, callPreParse) + except ParseBaseException as pe: + # cache a copy of the exception, without the traceback + cache.set(lookup, pe.__class__(*pe.args)) + raise + else: + cache.set(lookup, (value[0], value[1].copy())) + return value + else: + ParserElement.packrat_cache_stats[HIT] += 1 + if isinstance(value, Exception): + raise value + return (value[0], value[1].copy()) + + _parse = _parseNoCache + + @staticmethod + def resetCache(): + ParserElement.packrat_cache.clear() + ParserElement.packrat_cache_stats[:] = [0] * len(ParserElement.packrat_cache_stats) + + _packratEnabled = False + @staticmethod + def enablePackrat(cache_size_limit=128): + """Enables "packrat" parsing, which adds memoizing to the parsing logic. + Repeated parse attempts at the same string location (which happens + often in many complex grammars) can immediately return a cached value, + instead of re-executing parsing/validating code. Memoizing is done of + both valid results and parsing exceptions. + + Parameters: + - cache_size_limit - (default=C{128}) - if an integer value is provided + will limit the size of the packrat cache; if None is passed, then + the cache size will be unbounded; if 0 is passed, the cache will + be effectively disabled. + + This speedup may break existing programs that use parse actions that + have side-effects. For this reason, packrat parsing is disabled when + you first import pyparsing. To activate the packrat feature, your + program must call the class method C{ParserElement.enablePackrat()}. If + your program uses C{psyco} to "compile as you go", you must call + C{enablePackrat} before calling C{psyco.full()}. If you do not do this, + Python will crash. For best results, call C{enablePackrat()} immediately + after importing pyparsing. + + Example:: + import pyparsing + pyparsing.ParserElement.enablePackrat() + """ + if not ParserElement._packratEnabled: + ParserElement._packratEnabled = True + if cache_size_limit is None: + ParserElement.packrat_cache = ParserElement._UnboundedCache() + else: + ParserElement.packrat_cache = ParserElement._FifoCache(cache_size_limit) + ParserElement._parse = ParserElement._parseCache + + def parseString( self, instring, parseAll=False ): + """ + Execute the parse expression with the given string. + This is the main interface to the client code, once the complete + expression has been built. + + If you want the grammar to require that the entire input string be + successfully parsed, then set C{parseAll} to True (equivalent to ending + the grammar with C{L{StringEnd()}}). + + Note: C{parseString} implicitly calls C{expandtabs()} on the input string, + in order to report proper column numbers in parse actions. + If the input string contains tabs and + the grammar uses parse actions that use the C{loc} argument to index into the + string being parsed, you can ensure you have a consistent view of the input + string by: + - calling C{parseWithTabs} on your grammar before calling C{parseString} + (see L{I{parseWithTabs}}) + - define your parse action using the full C{(s,loc,toks)} signature, and + reference the input string using the parse action's C{s} argument + - explictly expand the tabs in your input string before calling + C{parseString} + + Example:: + Word('a').parseString('aaaaabaaa') # -> ['aaaaa'] + Word('a').parseString('aaaaabaaa', parseAll=True) # -> Exception: Expected end of text + """ + ParserElement.resetCache() + if not self.streamlined: + self.streamline() + #~ self.saveAsList = True + for e in self.ignoreExprs: + e.streamline() + if not self.keepTabs: + instring = instring.expandtabs() + try: + loc, tokens = self._parse( instring, 0 ) + if parseAll: + loc = self.preParse( instring, loc ) + se = Empty() + StringEnd() + se._parse( instring, loc ) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + else: + return tokens + + def scanString( self, instring, maxMatches=_MAX_INT, overlap=False ): + """ + Scan the input string for expression matches. Each match will return the + matching tokens, start location, and end location. May be called with optional + C{maxMatches} argument, to clip scanning after 'n' matches are found. If + C{overlap} is specified, then overlapping matches will be reported. + + Note that the start and end locations are reported relative to the string + being parsed. See L{I{parseString}} for more information on parsing + strings with embedded tabs. + + Example:: + source = "sldjf123lsdjjkf345sldkjf879lkjsfd987" + print(source) + for tokens,start,end in Word(alphas).scanString(source): + print(' '*start + '^'*(end-start)) + print(' '*start + tokens[0]) + + prints:: + + sldjf123lsdjjkf345sldkjf879lkjsfd987 + ^^^^^ + sldjf + ^^^^^^^ + lsdjjkf + ^^^^^^ + sldkjf + ^^^^^^ + lkjsfd + """ + if not self.streamlined: + self.streamline() + for e in self.ignoreExprs: + e.streamline() + + if not self.keepTabs: + instring = _ustr(instring).expandtabs() + instrlen = len(instring) + loc = 0 + preparseFn = self.preParse + parseFn = self._parse + ParserElement.resetCache() + matches = 0 + try: + while loc <= instrlen and matches < maxMatches: + try: + preloc = preparseFn( instring, loc ) + nextLoc,tokens = parseFn( instring, preloc, callPreParse=False ) + except ParseException: + loc = preloc+1 + else: + if nextLoc > loc: + matches += 1 + yield tokens, preloc, nextLoc + if overlap: + nextloc = preparseFn( instring, loc ) + if nextloc > loc: + loc = nextLoc + else: + loc += 1 + else: + loc = nextLoc + else: + loc = preloc+1 + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def transformString( self, instring ): + """ + Extension to C{L{scanString}}, to modify matching text with modified tokens that may + be returned from a parse action. To use C{transformString}, define a grammar and + attach a parse action to it that modifies the returned token list. + Invoking C{transformString()} on a target string will then scan for matches, + and replace the matched text patterns according to the logic in the parse + action. C{transformString()} returns the resulting transformed string. + + Example:: + wd = Word(alphas) + wd.setParseAction(lambda toks: toks[0].title()) + + print(wd.transformString("now is the winter of our discontent made glorious summer by this sun of york.")) + Prints:: + Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York. + """ + out = [] + lastE = 0 + # force preservation of s, to minimize unwanted transformation of string, and to + # keep string locs straight between transformString and scanString + self.keepTabs = True + try: + for t,s,e in self.scanString( instring ): + out.append( instring[lastE:s] ) + if t: + if isinstance(t,ParseResults): + out += t.asList() + elif isinstance(t,list): + out += t + else: + out.append(t) + lastE = e + out.append(instring[lastE:]) + out = [o for o in out if o] + return "".join(map(_ustr,_flatten(out))) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def searchString( self, instring, maxMatches=_MAX_INT ): + """ + Another extension to C{L{scanString}}, simplifying the access to the tokens found + to match the given parse expression. May be called with optional + C{maxMatches} argument, to clip searching after 'n' matches are found. + + Example:: + # a capitalized word starts with an uppercase letter, followed by zero or more lowercase letters + cap_word = Word(alphas.upper(), alphas.lower()) + + print(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity")) + + # the sum() builtin can be used to merge results into a single ParseResults object + print(sum(cap_word.searchString("More than Iron, more than Lead, more than Gold I need Electricity"))) + prints:: + [['More'], ['Iron'], ['Lead'], ['Gold'], ['I'], ['Electricity']] + ['More', 'Iron', 'Lead', 'Gold', 'I', 'Electricity'] + """ + try: + return ParseResults([ t for t,s,e in self.scanString( instring, maxMatches ) ]) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def split(self, instring, maxsplit=_MAX_INT, includeSeparators=False): + """ + Generator method to split a string using the given expression as a separator. + May be called with optional C{maxsplit} argument, to limit the number of splits; + and the optional C{includeSeparators} argument (default=C{False}), if the separating + matching text should be included in the split results. + + Example:: + punc = oneOf(list(".,;:/-!?")) + print(list(punc.split("This, this?, this sentence, is badly punctuated!"))) + prints:: + ['This', ' this', '', ' this sentence', ' is badly punctuated', ''] + """ + splits = 0 + last = 0 + for t,s,e in self.scanString(instring, maxMatches=maxsplit): + yield instring[last:s] + if includeSeparators: + yield t[0] + last = e + yield instring[last:] + + def __add__(self, other ): + """ + Implementation of + operator - returns C{L{And}}. Adding strings to a ParserElement + converts them to L{Literal}s by default. + + Example:: + greet = Word(alphas) + "," + Word(alphas) + "!" + hello = "Hello, World!" + print (hello, "->", greet.parseString(hello)) + Prints:: + Hello, World! -> ['Hello', ',', 'World', '!'] + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return And( [ self, other ] ) + + def __radd__(self, other ): + """ + Implementation of + operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other + self + + def __sub__(self, other): + """ + Implementation of - operator, returns C{L{And}} with error stop + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return self + And._ErrorStop() + other + + def __rsub__(self, other ): + """ + Implementation of - operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other - self + + def __mul__(self,other): + """ + Implementation of * operator, allows use of C{expr * 3} in place of + C{expr + expr + expr}. Expressions may also me multiplied by a 2-integer + tuple, similar to C{{min,max}} multipliers in regular expressions. Tuples + may also include C{None} as in: + - C{expr*(n,None)} or C{expr*(n,)} is equivalent + to C{expr*n + L{ZeroOrMore}(expr)} + (read as "at least n instances of C{expr}") + - C{expr*(None,n)} is equivalent to C{expr*(0,n)} + (read as "0 to n instances of C{expr}") + - C{expr*(None,None)} is equivalent to C{L{ZeroOrMore}(expr)} + - C{expr*(1,None)} is equivalent to C{L{OneOrMore}(expr)} + + Note that C{expr*(None,n)} does not raise an exception if + more than n exprs exist in the input stream; that is, + C{expr*(None,n)} does not enforce a maximum number of expr + occurrences. If this behavior is desired, then write + C{expr*(None,n) + ~expr} + """ + if isinstance(other,int): + minElements, optElements = other,0 + elif isinstance(other,tuple): + other = (other + (None, None))[:2] + if other[0] is None: + other = (0, other[1]) + if isinstance(other[0],int) and other[1] is None: + if other[0] == 0: + return ZeroOrMore(self) + if other[0] == 1: + return OneOrMore(self) + else: + return self*other[0] + ZeroOrMore(self) + elif isinstance(other[0],int) and isinstance(other[1],int): + minElements, optElements = other + optElements -= minElements + else: + raise TypeError("cannot multiply 'ParserElement' and ('%s','%s') objects", type(other[0]),type(other[1])) + else: + raise TypeError("cannot multiply 'ParserElement' and '%s' objects", type(other)) + + if minElements < 0: + raise ValueError("cannot multiply ParserElement by negative value") + if optElements < 0: + raise ValueError("second tuple value must be greater or equal to first tuple value") + if minElements == optElements == 0: + raise ValueError("cannot multiply ParserElement by 0 or (0,0)") + + if (optElements): + def makeOptionalList(n): + if n>1: + return Optional(self + makeOptionalList(n-1)) + else: + return Optional(self) + if minElements: + if minElements == 1: + ret = self + makeOptionalList(optElements) + else: + ret = And([self]*minElements) + makeOptionalList(optElements) + else: + ret = makeOptionalList(optElements) + else: + if minElements == 1: + ret = self + else: + ret = And([self]*minElements) + return ret + + def __rmul__(self, other): + return self.__mul__(other) + + def __or__(self, other ): + """ + Implementation of | operator - returns C{L{MatchFirst}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return MatchFirst( [ self, other ] ) + + def __ror__(self, other ): + """ + Implementation of | operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other | self + + def __xor__(self, other ): + """ + Implementation of ^ operator - returns C{L{Or}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Or( [ self, other ] ) + + def __rxor__(self, other ): + """ + Implementation of ^ operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other ^ self + + def __and__(self, other ): + """ + Implementation of & operator - returns C{L{Each}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return Each( [ self, other ] ) + + def __rand__(self, other ): + """ + Implementation of & operator when left operand is not a C{L{ParserElement}} + """ + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + if not isinstance( other, ParserElement ): + warnings.warn("Cannot combine element of type %s with ParserElement" % type(other), + SyntaxWarning, stacklevel=2) + return None + return other & self + + def __invert__( self ): + """ + Implementation of ~ operator - returns C{L{NotAny}} + """ + return NotAny( self ) + + def __call__(self, name=None): + """ + Shortcut for C{L{setResultsName}}, with C{listAllMatches=False}. + + If C{name} is given with a trailing C{'*'} character, then C{listAllMatches} will be + passed as C{True}. + + If C{name} is omitted, same as calling C{L{copy}}. + + Example:: + # these are equivalent + userdata = Word(alphas).setResultsName("name") + Word(nums+"-").setResultsName("socsecno") + userdata = Word(alphas)("name") + Word(nums+"-")("socsecno") + """ + if name is not None: + return self.setResultsName(name) + else: + return self.copy() + + def suppress( self ): + """ + Suppresses the output of this C{ParserElement}; useful to keep punctuation from + cluttering up returned output. + """ + return Suppress( self ) + + def leaveWhitespace( self ): + """ + Disables the skipping of whitespace before matching the characters in the + C{ParserElement}'s defined pattern. This is normally only used internally by + the pyparsing module, but may be needed in some whitespace-sensitive grammars. + """ + self.skipWhitespace = False + return self + + def setWhitespaceChars( self, chars ): + """ + Overrides the default whitespace chars + """ + self.skipWhitespace = True + self.whiteChars = chars + self.copyDefaultWhiteChars = False + return self + + def parseWithTabs( self ): + """ + Overrides default behavior to expand C{}s to spaces before parsing the input string. + Must be called before C{parseString} when the input grammar contains elements that + match C{} characters. + """ + self.keepTabs = True + return self + + def ignore( self, other ): + """ + Define expression to be ignored (e.g., comments) while doing pattern + matching; may be called repeatedly, to define multiple comment or other + ignorable patterns. + + Example:: + patt = OneOrMore(Word(alphas)) + patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj'] + + patt.ignore(cStyleComment) + patt.parseString('ablaj /* comment */ lskjd') # -> ['ablaj', 'lskjd'] + """ + if isinstance(other, basestring): + other = Suppress(other) + + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + self.ignoreExprs.append(other) + else: + self.ignoreExprs.append( Suppress( other.copy() ) ) + return self + + def setDebugActions( self, startAction, successAction, exceptionAction ): + """ + Enable display of debugging messages while doing pattern matching. + """ + self.debugActions = (startAction or _defaultStartDebugAction, + successAction or _defaultSuccessDebugAction, + exceptionAction or _defaultExceptionDebugAction) + self.debug = True + return self + + def setDebug( self, flag=True ): + """ + Enable display of debugging messages while doing pattern matching. + Set C{flag} to True to enable, False to disable. + + Example:: + wd = Word(alphas).setName("alphaword") + integer = Word(nums).setName("numword") + term = wd | integer + + # turn on debugging for wd + wd.setDebug() + + OneOrMore(term).parseString("abc 123 xyz 890") + + prints:: + Match alphaword at loc 0(1,1) + Matched alphaword -> ['abc'] + Match alphaword at loc 3(1,4) + Exception raised:Expected alphaword (at char 4), (line:1, col:5) + Match alphaword at loc 7(1,8) + Matched alphaword -> ['xyz'] + Match alphaword at loc 11(1,12) + Exception raised:Expected alphaword (at char 12), (line:1, col:13) + Match alphaword at loc 15(1,16) + Exception raised:Expected alphaword (at char 15), (line:1, col:16) + + The output shown is that produced by the default debug actions - custom debug actions can be + specified using L{setDebugActions}. Prior to attempting + to match the C{wd} expression, the debugging message C{"Match at loc (,)"} + is shown. Then if the parse succeeds, a C{"Matched"} message is shown, or an C{"Exception raised"} + message is shown. Also note the use of L{setName} to assign a human-readable name to the expression, + which makes debugging and exception messages easier to understand - for instance, the default + name created for the C{Word} expression without calling C{setName} is C{"W:(ABCD...)"}. + """ + if flag: + self.setDebugActions( _defaultStartDebugAction, _defaultSuccessDebugAction, _defaultExceptionDebugAction ) + else: + self.debug = False + return self + + def __str__( self ): + return self.name + + def __repr__( self ): + return _ustr(self) + + def streamline( self ): + self.streamlined = True + self.strRepr = None + return self + + def checkRecursion( self, parseElementList ): + pass + + def validate( self, validateTrace=[] ): + """ + Check defined expressions for valid structure, check for infinite recursive definitions. + """ + self.checkRecursion( [] ) + + def parseFile( self, file_or_filename, parseAll=False ): + """ + Execute the parse expression on the given file or filename. + If a filename is specified (instead of a file object), + the entire file is opened, read, and closed before parsing. + """ + try: + file_contents = file_or_filename.read() + except AttributeError: + with open(file_or_filename, "r") as f: + file_contents = f.read() + try: + return self.parseString(file_contents, parseAll) + except ParseBaseException as exc: + if ParserElement.verbose_stacktrace: + raise + else: + # catch and re-raise exception from here, clears out pyparsing internal stack trace + raise exc + + def __eq__(self,other): + if isinstance(other, ParserElement): + return self is other or vars(self) == vars(other) + elif isinstance(other, basestring): + return self.matches(other) + else: + return super(ParserElement,self)==other + + def __ne__(self,other): + return not (self == other) + + def __hash__(self): + return hash(id(self)) + + def __req__(self,other): + return self == other + + def __rne__(self,other): + return not (self == other) + + def matches(self, testString, parseAll=True): + """ + Method for quick testing of a parser against a test string. Good for simple + inline microtests of sub expressions while building up larger parser. + + Parameters: + - testString - to test against this expression for a match + - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests + + Example:: + expr = Word(nums) + assert expr.matches("100") + """ + try: + self.parseString(_ustr(testString), parseAll=parseAll) + return True + except ParseBaseException: + return False + + def runTests(self, tests, parseAll=True, comment='#', fullDump=True, printResults=True, failureTests=False): + """ + Execute the parse expression on a series of test strings, showing each + test, the parsed results or where the parse failed. Quick and easy way to + run a parse expression against a list of sample strings. + + Parameters: + - tests - a list of separate test strings, or a multiline string of test strings + - parseAll - (default=C{True}) - flag to pass to C{L{parseString}} when running tests + - comment - (default=C{'#'}) - expression for indicating embedded comments in the test + string; pass None to disable comment filtering + - fullDump - (default=C{True}) - dump results as list followed by results names in nested outline; + if False, only dump nested list + - printResults - (default=C{True}) prints test output to stdout + - failureTests - (default=C{False}) indicates if these tests are expected to fail parsing + + Returns: a (success, results) tuple, where success indicates that all tests succeeded + (or failed if C{failureTests} is True), and the results contain a list of lines of each + test's output + + Example:: + number_expr = pyparsing_common.number.copy() + + result = number_expr.runTests(''' + # unsigned integer + 100 + # negative integer + -100 + # float with scientific notation + 6.02e23 + # integer with scientific notation + 1e-12 + ''') + print("Success" if result[0] else "Failed!") + + result = number_expr.runTests(''' + # stray character + 100Z + # missing leading digit before '.' + -.100 + # too many '.' + 3.14.159 + ''', failureTests=True) + print("Success" if result[0] else "Failed!") + prints:: + # unsigned integer + 100 + [100] + + # negative integer + -100 + [-100] + + # float with scientific notation + 6.02e23 + [6.02e+23] + + # integer with scientific notation + 1e-12 + [1e-12] + + Success + + # stray character + 100Z + ^ + FAIL: Expected end of text (at char 3), (line:1, col:4) + + # missing leading digit before '.' + -.100 + ^ + FAIL: Expected {real number with scientific notation | real number | signed integer} (at char 0), (line:1, col:1) + + # too many '.' + 3.14.159 + ^ + FAIL: Expected end of text (at char 4), (line:1, col:5) + + Success + + Each test string must be on a single line. If you want to test a string that spans multiple + lines, create a test like this:: + + expr.runTest(r"this is a test\\n of strings that spans \\n 3 lines") + + (Note that this is a raw string literal, you must include the leading 'r'.) + """ + if isinstance(tests, basestring): + tests = list(map(str.strip, tests.rstrip().splitlines())) + if isinstance(comment, basestring): + comment = Literal(comment) + allResults = [] + comments = [] + success = True + for t in tests: + if comment is not None and comment.matches(t, False) or comments and not t: + comments.append(t) + continue + if not t: + continue + out = ['\n'.join(comments), t] + comments = [] + try: + t = t.replace(r'\n','\n') + result = self.parseString(t, parseAll=parseAll) + out.append(result.dump(full=fullDump)) + success = success and not failureTests + except ParseBaseException as pe: + fatal = "(FATAL)" if isinstance(pe, ParseFatalException) else "" + if '\n' in t: + out.append(line(pe.loc, t)) + out.append(' '*(col(pe.loc,t)-1) + '^' + fatal) + else: + out.append(' '*pe.loc + '^' + fatal) + out.append("FAIL: " + str(pe)) + success = success and failureTests + result = pe + except Exception as exc: + out.append("FAIL-EXCEPTION: " + str(exc)) + success = success and failureTests + result = exc + + if printResults: + if fullDump: + out.append('') + print('\n'.join(out)) + + allResults.append((t, result)) + + return success, allResults + + +class Token(ParserElement): + """ + Abstract C{ParserElement} subclass, for defining atomic matching patterns. + """ + def __init__( self ): + super(Token,self).__init__( savelist=False ) + + +class Empty(Token): + """ + An empty token, will always match. + """ + def __init__( self ): + super(Empty,self).__init__() + self.name = "Empty" + self.mayReturnEmpty = True + self.mayIndexError = False + + +class NoMatch(Token): + """ + A token that will never match. + """ + def __init__( self ): + super(NoMatch,self).__init__() + self.name = "NoMatch" + self.mayReturnEmpty = True + self.mayIndexError = False + self.errmsg = "Unmatchable token" + + def parseImpl( self, instring, loc, doActions=True ): + raise ParseException(instring, loc, self.errmsg, self) + + +class Literal(Token): + """ + Token to exactly match a specified string. + + Example:: + Literal('blah').parseString('blah') # -> ['blah'] + Literal('blah').parseString('blahfooblah') # -> ['blah'] + Literal('blah').parseString('bla') # -> Exception: Expected "blah" + + For case-insensitive matching, use L{CaselessLiteral}. + + For keyword matching (force word break before and after the matched string), + use L{Keyword} or L{CaselessKeyword}. + """ + def __init__( self, matchString ): + super(Literal,self).__init__() + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Literal; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.__class__ = Empty + self.name = '"%s"' % _ustr(self.match) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.mayIndexError = False + + # Performance tuning: this routine gets called a *lot* + # if this is a single character match string and the first character matches, + # short-circuit as quickly as possible, and avoid calling startswith + #~ @profile + def parseImpl( self, instring, loc, doActions=True ): + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) +_L = Literal +ParserElement._literalStringClass = Literal + +class Keyword(Token): + """ + Token to exactly match a specified string as a keyword, that is, it must be + immediately followed by a non-keyword character. Compare with C{L{Literal}}: + - C{Literal("if")} will match the leading C{'if'} in C{'ifAndOnlyIf'}. + - C{Keyword("if")} will not; it will only match the leading C{'if'} in C{'if x=1'}, or C{'if(y==2)'} + Accepts two optional constructor arguments in addition to the keyword string: + - C{identChars} is a string of characters that would be valid identifier characters, + defaulting to all alphanumerics + "_" and "$" + - C{caseless} allows case-insensitive matching, default is C{False}. + + Example:: + Keyword("start").parseString("start") # -> ['start'] + Keyword("start").parseString("starting") # -> Exception + + For case-insensitive matching, use L{CaselessKeyword}. + """ + DEFAULT_KEYWORD_CHARS = alphanums+"_$" + + def __init__( self, matchString, identChars=None, caseless=False ): + super(Keyword,self).__init__() + if identChars is None: + identChars = Keyword.DEFAULT_KEYWORD_CHARS + self.match = matchString + self.matchLen = len(matchString) + try: + self.firstMatchChar = matchString[0] + except IndexError: + warnings.warn("null string passed to Keyword; use Empty() instead", + SyntaxWarning, stacklevel=2) + self.name = '"%s"' % self.match + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = False + self.mayIndexError = False + self.caseless = caseless + if caseless: + self.caselessmatch = matchString.upper() + identChars = identChars.upper() + self.identChars = set(identChars) + + def parseImpl( self, instring, loc, doActions=True ): + if self.caseless: + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) and + (loc == 0 or instring[loc-1].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + else: + if (instring[loc] == self.firstMatchChar and + (self.matchLen==1 or instring.startswith(self.match,loc)) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen] not in self.identChars) and + (loc == 0 or instring[loc-1] not in self.identChars) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) + + def copy(self): + c = super(Keyword,self).copy() + c.identChars = Keyword.DEFAULT_KEYWORD_CHARS + return c + + @staticmethod + def setDefaultKeywordChars( chars ): + """Overrides the default Keyword chars + """ + Keyword.DEFAULT_KEYWORD_CHARS = chars + +class CaselessLiteral(Literal): + """ + Token to match a specified string, ignoring case of letters. + Note: the matched results will always be in the case of the given + match string, NOT the case of the input text. + + Example:: + OneOrMore(CaselessLiteral("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD', 'CMD'] + + (Contrast with example for L{CaselessKeyword}.) + """ + def __init__( self, matchString ): + super(CaselessLiteral,self).__init__( matchString.upper() ) + # Preserve the defining literal. + self.returnString = matchString + self.name = "'%s'" % self.returnString + self.errmsg = "Expected " + self.name + + def parseImpl( self, instring, loc, doActions=True ): + if instring[ loc:loc+self.matchLen ].upper() == self.match: + return loc+self.matchLen, self.returnString + raise ParseException(instring, loc, self.errmsg, self) + +class CaselessKeyword(Keyword): + """ + Caseless version of L{Keyword}. + + Example:: + OneOrMore(CaselessKeyword("CMD")).parseString("cmd CMD Cmd10") # -> ['CMD', 'CMD'] + + (Contrast with example for L{CaselessLiteral}.) + """ + def __init__( self, matchString, identChars=None ): + super(CaselessKeyword,self).__init__( matchString, identChars, caseless=True ) + + def parseImpl( self, instring, loc, doActions=True ): + if ( (instring[ loc:loc+self.matchLen ].upper() == self.caselessmatch) and + (loc >= len(instring)-self.matchLen or instring[loc+self.matchLen].upper() not in self.identChars) ): + return loc+self.matchLen, self.match + raise ParseException(instring, loc, self.errmsg, self) + +class CloseMatch(Token): + """ + A variation on L{Literal} which matches "close" matches, that is, + strings with at most 'n' mismatching characters. C{CloseMatch} takes parameters: + - C{match_string} - string to be matched + - C{maxMismatches} - (C{default=1}) maximum number of mismatches allowed to count as a match + + The results from a successful parse will contain the matched text from the input string and the following named results: + - C{mismatches} - a list of the positions within the match_string where mismatches were found + - C{original} - the original match_string used to compare against the input string + + If C{mismatches} is an empty list, then the match was an exact match. + + Example:: + patt = CloseMatch("ATCATCGAATGGA") + patt.parseString("ATCATCGAAXGGA") # -> (['ATCATCGAAXGGA'], {'mismatches': [[9]], 'original': ['ATCATCGAATGGA']}) + patt.parseString("ATCAXCGAAXGGA") # -> Exception: Expected 'ATCATCGAATGGA' (with up to 1 mismatches) (at char 0), (line:1, col:1) + + # exact match + patt.parseString("ATCATCGAATGGA") # -> (['ATCATCGAATGGA'], {'mismatches': [[]], 'original': ['ATCATCGAATGGA']}) + + # close match allowing up to 2 mismatches + patt = CloseMatch("ATCATCGAATGGA", maxMismatches=2) + patt.parseString("ATCAXCGAAXGGA") # -> (['ATCAXCGAAXGGA'], {'mismatches': [[4, 9]], 'original': ['ATCATCGAATGGA']}) + """ + def __init__(self, match_string, maxMismatches=1): + super(CloseMatch,self).__init__() + self.name = match_string + self.match_string = match_string + self.maxMismatches = maxMismatches + self.errmsg = "Expected %r (with up to %d mismatches)" % (self.match_string, self.maxMismatches) + self.mayIndexError = False + self.mayReturnEmpty = False + + def parseImpl( self, instring, loc, doActions=True ): + start = loc + instrlen = len(instring) + maxloc = start + len(self.match_string) + + if maxloc <= instrlen: + match_string = self.match_string + match_stringloc = 0 + mismatches = [] + maxMismatches = self.maxMismatches + + for match_stringloc,s_m in enumerate(zip(instring[loc:maxloc], self.match_string)): + src,mat = s_m + if src != mat: + mismatches.append(match_stringloc) + if len(mismatches) > maxMismatches: + break + else: + loc = match_stringloc + 1 + results = ParseResults([instring[start:loc]]) + results['original'] = self.match_string + results['mismatches'] = mismatches + return loc, results + + raise ParseException(instring, loc, self.errmsg, self) + + +class Word(Token): + """ + Token for matching words composed of allowed character sets. + Defined with string containing all allowed initial characters, + an optional string containing allowed body characters (if omitted, + defaults to the initial character set), and an optional minimum, + maximum, and/or exact length. The default value for C{min} is 1 (a + minimum value < 1 is not valid); the default values for C{max} and C{exact} + are 0, meaning no maximum or exact length restriction. An optional + C{excludeChars} parameter can list characters that might be found in + the input C{bodyChars} string; useful to define a word of all printables + except for one or two characters, for instance. + + L{srange} is useful for defining custom character set strings for defining + C{Word} expressions, using range notation from regular expression character sets. + + A common mistake is to use C{Word} to match a specific literal string, as in + C{Word("Address")}. Remember that C{Word} uses the string argument to define + I{sets} of matchable characters. This expression would match "Add", "AAA", + "dAred", or any other word made up of the characters 'A', 'd', 'r', 'e', and 's'. + To match an exact literal string, use L{Literal} or L{Keyword}. + + pyparsing includes helper strings for building Words: + - L{alphas} + - L{nums} + - L{alphanums} + - L{hexnums} + - L{alphas8bit} (alphabetic characters in ASCII range 128-255 - accented, tilded, umlauted, etc.) + - L{punc8bit} (non-alphabetic characters in ASCII range 128-255 - currency, symbols, superscripts, diacriticals, etc.) + - L{printables} (any non-whitespace character) + + Example:: + # a word composed of digits + integer = Word(nums) # equivalent to Word("0123456789") or Word(srange("0-9")) + + # a word with a leading capital, and zero or more lowercase + capital_word = Word(alphas.upper(), alphas.lower()) + + # hostnames are alphanumeric, with leading alpha, and '-' + hostname = Word(alphas, alphanums+'-') + + # roman numeral (not a strict parser, accepts invalid mix of characters) + roman = Word("IVXLCDM") + + # any string of non-whitespace characters, except for ',' + csv_value = Word(printables, excludeChars=",") + """ + def __init__( self, initChars, bodyChars=None, min=1, max=0, exact=0, asKeyword=False, excludeChars=None ): + super(Word,self).__init__() + if excludeChars: + initChars = ''.join(c for c in initChars if c not in excludeChars) + if bodyChars: + bodyChars = ''.join(c for c in bodyChars if c not in excludeChars) + self.initCharsOrig = initChars + self.initChars = set(initChars) + if bodyChars : + self.bodyCharsOrig = bodyChars + self.bodyChars = set(bodyChars) + else: + self.bodyCharsOrig = initChars + self.bodyChars = set(initChars) + + self.maxSpecified = max > 0 + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(Word()) if zero-length word is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.asKeyword = asKeyword + + if ' ' not in self.initCharsOrig+self.bodyCharsOrig and (min==1 and max==0 and exact==0): + if self.bodyCharsOrig == self.initCharsOrig: + self.reString = "[%s]+" % _escapeRegexRangeChars(self.initCharsOrig) + elif len(self.initCharsOrig) == 1: + self.reString = "%s[%s]*" % \ + (re.escape(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + else: + self.reString = "[%s][%s]*" % \ + (_escapeRegexRangeChars(self.initCharsOrig), + _escapeRegexRangeChars(self.bodyCharsOrig),) + if self.asKeyword: + self.reString = r"\b"+self.reString+r"\b" + try: + self.re = re.compile( self.reString ) + except Exception: + self.re = None + + def parseImpl( self, instring, loc, doActions=True ): + if self.re: + result = self.re.match(instring,loc) + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + return loc, result.group() + + if not(instring[ loc ] in self.initChars): + raise ParseException(instring, loc, self.errmsg, self) + + start = loc + loc += 1 + instrlen = len(instring) + bodychars = self.bodyChars + maxloc = start + self.maxLen + maxloc = min( maxloc, instrlen ) + while loc < maxloc and instring[loc] in bodychars: + loc += 1 + + throwException = False + if loc - start < self.minLen: + throwException = True + if self.maxSpecified and loc < instrlen and instring[loc] in bodychars: + throwException = True + if self.asKeyword: + if (start>0 and instring[start-1] in bodychars) or (loc4: + return s[:4]+"..." + else: + return s + + if ( self.initCharsOrig != self.bodyCharsOrig ): + self.strRepr = "W:(%s,%s)" % ( charsAsStr(self.initCharsOrig), charsAsStr(self.bodyCharsOrig) ) + else: + self.strRepr = "W:(%s)" % charsAsStr(self.initCharsOrig) + + return self.strRepr + + +class Regex(Token): + r""" + Token for matching strings that match a given regular expression. + Defined with string specifying the regular expression in a form recognized by the inbuilt Python re module. + If the given regex contains named groups (defined using C{(?P...)}), these will be preserved as + named parse results. + + Example:: + realnum = Regex(r"[+-]?\d+\.\d*") + date = Regex(r'(?P\d{4})-(?P\d\d?)-(?P\d\d?)') + # ref: http://stackoverflow.com/questions/267399/how-do-you-match-only-valid-roman-numerals-with-a-regular-expression + roman = Regex(r"M{0,4}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})") + """ + compiledREtype = type(re.compile("[A-Z]")) + def __init__( self, pattern, flags=0): + """The parameters C{pattern} and C{flags} are passed to the C{re.compile()} function as-is. See the Python C{re} module for an explanation of the acceptable patterns and flags.""" + super(Regex,self).__init__() + + if isinstance(pattern, basestring): + if not pattern: + warnings.warn("null string passed to Regex; use Empty() instead", + SyntaxWarning, stacklevel=2) + + self.pattern = pattern + self.flags = flags + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % pattern, + SyntaxWarning, stacklevel=2) + raise + + elif isinstance(pattern, Regex.compiledREtype): + self.re = pattern + self.pattern = \ + self.reString = str(pattern) + self.flags = flags + + else: + raise ValueError("Regex may only be constructed with a string or a compiled RE object") + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = self.re.match(instring,loc) + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + d = result.groupdict() + ret = ParseResults(result.group()) + if d: + for k in d: + ret[k] = d[k] + return loc,ret + + def __str__( self ): + try: + return super(Regex,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "Re:(%s)" % repr(self.pattern) + + return self.strRepr + + +class QuotedString(Token): + r""" + Token for matching strings that are delimited by quoting characters. + + Defined with the following parameters: + - quoteChar - string of one or more characters defining the quote delimiting string + - escChar - character to escape quotes, typically backslash (default=C{None}) + - escQuote - special quote sequence to escape an embedded quote string (such as SQL's "" to escape an embedded ") (default=C{None}) + - multiline - boolean indicating whether quotes can span multiple lines (default=C{False}) + - unquoteResults - boolean indicating whether the matched text should be unquoted (default=C{True}) + - endQuoteChar - string of one or more characters defining the end of the quote delimited string (default=C{None} => same as quoteChar) + - convertWhitespaceEscapes - convert escaped whitespace (C{'\t'}, C{'\n'}, etc.) to actual whitespace (default=C{True}) + + Example:: + qs = QuotedString('"') + print(qs.searchString('lsjdf "This is the quote" sldjf')) + complex_qs = QuotedString('{{', endQuoteChar='}}') + print(complex_qs.searchString('lsjdf {{This is the "quote"}} sldjf')) + sql_qs = QuotedString('"', escQuote='""') + print(sql_qs.searchString('lsjdf "This is the quote with ""embedded"" quotes" sldjf')) + prints:: + [['This is the quote']] + [['This is the "quote"']] + [['This is the quote with "embedded" quotes']] + """ + def __init__( self, quoteChar, escChar=None, escQuote=None, multiline=False, unquoteResults=True, endQuoteChar=None, convertWhitespaceEscapes=True): + super(QuotedString,self).__init__() + + # remove white space from quote chars - wont work anyway + quoteChar = quoteChar.strip() + if not quoteChar: + warnings.warn("quoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + if endQuoteChar is None: + endQuoteChar = quoteChar + else: + endQuoteChar = endQuoteChar.strip() + if not endQuoteChar: + warnings.warn("endQuoteChar cannot be the empty string",SyntaxWarning,stacklevel=2) + raise SyntaxError() + + self.quoteChar = quoteChar + self.quoteCharLen = len(quoteChar) + self.firstQuoteChar = quoteChar[0] + self.endQuoteChar = endQuoteChar + self.endQuoteCharLen = len(endQuoteChar) + self.escChar = escChar + self.escQuote = escQuote + self.unquoteResults = unquoteResults + self.convertWhitespaceEscapes = convertWhitespaceEscapes + + if multiline: + self.flags = re.MULTILINE | re.DOTALL + self.pattern = r'%s(?:[^%s%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + else: + self.flags = 0 + self.pattern = r'%s(?:[^%s\n\r%s]' % \ + ( re.escape(self.quoteChar), + _escapeRegexRangeChars(self.endQuoteChar[0]), + (escChar is not None and _escapeRegexRangeChars(escChar) or '') ) + if len(self.endQuoteChar) > 1: + self.pattern += ( + '|(?:' + ')|(?:'.join("%s[^%s]" % (re.escape(self.endQuoteChar[:i]), + _escapeRegexRangeChars(self.endQuoteChar[i])) + for i in range(len(self.endQuoteChar)-1,0,-1)) + ')' + ) + if escQuote: + self.pattern += (r'|(?:%s)' % re.escape(escQuote)) + if escChar: + self.pattern += (r'|(?:%s.)' % re.escape(escChar)) + self.escCharReplacePattern = re.escape(self.escChar)+"(.)" + self.pattern += (r')*%s' % re.escape(self.endQuoteChar)) + + try: + self.re = re.compile(self.pattern, self.flags) + self.reString = self.pattern + except sre_constants.error: + warnings.warn("invalid pattern (%s) passed to Regex" % self.pattern, + SyntaxWarning, stacklevel=2) + raise + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayIndexError = False + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + result = instring[loc] == self.firstQuoteChar and self.re.match(instring,loc) or None + if not result: + raise ParseException(instring, loc, self.errmsg, self) + + loc = result.end() + ret = result.group() + + if self.unquoteResults: + + # strip off quotes + ret = ret[self.quoteCharLen:-self.endQuoteCharLen] + + if isinstance(ret,basestring): + # replace escaped whitespace + if '\\' in ret and self.convertWhitespaceEscapes: + ws_map = { + r'\t' : '\t', + r'\n' : '\n', + r'\f' : '\f', + r'\r' : '\r', + } + for wslit,wschar in ws_map.items(): + ret = ret.replace(wslit, wschar) + + # replace escaped characters + if self.escChar: + ret = re.sub(self.escCharReplacePattern, r"\g<1>", ret) + + # replace escaped quotes + if self.escQuote: + ret = ret.replace(self.escQuote, self.endQuoteChar) + + return loc, ret + + def __str__( self ): + try: + return super(QuotedString,self).__str__() + except Exception: + pass + + if self.strRepr is None: + self.strRepr = "quoted string, starting with %s ending with %s" % (self.quoteChar, self.endQuoteChar) + + return self.strRepr + + +class CharsNotIn(Token): + """ + Token for matching words composed of characters I{not} in a given set (will + include whitespace in matched characters if not listed in the provided exclusion set - see example). + Defined with string containing all disallowed characters, and an optional + minimum, maximum, and/or exact length. The default value for C{min} is 1 (a + minimum value < 1 is not valid); the default values for C{max} and C{exact} + are 0, meaning no maximum or exact length restriction. + + Example:: + # define a comma-separated-value as anything that is not a ',' + csv_value = CharsNotIn(',') + print(delimitedList(csv_value).parseString("dkls,lsdkjf,s12 34,@!#,213")) + prints:: + ['dkls', 'lsdkjf', 's12 34', '@!#', '213'] + """ + def __init__( self, notChars, min=1, max=0, exact=0 ): + super(CharsNotIn,self).__init__() + self.skipWhitespace = False + self.notChars = notChars + + if min < 1: + raise ValueError("cannot specify a minimum length < 1; use Optional(CharsNotIn()) if zero-length char group is permitted") + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + self.name = _ustr(self) + self.errmsg = "Expected " + self.name + self.mayReturnEmpty = ( self.minLen == 0 ) + self.mayIndexError = False + + def parseImpl( self, instring, loc, doActions=True ): + if instring[loc] in self.notChars: + raise ParseException(instring, loc, self.errmsg, self) + + start = loc + loc += 1 + notchars = self.notChars + maxlen = min( start+self.maxLen, len(instring) ) + while loc < maxlen and \ + (instring[loc] not in notchars): + loc += 1 + + if loc - start < self.minLen: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + def __str__( self ): + try: + return super(CharsNotIn, self).__str__() + except Exception: + pass + + if self.strRepr is None: + if len(self.notChars) > 4: + self.strRepr = "!W:(%s...)" % self.notChars[:4] + else: + self.strRepr = "!W:(%s)" % self.notChars + + return self.strRepr + +class White(Token): + """ + Special matching class for matching whitespace. Normally, whitespace is ignored + by pyparsing grammars. This class is included when some whitespace structures + are significant. Define with a string containing the whitespace characters to be + matched; default is C{" \\t\\r\\n"}. Also takes optional C{min}, C{max}, and C{exact} arguments, + as defined for the C{L{Word}} class. + """ + whiteStrs = { + " " : "", + "\t": "", + "\n": "", + "\r": "", + "\f": "", + } + def __init__(self, ws=" \t\r\n", min=1, max=0, exact=0): + super(White,self).__init__() + self.matchWhite = ws + self.setWhitespaceChars( "".join(c for c in self.whiteChars if c not in self.matchWhite) ) + #~ self.leaveWhitespace() + self.name = ("".join(White.whiteStrs[c] for c in self.matchWhite)) + self.mayReturnEmpty = True + self.errmsg = "Expected " + self.name + + self.minLen = min + + if max > 0: + self.maxLen = max + else: + self.maxLen = _MAX_INT + + if exact > 0: + self.maxLen = exact + self.minLen = exact + + def parseImpl( self, instring, loc, doActions=True ): + if not(instring[ loc ] in self.matchWhite): + raise ParseException(instring, loc, self.errmsg, self) + start = loc + loc += 1 + maxloc = start + self.maxLen + maxloc = min( maxloc, len(instring) ) + while loc < maxloc and instring[loc] in self.matchWhite: + loc += 1 + + if loc - start < self.minLen: + raise ParseException(instring, loc, self.errmsg, self) + + return loc, instring[start:loc] + + +class _PositionToken(Token): + def __init__( self ): + super(_PositionToken,self).__init__() + self.name=self.__class__.__name__ + self.mayReturnEmpty = True + self.mayIndexError = False + +class GoToColumn(_PositionToken): + """ + Token to advance to a specific column of input text; useful for tabular report scraping. + """ + def __init__( self, colno ): + super(GoToColumn,self).__init__() + self.col = colno + + def preParse( self, instring, loc ): + if col(loc,instring) != self.col: + instrlen = len(instring) + if self.ignoreExprs: + loc = self._skipIgnorables( instring, loc ) + while loc < instrlen and instring[loc].isspace() and col( loc, instring ) != self.col : + loc += 1 + return loc + + def parseImpl( self, instring, loc, doActions=True ): + thiscol = col( loc, instring ) + if thiscol > self.col: + raise ParseException( instring, loc, "Text not in expected column", self ) + newloc = loc + self.col - thiscol + ret = instring[ loc: newloc ] + return newloc, ret + + +class LineStart(_PositionToken): + """ + Matches if current position is at the beginning of a line within the parse string + + Example:: + + test = '''\ + AAA this line + AAA and this line + AAA but not this one + B AAA and definitely not this one + ''' + + for t in (LineStart() + 'AAA' + restOfLine).searchString(test): + print(t) + + Prints:: + ['AAA', ' this line'] + ['AAA', ' and this line'] + + """ + def __init__( self ): + super(LineStart,self).__init__() + self.errmsg = "Expected start of line" + + def parseImpl( self, instring, loc, doActions=True ): + if col(loc, instring) == 1: + return loc, [] + raise ParseException(instring, loc, self.errmsg, self) + +class LineEnd(_PositionToken): + """ + Matches if current position is at the end of a line within the parse string + """ + def __init__( self ): + super(LineEnd,self).__init__() + self.setWhitespaceChars( ParserElement.DEFAULT_WHITE_CHARS.replace("\n","") ) + self.errmsg = "Expected end of line" + + def parseImpl( self, instring, loc, doActions=True ): + if loc len(instring): + return loc, [] + else: + raise ParseException(instring, loc, self.errmsg, self) + +class WordStart(_PositionToken): + """ + Matches if the current position is at the beginning of a Word, and + is not preceded by any character in a given set of C{wordChars} + (default=C{printables}). To emulate the C{\b} behavior of regular expressions, + use C{WordStart(alphanums)}. C{WordStart} will also match at the beginning of + the string being parsed, or at the beginning of a line. + """ + def __init__(self, wordChars = printables): + super(WordStart,self).__init__() + self.wordChars = set(wordChars) + self.errmsg = "Not at the start of a word" + + def parseImpl(self, instring, loc, doActions=True ): + if loc != 0: + if (instring[loc-1] in self.wordChars or + instring[loc] not in self.wordChars): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + +class WordEnd(_PositionToken): + """ + Matches if the current position is at the end of a Word, and + is not followed by any character in a given set of C{wordChars} + (default=C{printables}). To emulate the C{\b} behavior of regular expressions, + use C{WordEnd(alphanums)}. C{WordEnd} will also match at the end of + the string being parsed, or at the end of a line. + """ + def __init__(self, wordChars = printables): + super(WordEnd,self).__init__() + self.wordChars = set(wordChars) + self.skipWhitespace = False + self.errmsg = "Not at the end of a word" + + def parseImpl(self, instring, loc, doActions=True ): + instrlen = len(instring) + if instrlen>0 and loc maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + else: + # save match among all matches, to retry longest to shortest + matches.append((loc2, e)) + + if matches: + matches.sort(key=lambda x: -x[0]) + for _,e in matches: + try: + return e._parse( instring, loc, doActions ) + except ParseException as err: + err.__traceback__ = None + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + + if maxException is not None: + maxException.msg = self.errmsg + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + + def __ixor__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #Or( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " ^ ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class MatchFirst(ParseExpression): + """ + Requires that at least one C{ParseExpression} is found. + If two expressions match, the first one listed is the one that will match. + May be constructed using the C{'|'} operator. + + Example:: + # construct MatchFirst using '|' operator + + # watch the order of expressions to match + number = Word(nums) | Combine(Word(nums) + '.' + Word(nums)) + print(number.searchString("123 3.1416 789")) # Fail! -> [['123'], ['3'], ['1416'], ['789']] + + # put more selective expression first + number = Combine(Word(nums) + '.' + Word(nums)) | Word(nums) + print(number.searchString("123 3.1416 789")) # Better -> [['123'], ['3.1416'], ['789']] + """ + def __init__( self, exprs, savelist = False ): + super(MatchFirst,self).__init__(exprs, savelist) + if self.exprs: + self.mayReturnEmpty = any(e.mayReturnEmpty for e in self.exprs) + else: + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + maxExcLoc = -1 + maxException = None + for e in self.exprs: + try: + ret = e._parse( instring, loc, doActions ) + return ret + except ParseException as err: + if err.loc > maxExcLoc: + maxException = err + maxExcLoc = err.loc + except IndexError: + if len(instring) > maxExcLoc: + maxException = ParseException(instring,len(instring),e.errmsg,self) + maxExcLoc = len(instring) + + # only got here if no expression matched, raise exception for match that made it the furthest + else: + if maxException is not None: + maxException.msg = self.errmsg + raise maxException + else: + raise ParseException(instring, loc, "no defined alternatives to match", self) + + def __ior__(self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass( other ) + return self.append( other ) #MatchFirst( [ self, other ] ) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " | ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class Each(ParseExpression): + """ + Requires all given C{ParseExpression}s to be found, but in any order. + Expressions may be separated by whitespace. + May be constructed using the C{'&'} operator. + + Example:: + color = oneOf("RED ORANGE YELLOW GREEN BLUE PURPLE BLACK WHITE BROWN") + shape_type = oneOf("SQUARE CIRCLE TRIANGLE STAR HEXAGON OCTAGON") + integer = Word(nums) + shape_attr = "shape:" + shape_type("shape") + posn_attr = "posn:" + Group(integer("x") + ',' + integer("y"))("posn") + color_attr = "color:" + color("color") + size_attr = "size:" + integer("size") + + # use Each (using operator '&') to accept attributes in any order + # (shape and posn are required, color and size are optional) + shape_spec = shape_attr & posn_attr & Optional(color_attr) & Optional(size_attr) + + shape_spec.runTests(''' + shape: SQUARE color: BLACK posn: 100, 120 + shape: CIRCLE size: 50 color: BLUE posn: 50,80 + color:GREEN size:20 shape:TRIANGLE posn:20,40 + ''' + ) + prints:: + shape: SQUARE color: BLACK posn: 100, 120 + ['shape:', 'SQUARE', 'color:', 'BLACK', 'posn:', ['100', ',', '120']] + - color: BLACK + - posn: ['100', ',', '120'] + - x: 100 + - y: 120 + - shape: SQUARE + + + shape: CIRCLE size: 50 color: BLUE posn: 50,80 + ['shape:', 'CIRCLE', 'size:', '50', 'color:', 'BLUE', 'posn:', ['50', ',', '80']] + - color: BLUE + - posn: ['50', ',', '80'] + - x: 50 + - y: 80 + - shape: CIRCLE + - size: 50 + + + color: GREEN size: 20 shape: TRIANGLE posn: 20,40 + ['color:', 'GREEN', 'size:', '20', 'shape:', 'TRIANGLE', 'posn:', ['20', ',', '40']] + - color: GREEN + - posn: ['20', ',', '40'] + - x: 20 + - y: 40 + - shape: TRIANGLE + - size: 20 + """ + def __init__( self, exprs, savelist = True ): + super(Each,self).__init__(exprs, savelist) + self.mayReturnEmpty = all(e.mayReturnEmpty for e in self.exprs) + self.skipWhitespace = True + self.initExprGroups = True + + def parseImpl( self, instring, loc, doActions=True ): + if self.initExprGroups: + self.opt1map = dict((id(e.expr),e) for e in self.exprs if isinstance(e,Optional)) + opt1 = [ e.expr for e in self.exprs if isinstance(e,Optional) ] + opt2 = [ e for e in self.exprs if e.mayReturnEmpty and not isinstance(e,Optional)] + self.optionals = opt1 + opt2 + self.multioptionals = [ e.expr for e in self.exprs if isinstance(e,ZeroOrMore) ] + self.multirequired = [ e.expr for e in self.exprs if isinstance(e,OneOrMore) ] + self.required = [ e for e in self.exprs if not isinstance(e,(Optional,ZeroOrMore,OneOrMore)) ] + self.required += self.multirequired + self.initExprGroups = False + tmpLoc = loc + tmpReqd = self.required[:] + tmpOpt = self.optionals[:] + matchOrder = [] + + keepMatching = True + while keepMatching: + tmpExprs = tmpReqd + tmpOpt + self.multioptionals + self.multirequired + failed = [] + for e in tmpExprs: + try: + tmpLoc = e.tryParse( instring, tmpLoc ) + except ParseException: + failed.append(e) + else: + matchOrder.append(self.opt1map.get(id(e),e)) + if e in tmpReqd: + tmpReqd.remove(e) + elif e in tmpOpt: + tmpOpt.remove(e) + if len(failed) == len(tmpExprs): + keepMatching = False + + if tmpReqd: + missing = ", ".join(_ustr(e) for e in tmpReqd) + raise ParseException(instring,loc,"Missing one or more required elements (%s)" % missing ) + + # add any unmatched Optionals, in case they have default values defined + matchOrder += [e for e in self.exprs if isinstance(e,Optional) and e.expr in tmpOpt] + + resultlist = [] + for e in matchOrder: + loc,results = e._parse(instring,loc,doActions) + resultlist.append(results) + + finalResults = sum(resultlist, ParseResults([])) + return loc, finalResults + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + " & ".join(_ustr(e) for e in self.exprs) + "}" + + return self.strRepr + + def checkRecursion( self, parseElementList ): + subRecCheckList = parseElementList[:] + [ self ] + for e in self.exprs: + e.checkRecursion( subRecCheckList ) + + +class ParseElementEnhance(ParserElement): + """ + Abstract subclass of C{ParserElement}, for combining and post-processing parsed tokens. + """ + def __init__( self, expr, savelist=False ): + super(ParseElementEnhance,self).__init__(savelist) + if isinstance( expr, basestring ): + if issubclass(ParserElement._literalStringClass, Token): + expr = ParserElement._literalStringClass(expr) + else: + expr = ParserElement._literalStringClass(Literal(expr)) + self.expr = expr + self.strRepr = None + if expr is not None: + self.mayIndexError = expr.mayIndexError + self.mayReturnEmpty = expr.mayReturnEmpty + self.setWhitespaceChars( expr.whiteChars ) + self.skipWhitespace = expr.skipWhitespace + self.saveAsList = expr.saveAsList + self.callPreparse = expr.callPreparse + self.ignoreExprs.extend(expr.ignoreExprs) + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr is not None: + return self.expr._parse( instring, loc, doActions, callPreParse=False ) + else: + raise ParseException("",loc,self.errmsg,self) + + def leaveWhitespace( self ): + self.skipWhitespace = False + self.expr = self.expr.copy() + if self.expr is not None: + self.expr.leaveWhitespace() + return self + + def ignore( self, other ): + if isinstance( other, Suppress ): + if other not in self.ignoreExprs: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + else: + super( ParseElementEnhance, self).ignore( other ) + if self.expr is not None: + self.expr.ignore( self.ignoreExprs[-1] ) + return self + + def streamline( self ): + super(ParseElementEnhance,self).streamline() + if self.expr is not None: + self.expr.streamline() + return self + + def checkRecursion( self, parseElementList ): + if self in parseElementList: + raise RecursiveGrammarException( parseElementList+[self] ) + subRecCheckList = parseElementList[:] + [ self ] + if self.expr is not None: + self.expr.checkRecursion( subRecCheckList ) + + def validate( self, validateTrace=[] ): + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion( [] ) + + def __str__( self ): + try: + return super(ParseElementEnhance,self).__str__() + except Exception: + pass + + if self.strRepr is None and self.expr is not None: + self.strRepr = "%s:(%s)" % ( self.__class__.__name__, _ustr(self.expr) ) + return self.strRepr + + +class FollowedBy(ParseElementEnhance): + """ + Lookahead matching of the given parse expression. C{FollowedBy} + does I{not} advance the parsing position within the input string, it only + verifies that the specified parse expression matches at the current + position. C{FollowedBy} always returns a null token list. + + Example:: + # use FollowedBy to match a label only if it is followed by a ':' + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + + OneOrMore(attr_expr).parseString("shape: SQUARE color: BLACK posn: upper left").pprint() + prints:: + [['shape', 'SQUARE'], ['color', 'BLACK'], ['posn', 'upper left']] + """ + def __init__( self, expr ): + super(FollowedBy,self).__init__(expr) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + self.expr.tryParse( instring, loc ) + return loc, [] + + +class NotAny(ParseElementEnhance): + """ + Lookahead to disallow matching with the given parse expression. C{NotAny} + does I{not} advance the parsing position within the input string, it only + verifies that the specified parse expression does I{not} match at the current + position. Also, C{NotAny} does I{not} skip over leading whitespace. C{NotAny} + always returns a null token list. May be constructed using the '~' operator. + + Example:: + + """ + def __init__( self, expr ): + super(NotAny,self).__init__(expr) + #~ self.leaveWhitespace() + self.skipWhitespace = False # do NOT use self.leaveWhitespace(), don't want to propagate to exprs + self.mayReturnEmpty = True + self.errmsg = "Found unwanted token, "+_ustr(self.expr) + + def parseImpl( self, instring, loc, doActions=True ): + if self.expr.canParseNext(instring, loc): + raise ParseException(instring, loc, self.errmsg, self) + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "~{" + _ustr(self.expr) + "}" + + return self.strRepr + +class _MultipleMatch(ParseElementEnhance): + def __init__( self, expr, stopOn=None): + super(_MultipleMatch, self).__init__(expr) + self.saveAsList = True + ender = stopOn + if isinstance(ender, basestring): + ender = ParserElement._literalStringClass(ender) + self.not_ender = ~ender if ender is not None else None + + def parseImpl( self, instring, loc, doActions=True ): + self_expr_parse = self.expr._parse + self_skip_ignorables = self._skipIgnorables + check_ender = self.not_ender is not None + if check_ender: + try_not_ender = self.not_ender.tryParse + + # must be at least one (but first see if we are the stopOn sentinel; + # if so, fail) + if check_ender: + try_not_ender(instring, loc) + loc, tokens = self_expr_parse( instring, loc, doActions, callPreParse=False ) + try: + hasIgnoreExprs = (not not self.ignoreExprs) + while 1: + if check_ender: + try_not_ender(instring, loc) + if hasIgnoreExprs: + preloc = self_skip_ignorables( instring, loc ) + else: + preloc = loc + loc, tmptokens = self_expr_parse( instring, preloc, doActions ) + if tmptokens or tmptokens.haskeys(): + tokens += tmptokens + except (ParseException,IndexError): + pass + + return loc, tokens + +class OneOrMore(_MultipleMatch): + """ + Repetition of one or more of the given expression. + + Parameters: + - expr - expression that must match one or more times + - stopOn - (default=C{None}) - expression for a terminating sentinel + (only required if the sentinel would ordinarily match the repetition + expression) + + Example:: + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) + + text = "shape: SQUARE posn: upper left color: BLACK" + OneOrMore(attr_expr).parseString(text).pprint() # Fail! read 'color' as data instead of next label -> [['shape', 'SQUARE color']] + + # use stopOn attribute for OneOrMore to avoid reading label string as part of the data + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + OneOrMore(attr_expr).parseString(text).pprint() # Better -> [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'BLACK']] + + # could also be written as + (attr_expr * (1,)).parseString(text).pprint() + """ + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "{" + _ustr(self.expr) + "}..." + + return self.strRepr + +class ZeroOrMore(_MultipleMatch): + """ + Optional repetition of zero or more of the given expression. + + Parameters: + - expr - expression that must match zero or more times + - stopOn - (default=C{None}) - expression for a terminating sentinel + (only required if the sentinel would ordinarily match the repetition + expression) + + Example: similar to L{OneOrMore} + """ + def __init__( self, expr, stopOn=None): + super(ZeroOrMore,self).__init__(expr, stopOn=stopOn) + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + return super(ZeroOrMore, self).parseImpl(instring, loc, doActions) + except (ParseException,IndexError): + return loc, [] + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]..." + + return self.strRepr + +class _NullToken(object): + def __bool__(self): + return False + __nonzero__ = __bool__ + def __str__(self): + return "" + +_optionalNotMatched = _NullToken() +class Optional(ParseElementEnhance): + """ + Optional matching of the given expression. + + Parameters: + - expr - expression that must match zero or more times + - default (optional) - value to be returned if the optional expression is not found. + + Example:: + # US postal code can be a 5-digit zip, plus optional 4-digit qualifier + zip = Combine(Word(nums, exact=5) + Optional('-' + Word(nums, exact=4))) + zip.runTests(''' + # traditional ZIP code + 12345 + + # ZIP+4 form + 12101-0001 + + # invalid ZIP + 98765- + ''') + prints:: + # traditional ZIP code + 12345 + ['12345'] + + # ZIP+4 form + 12101-0001 + ['12101-0001'] + + # invalid ZIP + 98765- + ^ + FAIL: Expected end of text (at char 5), (line:1, col:6) + """ + def __init__( self, expr, default=_optionalNotMatched ): + super(Optional,self).__init__( expr, savelist=False ) + self.saveAsList = self.expr.saveAsList + self.defaultValue = default + self.mayReturnEmpty = True + + def parseImpl( self, instring, loc, doActions=True ): + try: + loc, tokens = self.expr._parse( instring, loc, doActions, callPreParse=False ) + except (ParseException,IndexError): + if self.defaultValue is not _optionalNotMatched: + if self.expr.resultsName: + tokens = ParseResults([ self.defaultValue ]) + tokens[self.expr.resultsName] = self.defaultValue + else: + tokens = [ self.defaultValue ] + else: + tokens = [] + return loc, tokens + + def __str__( self ): + if hasattr(self,"name"): + return self.name + + if self.strRepr is None: + self.strRepr = "[" + _ustr(self.expr) + "]" + + return self.strRepr + +class SkipTo(ParseElementEnhance): + """ + Token for skipping over all undefined text until the matched expression is found. + + Parameters: + - expr - target expression marking the end of the data to be skipped + - include - (default=C{False}) if True, the target expression is also parsed + (the skipped text and target expression are returned as a 2-element list). + - ignore - (default=C{None}) used to define grammars (typically quoted strings and + comments) that might contain false matches to the target expression + - failOn - (default=C{None}) define expressions that are not allowed to be + included in the skipped test; if found before the target expression is found, + the SkipTo is not a match + + Example:: + report = ''' + Outstanding Issues Report - 1 Jan 2000 + + # | Severity | Description | Days Open + -----+----------+-------------------------------------------+----------- + 101 | Critical | Intermittent system crash | 6 + 94 | Cosmetic | Spelling error on Login ('log|n') | 14 + 79 | Minor | System slow when running too many reports | 47 + ''' + integer = Word(nums) + SEP = Suppress('|') + # use SkipTo to simply match everything up until the next SEP + # - ignore quoted strings, so that a '|' character inside a quoted string does not match + # - parse action will call token.strip() for each matched token, i.e., the description body + string_data = SkipTo(SEP, ignore=quotedString) + string_data.setParseAction(tokenMap(str.strip)) + ticket_expr = (integer("issue_num") + SEP + + string_data("sev") + SEP + + string_data("desc") + SEP + + integer("days_open")) + + for tkt in ticket_expr.searchString(report): + print tkt.dump() + prints:: + ['101', 'Critical', 'Intermittent system crash', '6'] + - days_open: 6 + - desc: Intermittent system crash + - issue_num: 101 + - sev: Critical + ['94', 'Cosmetic', "Spelling error on Login ('log|n')", '14'] + - days_open: 14 + - desc: Spelling error on Login ('log|n') + - issue_num: 94 + - sev: Cosmetic + ['79', 'Minor', 'System slow when running too many reports', '47'] + - days_open: 47 + - desc: System slow when running too many reports + - issue_num: 79 + - sev: Minor + """ + def __init__( self, other, include=False, ignore=None, failOn=None ): + super( SkipTo, self ).__init__( other ) + self.ignoreExpr = ignore + self.mayReturnEmpty = True + self.mayIndexError = False + self.includeMatch = include + self.asList = False + if isinstance(failOn, basestring): + self.failOn = ParserElement._literalStringClass(failOn) + else: + self.failOn = failOn + self.errmsg = "No match found for "+_ustr(self.expr) + + def parseImpl( self, instring, loc, doActions=True ): + startloc = loc + instrlen = len(instring) + expr = self.expr + expr_parse = self.expr._parse + self_failOn_canParseNext = self.failOn.canParseNext if self.failOn is not None else None + self_ignoreExpr_tryParse = self.ignoreExpr.tryParse if self.ignoreExpr is not None else None + + tmploc = loc + while tmploc <= instrlen: + if self_failOn_canParseNext is not None: + # break if failOn expression matches + if self_failOn_canParseNext(instring, tmploc): + break + + if self_ignoreExpr_tryParse is not None: + # advance past ignore expressions + while 1: + try: + tmploc = self_ignoreExpr_tryParse(instring, tmploc) + except ParseBaseException: + break + + try: + expr_parse(instring, tmploc, doActions=False, callPreParse=False) + except (ParseException, IndexError): + # no match, advance loc in string + tmploc += 1 + else: + # matched skipto expr, done + break + + else: + # ran off the end of the input string without matching skipto expr, fail + raise ParseException(instring, loc, self.errmsg, self) + + # build up return values + loc = tmploc + skiptext = instring[startloc:loc] + skipresult = ParseResults(skiptext) + + if self.includeMatch: + loc, mat = expr_parse(instring,loc,doActions,callPreParse=False) + skipresult += mat + + return loc, skipresult + +class Forward(ParseElementEnhance): + """ + Forward declaration of an expression to be defined later - + used for recursive grammars, such as algebraic infix notation. + When the expression is known, it is assigned to the C{Forward} variable using the '<<' operator. + + Note: take care when assigning to C{Forward} not to overlook precedence of operators. + Specifically, '|' has a lower precedence than '<<', so that:: + fwdExpr << a | b | c + will actually be evaluated as:: + (fwdExpr << a) | b | c + thereby leaving b and c out as parseable alternatives. It is recommended that you + explicitly group the values inserted into the C{Forward}:: + fwdExpr << (a | b | c) + Converting to use the '<<=' operator instead will avoid this problem. + + See L{ParseResults.pprint} for an example of a recursive parser created using + C{Forward}. + """ + def __init__( self, other=None ): + super(Forward,self).__init__( other, savelist=False ) + + def __lshift__( self, other ): + if isinstance( other, basestring ): + other = ParserElement._literalStringClass(other) + self.expr = other + self.strRepr = None + self.mayIndexError = self.expr.mayIndexError + self.mayReturnEmpty = self.expr.mayReturnEmpty + self.setWhitespaceChars( self.expr.whiteChars ) + self.skipWhitespace = self.expr.skipWhitespace + self.saveAsList = self.expr.saveAsList + self.ignoreExprs.extend(self.expr.ignoreExprs) + return self + + def __ilshift__(self, other): + return self << other + + def leaveWhitespace( self ): + self.skipWhitespace = False + return self + + def streamline( self ): + if not self.streamlined: + self.streamlined = True + if self.expr is not None: + self.expr.streamline() + return self + + def validate( self, validateTrace=[] ): + if self not in validateTrace: + tmp = validateTrace[:]+[self] + if self.expr is not None: + self.expr.validate(tmp) + self.checkRecursion([]) + + def __str__( self ): + if hasattr(self,"name"): + return self.name + return self.__class__.__name__ + ": ..." + + # stubbed out for now - creates awful memory and perf issues + self._revertClass = self.__class__ + self.__class__ = _ForwardNoRecurse + try: + if self.expr is not None: + retString = _ustr(self.expr) + else: + retString = "None" + finally: + self.__class__ = self._revertClass + return self.__class__.__name__ + ": " + retString + + def copy(self): + if self.expr is not None: + return super(Forward,self).copy() + else: + ret = Forward() + ret <<= self + return ret + +class _ForwardNoRecurse(Forward): + def __str__( self ): + return "..." + +class TokenConverter(ParseElementEnhance): + """ + Abstract subclass of C{ParseExpression}, for converting parsed results. + """ + def __init__( self, expr, savelist=False ): + super(TokenConverter,self).__init__( expr )#, savelist ) + self.saveAsList = False + +class Combine(TokenConverter): + """ + Converter to concatenate all matching tokens to a single string. + By default, the matching patterns must also be contiguous in the input string; + this can be disabled by specifying C{'adjacent=False'} in the constructor. + + Example:: + real = Word(nums) + '.' + Word(nums) + print(real.parseString('3.1416')) # -> ['3', '.', '1416'] + # will also erroneously match the following + print(real.parseString('3. 1416')) # -> ['3', '.', '1416'] + + real = Combine(Word(nums) + '.' + Word(nums)) + print(real.parseString('3.1416')) # -> ['3.1416'] + # no match when there are internal spaces + print(real.parseString('3. 1416')) # -> Exception: Expected W:(0123...) + """ + def __init__( self, expr, joinString="", adjacent=True ): + super(Combine,self).__init__( expr ) + # suppress whitespace-stripping in contained parse expressions, but re-enable it on the Combine itself + if adjacent: + self.leaveWhitespace() + self.adjacent = adjacent + self.skipWhitespace = True + self.joinString = joinString + self.callPreparse = True + + def ignore( self, other ): + if self.adjacent: + ParserElement.ignore(self, other) + else: + super( Combine, self).ignore( other ) + return self + + def postParse( self, instring, loc, tokenlist ): + retToks = tokenlist.copy() + del retToks[:] + retToks += ParseResults([ "".join(tokenlist._asStringList(self.joinString)) ], modal=self.modalResults) + + if self.resultsName and retToks.haskeys(): + return [ retToks ] + else: + return retToks + +class Group(TokenConverter): + """ + Converter to return the matched tokens as a list - useful for returning tokens of C{L{ZeroOrMore}} and C{L{OneOrMore}} expressions. + + Example:: + ident = Word(alphas) + num = Word(nums) + term = ident | num + func = ident + Optional(delimitedList(term)) + print(func.parseString("fn a,b,100")) # -> ['fn', 'a', 'b', '100'] + + func = ident + Group(Optional(delimitedList(term))) + print(func.parseString("fn a,b,100")) # -> ['fn', ['a', 'b', '100']] + """ + def __init__( self, expr ): + super(Group,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + return [ tokenlist ] + +class Dict(TokenConverter): + """ + Converter to return a repetitive expression as a list, but also as a dictionary. + Each element can also be referenced using the first token in the expression as its key. + Useful for tabular report scraping when the first column can be used as a item key. + + Example:: + data_word = Word(alphas) + label = data_word + FollowedBy(':') + attr_expr = Group(label + Suppress(':') + OneOrMore(data_word).setParseAction(' '.join)) + + text = "shape: SQUARE posn: upper left color: light blue texture: burlap" + attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + + # print attributes as plain groups + print(OneOrMore(attr_expr).parseString(text).dump()) + + # instead of OneOrMore(expr), parse using Dict(OneOrMore(Group(expr))) - Dict will auto-assign names + result = Dict(OneOrMore(Group(attr_expr))).parseString(text) + print(result.dump()) + + # access named fields as dict entries, or output as dict + print(result['shape']) + print(result.asDict()) + prints:: + ['shape', 'SQUARE', 'posn', 'upper left', 'color', 'light blue', 'texture', 'burlap'] + + [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] + - color: light blue + - posn: upper left + - shape: SQUARE + - texture: burlap + SQUARE + {'color': 'light blue', 'posn': 'upper left', 'texture': 'burlap', 'shape': 'SQUARE'} + See more examples at L{ParseResults} of accessing fields by results name. + """ + def __init__( self, expr ): + super(Dict,self).__init__( expr ) + self.saveAsList = True + + def postParse( self, instring, loc, tokenlist ): + for i,tok in enumerate(tokenlist): + if len(tok) == 0: + continue + ikey = tok[0] + if isinstance(ikey,int): + ikey = _ustr(tok[0]).strip() + if len(tok)==1: + tokenlist[ikey] = _ParseResultsWithOffset("",i) + elif len(tok)==2 and not isinstance(tok[1],ParseResults): + tokenlist[ikey] = _ParseResultsWithOffset(tok[1],i) + else: + dictvalue = tok.copy() #ParseResults(i) + del dictvalue[0] + if len(dictvalue)!= 1 or (isinstance(dictvalue,ParseResults) and dictvalue.haskeys()): + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue,i) + else: + tokenlist[ikey] = _ParseResultsWithOffset(dictvalue[0],i) + + if self.resultsName: + return [ tokenlist ] + else: + return tokenlist + + +class Suppress(TokenConverter): + """ + Converter for ignoring the results of a parsed expression. + + Example:: + source = "a, b, c,d" + wd = Word(alphas) + wd_list1 = wd + ZeroOrMore(',' + wd) + print(wd_list1.parseString(source)) + + # often, delimiters that are useful during parsing are just in the + # way afterward - use Suppress to keep them out of the parsed output + wd_list2 = wd + ZeroOrMore(Suppress(',') + wd) + print(wd_list2.parseString(source)) + prints:: + ['a', ',', 'b', ',', 'c', ',', 'd'] + ['a', 'b', 'c', 'd'] + (See also L{delimitedList}.) + """ + def postParse( self, instring, loc, tokenlist ): + return [] + + def suppress( self ): + return self + + +class OnlyOnce(object): + """ + Wrapper for parse actions, to ensure they are only called once. + """ + def __init__(self, methodCall): + self.callable = _trim_arity(methodCall) + self.called = False + def __call__(self,s,l,t): + if not self.called: + results = self.callable(s,l,t) + self.called = True + return results + raise ParseException(s,l,"") + def reset(self): + self.called = False + +def traceParseAction(f): + """ + Decorator for debugging parse actions. + + When the parse action is called, this decorator will print C{">> entering I{method-name}(line:I{current_source_line}, I{parse_location}, I{matched_tokens})".} + When the parse action completes, the decorator will print C{"<<"} followed by the returned value, or any exception that the parse action raised. + + Example:: + wd = Word(alphas) + + @traceParseAction + def remove_duplicate_chars(tokens): + return ''.join(sorted(set(''.join(tokens))) + + wds = OneOrMore(wd).setParseAction(remove_duplicate_chars) + print(wds.parseString("slkdjs sld sldd sdlf sdljf")) + prints:: + >>entering remove_duplicate_chars(line: 'slkdjs sld sldd sdlf sdljf', 0, (['slkdjs', 'sld', 'sldd', 'sdlf', 'sdljf'], {})) + <3: + thisFunc = paArgs[0].__class__.__name__ + '.' + thisFunc + sys.stderr.write( ">>entering %s(line: '%s', %d, %r)\n" % (thisFunc,line(l,s),l,t) ) + try: + ret = f(*paArgs) + except Exception as exc: + sys.stderr.write( "< ['aa', 'bb', 'cc'] + delimitedList(Word(hexnums), delim=':', combine=True).parseString("AA:BB:CC:DD:EE") # -> ['AA:BB:CC:DD:EE'] + """ + dlName = _ustr(expr)+" ["+_ustr(delim)+" "+_ustr(expr)+"]..." + if combine: + return Combine( expr + ZeroOrMore( delim + expr ) ).setName(dlName) + else: + return ( expr + ZeroOrMore( Suppress( delim ) + expr ) ).setName(dlName) + +def countedArray( expr, intExpr=None ): + """ + Helper to define a counted list of expressions. + This helper defines a pattern of the form:: + integer expr expr expr... + where the leading integer tells how many expr expressions follow. + The matched tokens returns the array of expr tokens as a list - the leading count token is suppressed. + + If C{intExpr} is specified, it should be a pyparsing expression that produces an integer value. + + Example:: + countedArray(Word(alphas)).parseString('2 ab cd ef') # -> ['ab', 'cd'] + + # in this parser, the leading integer value is given in binary, + # '10' indicating that 2 values are in the array + binaryConstant = Word('01').setParseAction(lambda t: int(t[0], 2)) + countedArray(Word(alphas), intExpr=binaryConstant).parseString('10 ab cd ef') # -> ['ab', 'cd'] + """ + arrayExpr = Forward() + def countFieldParseAction(s,l,t): + n = t[0] + arrayExpr << (n and Group(And([expr]*n)) or Group(empty)) + return [] + if intExpr is None: + intExpr = Word(nums).setParseAction(lambda t:int(t[0])) + else: + intExpr = intExpr.copy() + intExpr.setName("arrayLen") + intExpr.addParseAction(countFieldParseAction, callDuringTry=True) + return ( intExpr + arrayExpr ).setName('(len) ' + _ustr(expr) + '...') + +def _flatten(L): + ret = [] + for i in L: + if isinstance(i,list): + ret.extend(_flatten(i)) + else: + ret.append(i) + return ret + +def matchPreviousLiteral(expr): + """ + Helper to define an expression that is indirectly defined from + the tokens matched in a previous expression, that is, it looks + for a 'repeat' of a previous expression. For example:: + first = Word(nums) + second = matchPreviousLiteral(first) + matchExpr = first + ":" + second + will match C{"1:1"}, but not C{"1:2"}. Because this matches a + previous literal, will also match the leading C{"1:1"} in C{"1:10"}. + If this is not desired, use C{matchPreviousExpr}. + Do I{not} use with packrat parsing enabled. + """ + rep = Forward() + def copyTokenToRepeater(s,l,t): + if t: + if len(t) == 1: + rep << t[0] + else: + # flatten t tokens + tflat = _flatten(t.asList()) + rep << And(Literal(tt) for tt in tflat) + else: + rep << Empty() + expr.addParseAction(copyTokenToRepeater, callDuringTry=True) + rep.setName('(prev) ' + _ustr(expr)) + return rep + +def matchPreviousExpr(expr): + """ + Helper to define an expression that is indirectly defined from + the tokens matched in a previous expression, that is, it looks + for a 'repeat' of a previous expression. For example:: + first = Word(nums) + second = matchPreviousExpr(first) + matchExpr = first + ":" + second + will match C{"1:1"}, but not C{"1:2"}. Because this matches by + expressions, will I{not} match the leading C{"1:1"} in C{"1:10"}; + the expressions are evaluated first, and then compared, so + C{"1"} is compared with C{"10"}. + Do I{not} use with packrat parsing enabled. + """ + rep = Forward() + e2 = expr.copy() + rep <<= e2 + def copyTokenToRepeater(s,l,t): + matchTokens = _flatten(t.asList()) + def mustMatchTheseTokens(s,l,t): + theseTokens = _flatten(t.asList()) + if theseTokens != matchTokens: + raise ParseException("",0,"") + rep.setParseAction( mustMatchTheseTokens, callDuringTry=True ) + expr.addParseAction(copyTokenToRepeater, callDuringTry=True) + rep.setName('(prev) ' + _ustr(expr)) + return rep + +def _escapeRegexRangeChars(s): + #~ escape these chars: ^-] + for c in r"\^-]": + s = s.replace(c,_bslash+c) + s = s.replace("\n",r"\n") + s = s.replace("\t",r"\t") + return _ustr(s) + +def oneOf( strs, caseless=False, useRegex=True ): + """ + Helper to quickly define a set of alternative Literals, and makes sure to do + longest-first testing when there is a conflict, regardless of the input order, + but returns a C{L{MatchFirst}} for best performance. + + Parameters: + - strs - a string of space-delimited literals, or a collection of string literals + - caseless - (default=C{False}) - treat all literals as caseless + - useRegex - (default=C{True}) - as an optimization, will generate a Regex + object; otherwise, will generate a C{MatchFirst} object (if C{caseless=True}, or + if creating a C{Regex} raises an exception) + + Example:: + comp_oper = oneOf("< = > <= >= !=") + var = Word(alphas) + number = Word(nums) + term = var | number + comparison_expr = term + comp_oper + term + print(comparison_expr.searchString("B = 12 AA=23 B<=AA AA>12")) + prints:: + [['B', '=', '12'], ['AA', '=', '23'], ['B', '<=', 'AA'], ['AA', '>', '12']] + """ + if caseless: + isequal = ( lambda a,b: a.upper() == b.upper() ) + masks = ( lambda a,b: b.upper().startswith(a.upper()) ) + parseElementClass = CaselessLiteral + else: + isequal = ( lambda a,b: a == b ) + masks = ( lambda a,b: b.startswith(a) ) + parseElementClass = Literal + + symbols = [] + if isinstance(strs,basestring): + symbols = strs.split() + elif isinstance(strs, collections.Iterable): + symbols = list(strs) + else: + warnings.warn("Invalid argument to oneOf, expected string or iterable", + SyntaxWarning, stacklevel=2) + if not symbols: + return NoMatch() + + i = 0 + while i < len(symbols)-1: + cur = symbols[i] + for j,other in enumerate(symbols[i+1:]): + if ( isequal(other, cur) ): + del symbols[i+j+1] + break + elif ( masks(cur, other) ): + del symbols[i+j+1] + symbols.insert(i,other) + cur = other + break + else: + i += 1 + + if not caseless and useRegex: + #~ print (strs,"->", "|".join( [ _escapeRegexChars(sym) for sym in symbols] )) + try: + if len(symbols)==len("".join(symbols)): + return Regex( "[%s]" % "".join(_escapeRegexRangeChars(sym) for sym in symbols) ).setName(' | '.join(symbols)) + else: + return Regex( "|".join(re.escape(sym) for sym in symbols) ).setName(' | '.join(symbols)) + except Exception: + warnings.warn("Exception creating Regex for oneOf, building MatchFirst", + SyntaxWarning, stacklevel=2) + + + # last resort, just use MatchFirst + return MatchFirst(parseElementClass(sym) for sym in symbols).setName(' | '.join(symbols)) + +def dictOf( key, value ): + """ + Helper to easily and clearly define a dictionary by specifying the respective patterns + for the key and value. Takes care of defining the C{L{Dict}}, C{L{ZeroOrMore}}, and C{L{Group}} tokens + in the proper order. The key pattern can include delimiting markers or punctuation, + as long as they are suppressed, thereby leaving the significant key text. The value + pattern can include named results, so that the C{Dict} results can include named token + fields. + + Example:: + text = "shape: SQUARE posn: upper left color: light blue texture: burlap" + attr_expr = (label + Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join)) + print(OneOrMore(attr_expr).parseString(text).dump()) + + attr_label = label + attr_value = Suppress(':') + OneOrMore(data_word, stopOn=label).setParseAction(' '.join) + + # similar to Dict, but simpler call format + result = dictOf(attr_label, attr_value).parseString(text) + print(result.dump()) + print(result['shape']) + print(result.shape) # object attribute access works too + print(result.asDict()) + prints:: + [['shape', 'SQUARE'], ['posn', 'upper left'], ['color', 'light blue'], ['texture', 'burlap']] + - color: light blue + - posn: upper left + - shape: SQUARE + - texture: burlap + SQUARE + SQUARE + {'color': 'light blue', 'shape': 'SQUARE', 'posn': 'upper left', 'texture': 'burlap'} + """ + return Dict( ZeroOrMore( Group ( key + value ) ) ) + +def originalTextFor(expr, asString=True): + """ + Helper to return the original, untokenized text for a given expression. Useful to + restore the parsed fields of an HTML start tag into the raw tag text itself, or to + revert separate tokens with intervening whitespace back to the original matching + input text. By default, returns astring containing the original parsed text. + + If the optional C{asString} argument is passed as C{False}, then the return value is a + C{L{ParseResults}} containing any results names that were originally matched, and a + single token containing the original matched text from the input string. So if + the expression passed to C{L{originalTextFor}} contains expressions with defined + results names, you must set C{asString} to C{False} if you want to preserve those + results name values. + + Example:: + src = "this is test bold text normal text " + for tag in ("b","i"): + opener,closer = makeHTMLTags(tag) + patt = originalTextFor(opener + SkipTo(closer) + closer) + print(patt.searchString(src)[0]) + prints:: + [' bold text '] + ['text'] + """ + locMarker = Empty().setParseAction(lambda s,loc,t: loc) + endlocMarker = locMarker.copy() + endlocMarker.callPreparse = False + matchExpr = locMarker("_original_start") + expr + endlocMarker("_original_end") + if asString: + extractText = lambda s,l,t: s[t._original_start:t._original_end] + else: + def extractText(s,l,t): + t[:] = [s[t.pop('_original_start'):t.pop('_original_end')]] + matchExpr.setParseAction(extractText) + matchExpr.ignoreExprs = expr.ignoreExprs + return matchExpr + +def ungroup(expr): + """ + Helper to undo pyparsing's default grouping of And expressions, even + if all but one are non-empty. + """ + return TokenConverter(expr).setParseAction(lambda t:t[0]) + +def locatedExpr(expr): + """ + Helper to decorate a returned token with its starting and ending locations in the input string. + This helper adds the following results names: + - locn_start = location where matched expression begins + - locn_end = location where matched expression ends + - value = the actual parsed results + + Be careful if the input text contains C{} characters, you may want to call + C{L{ParserElement.parseWithTabs}} + + Example:: + wd = Word(alphas) + for match in locatedExpr(wd).searchString("ljsdf123lksdjjf123lkkjj1222"): + print(match) + prints:: + [[0, 'ljsdf', 5]] + [[8, 'lksdjjf', 15]] + [[18, 'lkkjj', 23]] + """ + locator = Empty().setParseAction(lambda s,l,t: l) + return Group(locator("locn_start") + expr("value") + locator.copy().leaveWhitespace()("locn_end")) + + +# convenience constants for positional expressions +empty = Empty().setName("empty") +lineStart = LineStart().setName("lineStart") +lineEnd = LineEnd().setName("lineEnd") +stringStart = StringStart().setName("stringStart") +stringEnd = StringEnd().setName("stringEnd") + +_escapedPunc = Word( _bslash, r"\[]-*.$+^?()~ ", exact=2 ).setParseAction(lambda s,l,t:t[0][1]) +_escapedHexChar = Regex(r"\\0?[xX][0-9a-fA-F]+").setParseAction(lambda s,l,t:unichr(int(t[0].lstrip(r'\0x'),16))) +_escapedOctChar = Regex(r"\\0[0-7]+").setParseAction(lambda s,l,t:unichr(int(t[0][1:],8))) +_singleChar = _escapedPunc | _escapedHexChar | _escapedOctChar | Word(printables, excludeChars=r'\]', exact=1) | Regex(r"\w", re.UNICODE) +_charRange = Group(_singleChar + Suppress("-") + _singleChar) +_reBracketExpr = Literal("[") + Optional("^").setResultsName("negate") + Group( OneOrMore( _charRange | _singleChar ) ).setResultsName("body") + "]" + +def srange(s): + r""" + Helper to easily define string ranges for use in Word construction. Borrows + syntax from regexp '[]' string range definitions:: + srange("[0-9]") -> "0123456789" + srange("[a-z]") -> "abcdefghijklmnopqrstuvwxyz" + srange("[a-z$_]") -> "abcdefghijklmnopqrstuvwxyz$_" + The input string must be enclosed in []'s, and the returned string is the expanded + character set joined into a single string. + The values enclosed in the []'s may be: + - a single character + - an escaped character with a leading backslash (such as C{\-} or C{\]}) + - an escaped hex character with a leading C{'\x'} (C{\x21}, which is a C{'!'} character) + (C{\0x##} is also supported for backwards compatibility) + - an escaped octal character with a leading C{'\0'} (C{\041}, which is a C{'!'} character) + - a range of any of the above, separated by a dash (C{'a-z'}, etc.) + - any combination of the above (C{'aeiouy'}, C{'a-zA-Z0-9_$'}, etc.) + """ + _expanded = lambda p: p if not isinstance(p,ParseResults) else ''.join(unichr(c) for c in range(ord(p[0]),ord(p[1])+1)) + try: + return "".join(_expanded(part) for part in _reBracketExpr.parseString(s).body) + except Exception: + return "" + +def matchOnlyAtCol(n): + """ + Helper method for defining parse actions that require matching at a specific + column in the input text. + """ + def verifyCol(strg,locn,toks): + if col(locn,strg) != n: + raise ParseException(strg,locn,"matched token not at column %d" % n) + return verifyCol + +def replaceWith(replStr): + """ + Helper method for common parse actions that simply return a literal value. Especially + useful when used with C{L{transformString}()}. + + Example:: + num = Word(nums).setParseAction(lambda toks: int(toks[0])) + na = oneOf("N/A NA").setParseAction(replaceWith(math.nan)) + term = na | num + + OneOrMore(term).parseString("324 234 N/A 234") # -> [324, 234, nan, 234] + """ + return lambda s,l,t: [replStr] + +def removeQuotes(s,l,t): + """ + Helper parse action for removing quotation marks from parsed quoted strings. + + Example:: + # by default, quotation marks are included in parsed results + quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["'Now is the Winter of our Discontent'"] + + # use removeQuotes to strip quotation marks from parsed results + quotedString.setParseAction(removeQuotes) + quotedString.parseString("'Now is the Winter of our Discontent'") # -> ["Now is the Winter of our Discontent"] + """ + return t[0][1:-1] + +def tokenMap(func, *args): + """ + Helper to define a parse action by mapping a function to all elements of a ParseResults list.If any additional + args are passed, they are forwarded to the given function as additional arguments after + the token, as in C{hex_integer = Word(hexnums).setParseAction(tokenMap(int, 16))}, which will convert the + parsed data to an integer using base 16. + + Example (compare the last to example in L{ParserElement.transformString}:: + hex_ints = OneOrMore(Word(hexnums)).setParseAction(tokenMap(int, 16)) + hex_ints.runTests(''' + 00 11 22 aa FF 0a 0d 1a + ''') + + upperword = Word(alphas).setParseAction(tokenMap(str.upper)) + OneOrMore(upperword).runTests(''' + my kingdom for a horse + ''') + + wd = Word(alphas).setParseAction(tokenMap(str.title)) + OneOrMore(wd).setParseAction(' '.join).runTests(''' + now is the winter of our discontent made glorious summer by this sun of york + ''') + prints:: + 00 11 22 aa FF 0a 0d 1a + [0, 17, 34, 170, 255, 10, 13, 26] + + my kingdom for a horse + ['MY', 'KINGDOM', 'FOR', 'A', 'HORSE'] + + now is the winter of our discontent made glorious summer by this sun of york + ['Now Is The Winter Of Our Discontent Made Glorious Summer By This Sun Of York'] + """ + def pa(s,l,t): + return [func(tokn, *args) for tokn in t] + + try: + func_name = getattr(func, '__name__', + getattr(func, '__class__').__name__) + except Exception: + func_name = str(func) + pa.__name__ = func_name + + return pa + +upcaseTokens = tokenMap(lambda t: _ustr(t).upper()) +"""(Deprecated) Helper parse action to convert tokens to upper case. Deprecated in favor of L{pyparsing_common.upcaseTokens}""" + +downcaseTokens = tokenMap(lambda t: _ustr(t).lower()) +"""(Deprecated) Helper parse action to convert tokens to lower case. Deprecated in favor of L{pyparsing_common.downcaseTokens}""" + +def _makeTags(tagStr, xml): + """Internal helper to construct opening and closing tag expressions, given a tag name""" + if isinstance(tagStr,basestring): + resname = tagStr + tagStr = Keyword(tagStr, caseless=not xml) + else: + resname = tagStr.name + + tagAttrName = Word(alphas,alphanums+"_-:") + if (xml): + tagAttrValue = dblQuotedString.copy().setParseAction( removeQuotes ) + openTag = Suppress("<") + tagStr("tag") + \ + Dict(ZeroOrMore(Group( tagAttrName + Suppress("=") + tagAttrValue ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + else: + printablesLessRAbrack = "".join(c for c in printables if c not in ">") + tagAttrValue = quotedString.copy().setParseAction( removeQuotes ) | Word(printablesLessRAbrack) + openTag = Suppress("<") + tagStr("tag") + \ + Dict(ZeroOrMore(Group( tagAttrName.setParseAction(downcaseTokens) + \ + Optional( Suppress("=") + tagAttrValue ) ))) + \ + Optional("/",default=[False]).setResultsName("empty").setParseAction(lambda s,l,t:t[0]=='/') + Suppress(">") + closeTag = Combine(_L("") + + openTag = openTag.setResultsName("start"+"".join(resname.replace(":"," ").title().split())).setName("<%s>" % resname) + closeTag = closeTag.setResultsName("end"+"".join(resname.replace(":"," ").title().split())).setName("" % resname) + openTag.tag = resname + closeTag.tag = resname + return openTag, closeTag + +def makeHTMLTags(tagStr): + """ + Helper to construct opening and closing tag expressions for HTML, given a tag name. Matches + tags in either upper or lower case, attributes with namespaces and with quoted or unquoted values. + + Example:: + text = 'More info at the pyparsing wiki page' + # makeHTMLTags returns pyparsing expressions for the opening and closing tags as a 2-tuple + a,a_end = makeHTMLTags("A") + link_expr = a + SkipTo(a_end)("link_text") + a_end + + for link in link_expr.searchString(text): + # attributes in the tag (like "href" shown here) are also accessible as named results + print(link.link_text, '->', link.href) + prints:: + pyparsing -> http://pyparsing.wikispaces.com + """ + return _makeTags( tagStr, False ) + +def makeXMLTags(tagStr): + """ + Helper to construct opening and closing tag expressions for XML, given a tag name. Matches + tags only in the given upper/lower case. + + Example: similar to L{makeHTMLTags} + """ + return _makeTags( tagStr, True ) + +def withAttribute(*args,**attrDict): + """ + Helper to create a validating parse action to be used with start tags created + with C{L{makeXMLTags}} or C{L{makeHTMLTags}}. Use C{withAttribute} to qualify a starting tag + with a required attribute value, to avoid false matches on common tags such as + C{} or C{
}. + + Call C{withAttribute} with a series of attribute names and values. Specify the list + of filter attributes names and values as: + - keyword arguments, as in C{(align="right")}, or + - as an explicit dict with C{**} operator, when an attribute name is also a Python + reserved word, as in C{**{"class":"Customer", "align":"right"}} + - a list of name-value tuples, as in ( ("ns1:class", "Customer"), ("ns2:align","right") ) + For attribute names with a namespace prefix, you must use the second form. Attribute + names are matched insensitive to upper/lower case. + + If just testing for C{class} (with or without a namespace), use C{L{withClass}}. + + To verify that the attribute exists, but without specifying a value, pass + C{withAttribute.ANY_VALUE} as the value. + + Example:: + html = ''' +
+ Some text +
1 4 0 1 0
+
1,3 2,3 1,1
+
this has no type
+
+ + ''' + div,div_end = makeHTMLTags("div") + + # only match div tag having a type attribute with value "grid" + div_grid = div().setParseAction(withAttribute(type="grid")) + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + # construct a match with any div tag having a type attribute, regardless of the value + div_any_type = div().setParseAction(withAttribute(type=withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + if args: + attrs = args[:] + else: + attrs = attrDict.items() + attrs = [(k,v) for k,v in attrs] + def pa(s,l,tokens): + for attrName,attrValue in attrs: + if attrName not in tokens: + raise ParseException(s,l,"no matching attribute " + attrName) + if attrValue != withAttribute.ANY_VALUE and tokens[attrName] != attrValue: + raise ParseException(s,l,"attribute '%s' has value '%s', must be '%s'" % + (attrName, tokens[attrName], attrValue)) + return pa +withAttribute.ANY_VALUE = object() + +def withClass(classname, namespace=''): + """ + Simplified version of C{L{withAttribute}} when matching on a div class - made + difficult because C{class} is a reserved word in Python. + + Example:: + html = ''' +
+ Some text +
1 4 0 1 0
+
1,3 2,3 1,1
+
this <div> has no class
+
+ + ''' + div,div_end = makeHTMLTags("div") + div_grid = div().setParseAction(withClass("grid")) + + grid_expr = div_grid + SkipTo(div | div_end)("body") + for grid_header in grid_expr.searchString(html): + print(grid_header.body) + + div_any_type = div().setParseAction(withClass(withAttribute.ANY_VALUE)) + div_expr = div_any_type + SkipTo(div | div_end)("body") + for div_header in div_expr.searchString(html): + print(div_header.body) + prints:: + 1 4 0 1 0 + + 1 4 0 1 0 + 1,3 2,3 1,1 + """ + classattr = "%s:class" % namespace if namespace else "class" + return withAttribute(**{classattr : classname}) + +opAssoc = _Constants() +opAssoc.LEFT = object() +opAssoc.RIGHT = object() + +def infixNotation( baseExpr, opList, lpar=Suppress('('), rpar=Suppress(')') ): + """ + Helper method for constructing grammars of expressions made up of + operators working in a precedence hierarchy. Operators may be unary or + binary, left- or right-associative. Parse actions can also be attached + to operator expressions. The generated parser will also recognize the use + of parentheses to override operator precedences (see example below). + + Note: if you define a deep operator list, you may see performance issues + when using infixNotation. See L{ParserElement.enablePackrat} for a + mechanism to potentially improve your parser performance. + + Parameters: + - baseExpr - expression representing the most basic element for the nested + - opList - list of tuples, one for each operator precedence level in the + expression grammar; each tuple is of the form + (opExpr, numTerms, rightLeftAssoc, parseAction), where: + - opExpr is the pyparsing expression for the operator; + may also be a string, which will be converted to a Literal; + if numTerms is 3, opExpr is a tuple of two expressions, for the + two operators separating the 3 terms + - numTerms is the number of terms for this operator (must + be 1, 2, or 3) + - rightLeftAssoc is the indicator whether the operator is + right or left associative, using the pyparsing-defined + constants C{opAssoc.RIGHT} and C{opAssoc.LEFT}. + - parseAction is the parse action to be associated with + expressions matching this operator expression (the + parse action tuple member may be omitted); if the parse action + is passed a tuple or list of functions, this is equivalent to + calling C{setParseAction(*fn)} (L{ParserElement.setParseAction}) + - lpar - expression for matching left-parentheses (default=C{Suppress('(')}) + - rpar - expression for matching right-parentheses (default=C{Suppress(')')}) + + Example:: + # simple example of four-function arithmetic with ints and variable names + integer = pyparsing_common.signed_integer + varname = pyparsing_common.identifier + + arith_expr = infixNotation(integer | varname, + [ + ('-', 1, opAssoc.RIGHT), + (oneOf('* /'), 2, opAssoc.LEFT), + (oneOf('+ -'), 2, opAssoc.LEFT), + ]) + + arith_expr.runTests(''' + 5+3*6 + (5+3)*6 + -2--11 + ''', fullDump=False) + prints:: + 5+3*6 + [[5, '+', [3, '*', 6]]] + + (5+3)*6 + [[[5, '+', 3], '*', 6]] + + -2--11 + [[['-', 2], '-', ['-', 11]]] + """ + ret = Forward() + lastExpr = baseExpr | ( lpar + ret + rpar ) + for i,operDef in enumerate(opList): + opExpr,arity,rightLeftAssoc,pa = (operDef + (None,))[:4] + termName = "%s term" % opExpr if arity < 3 else "%s%s term" % opExpr + if arity == 3: + if opExpr is None or len(opExpr) != 2: + raise ValueError("if numterms=3, opExpr must be a tuple or list of two expressions") + opExpr1, opExpr2 = opExpr + thisExpr = Forward().setName(termName) + if rightLeftAssoc == opAssoc.LEFT: + if arity == 1: + matchExpr = FollowedBy(lastExpr + opExpr) + Group( lastExpr + OneOrMore( opExpr ) ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + lastExpr) + Group( lastExpr + OneOrMore( opExpr + lastExpr ) ) + else: + matchExpr = FollowedBy(lastExpr+lastExpr) + Group( lastExpr + OneOrMore(lastExpr) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr) + \ + Group( lastExpr + opExpr1 + lastExpr + opExpr2 + lastExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + elif rightLeftAssoc == opAssoc.RIGHT: + if arity == 1: + # try to avoid LR with this extra test + if not isinstance(opExpr, Optional): + opExpr = Optional(opExpr) + matchExpr = FollowedBy(opExpr.expr + thisExpr) + Group( opExpr + thisExpr ) + elif arity == 2: + if opExpr is not None: + matchExpr = FollowedBy(lastExpr + opExpr + thisExpr) + Group( lastExpr + OneOrMore( opExpr + thisExpr ) ) + else: + matchExpr = FollowedBy(lastExpr + thisExpr) + Group( lastExpr + OneOrMore( thisExpr ) ) + elif arity == 3: + matchExpr = FollowedBy(lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr) + \ + Group( lastExpr + opExpr1 + thisExpr + opExpr2 + thisExpr ) + else: + raise ValueError("operator must be unary (1), binary (2), or ternary (3)") + else: + raise ValueError("operator must indicate right or left associativity") + if pa: + if isinstance(pa, (tuple, list)): + matchExpr.setParseAction(*pa) + else: + matchExpr.setParseAction(pa) + thisExpr <<= ( matchExpr.setName(termName) | lastExpr ) + lastExpr = thisExpr + ret <<= lastExpr + return ret + +operatorPrecedence = infixNotation +"""(Deprecated) Former name of C{L{infixNotation}}, will be dropped in a future release.""" + +dblQuotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"').setName("string enclosed in double quotes") +sglQuotedString = Combine(Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("string enclosed in single quotes") +quotedString = Combine(Regex(r'"(?:[^"\n\r\\]|(?:"")|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*')+'"'| + Regex(r"'(?:[^'\n\r\\]|(?:'')|(?:\\(?:[^x]|x[0-9a-fA-F]+)))*")+"'").setName("quotedString using single or double quotes") +unicodeString = Combine(_L('u') + quotedString.copy()).setName("unicode string literal") + +def nestedExpr(opener="(", closer=")", content=None, ignoreExpr=quotedString.copy()): + """ + Helper method for defining nested lists enclosed in opening and closing + delimiters ("(" and ")" are the default). + + Parameters: + - opener - opening character for a nested list (default=C{"("}); can also be a pyparsing expression + - closer - closing character for a nested list (default=C{")"}); can also be a pyparsing expression + - content - expression for items within the nested lists (default=C{None}) + - ignoreExpr - expression for ignoring opening and closing delimiters (default=C{quotedString}) + + If an expression is not provided for the content argument, the nested + expression will capture all whitespace-delimited content between delimiters + as a list of separate values. + + Use the C{ignoreExpr} argument to define expressions that may contain + opening or closing characters that should not be treated as opening + or closing characters for nesting, such as quotedString or a comment + expression. Specify multiple expressions using an C{L{Or}} or C{L{MatchFirst}}. + The default is L{quotedString}, but if no expressions are to be ignored, + then pass C{None} for this argument. + + Example:: + data_type = oneOf("void int short long char float double") + decl_data_type = Combine(data_type + Optional(Word('*'))) + ident = Word(alphas+'_', alphanums+'_') + number = pyparsing_common.number + arg = Group(decl_data_type + ident) + LPAR,RPAR = map(Suppress, "()") + + code_body = nestedExpr('{', '}', ignoreExpr=(quotedString | cStyleComment)) + + c_function = (decl_data_type("type") + + ident("name") + + LPAR + Optional(delimitedList(arg), [])("args") + RPAR + + code_body("body")) + c_function.ignore(cStyleComment) + + source_code = ''' + int is_odd(int x) { + return (x%2); + } + + int dec_to_hex(char hchar) { + if (hchar >= '0' && hchar <= '9') { + return (ord(hchar)-ord('0')); + } else { + return (10+ord(hchar)-ord('A')); + } + } + ''' + for func in c_function.searchString(source_code): + print("%(name)s (%(type)s) args: %(args)s" % func) + + prints:: + is_odd (int) args: [['int', 'x']] + dec_to_hex (int) args: [['char', 'hchar']] + """ + if opener == closer: + raise ValueError("opening and closing strings cannot be the same") + if content is None: + if isinstance(opener,basestring) and isinstance(closer,basestring): + if len(opener) == 1 and len(closer)==1: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (empty.copy()+CharsNotIn(opener+closer+ParserElement.DEFAULT_WHITE_CHARS + ).setParseAction(lambda t:t[0].strip())) + else: + if ignoreExpr is not None: + content = (Combine(OneOrMore(~ignoreExpr + + ~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + content = (Combine(OneOrMore(~Literal(opener) + ~Literal(closer) + + CharsNotIn(ParserElement.DEFAULT_WHITE_CHARS,exact=1)) + ).setParseAction(lambda t:t[0].strip())) + else: + raise ValueError("opening and closing arguments must be strings if no content expression is given") + ret = Forward() + if ignoreExpr is not None: + ret <<= Group( Suppress(opener) + ZeroOrMore( ignoreExpr | ret | content ) + Suppress(closer) ) + else: + ret <<= Group( Suppress(opener) + ZeroOrMore( ret | content ) + Suppress(closer) ) + ret.setName('nested %s%s expression' % (opener,closer)) + return ret + +def indentedBlock(blockStatementExpr, indentStack, indent=True): + """ + Helper method for defining space-delimited indentation blocks, such as + those used to define block statements in Python source code. + + Parameters: + - blockStatementExpr - expression defining syntax of statement that + is repeated within the indented block + - indentStack - list created by caller to manage indentation stack + (multiple statementWithIndentedBlock expressions within a single grammar + should share a common indentStack) + - indent - boolean indicating whether block must be indented beyond the + the current level; set to False for block of left-most statements + (default=C{True}) + + A valid block must contain at least one C{blockStatement}. + + Example:: + data = ''' + def A(z): + A1 + B = 100 + G = A2 + A2 + A3 + B + def BB(a,b,c): + BB1 + def BBA(): + bba1 + bba2 + bba3 + C + D + def spam(x,y): + def eggs(z): + pass + ''' + + + indentStack = [1] + stmt = Forward() + + identifier = Word(alphas, alphanums) + funcDecl = ("def" + identifier + Group( "(" + Optional( delimitedList(identifier) ) + ")" ) + ":") + func_body = indentedBlock(stmt, indentStack) + funcDef = Group( funcDecl + func_body ) + + rvalue = Forward() + funcCall = Group(identifier + "(" + Optional(delimitedList(rvalue)) + ")") + rvalue << (funcCall | identifier | Word(nums)) + assignment = Group(identifier + "=" + rvalue) + stmt << ( funcDef | assignment | identifier ) + + module_body = OneOrMore(stmt) + + parseTree = module_body.parseString(data) + parseTree.pprint() + prints:: + [['def', + 'A', + ['(', 'z', ')'], + ':', + [['A1'], [['B', '=', '100']], [['G', '=', 'A2']], ['A2'], ['A3']]], + 'B', + ['def', + 'BB', + ['(', 'a', 'b', 'c', ')'], + ':', + [['BB1'], [['def', 'BBA', ['(', ')'], ':', [['bba1'], ['bba2'], ['bba3']]]]]], + 'C', + 'D', + ['def', + 'spam', + ['(', 'x', 'y', ')'], + ':', + [[['def', 'eggs', ['(', 'z', ')'], ':', [['pass']]]]]]] + """ + def checkPeerIndent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if curCol != indentStack[-1]: + if curCol > indentStack[-1]: + raise ParseFatalException(s,l,"illegal nesting") + raise ParseException(s,l,"not a peer entry") + + def checkSubIndent(s,l,t): + curCol = col(l,s) + if curCol > indentStack[-1]: + indentStack.append( curCol ) + else: + raise ParseException(s,l,"not a subentry") + + def checkUnindent(s,l,t): + if l >= len(s): return + curCol = col(l,s) + if not(indentStack and curCol < indentStack[-1] and curCol <= indentStack[-2]): + raise ParseException(s,l,"not an unindent") + indentStack.pop() + + NL = OneOrMore(LineEnd().setWhitespaceChars("\t ").suppress()) + INDENT = (Empty() + Empty().setParseAction(checkSubIndent)).setName('INDENT') + PEER = Empty().setParseAction(checkPeerIndent).setName('') + UNDENT = Empty().setParseAction(checkUnindent).setName('UNINDENT') + if indent: + smExpr = Group( Optional(NL) + + #~ FollowedBy(blockStatementExpr) + + INDENT + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) + UNDENT) + else: + smExpr = Group( Optional(NL) + + (OneOrMore( PEER + Group(blockStatementExpr) + Optional(NL) )) ) + blockStatementExpr.ignore(_bslash + LineEnd()) + return smExpr.setName('indented block') + +alphas8bit = srange(r"[\0xc0-\0xd6\0xd8-\0xf6\0xf8-\0xff]") +punc8bit = srange(r"[\0xa1-\0xbf\0xd7\0xf7]") + +anyOpenTag,anyCloseTag = makeHTMLTags(Word(alphas,alphanums+"_:").setName('any tag')) +_htmlEntityMap = dict(zip("gt lt amp nbsp quot apos".split(),'><& "\'')) +commonHTMLEntity = Regex('&(?P' + '|'.join(_htmlEntityMap.keys()) +");").setName("common HTML entity") +def replaceHTMLEntity(t): + """Helper parser action to replace common HTML entities with their special characters""" + return _htmlEntityMap.get(t.entity) + +# it's easy to get these comment structures wrong - they're very common, so may as well make them available +cStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/').setName("C style comment") +"Comment of the form C{/* ... */}" + +htmlComment = Regex(r"").setName("HTML comment") +"Comment of the form C{}" + +restOfLine = Regex(r".*").leaveWhitespace().setName("rest of line") +dblSlashComment = Regex(r"//(?:\\\n|[^\n])*").setName("// comment") +"Comment of the form C{// ... (to end of line)}" + +cppStyleComment = Combine(Regex(r"/\*(?:[^*]|\*(?!/))*") + '*/'| dblSlashComment).setName("C++ style comment") +"Comment of either form C{L{cStyleComment}} or C{L{dblSlashComment}}" + +javaStyleComment = cppStyleComment +"Same as C{L{cppStyleComment}}" + +pythonStyleComment = Regex(r"#.*").setName("Python style comment") +"Comment of the form C{# ... (to end of line)}" + +_commasepitem = Combine(OneOrMore(Word(printables, excludeChars=',') + + Optional( Word(" \t") + + ~Literal(",") + ~LineEnd() ) ) ).streamline().setName("commaItem") +commaSeparatedList = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("commaSeparatedList") +"""(Deprecated) Predefined expression of 1 or more printable words or quoted strings, separated by commas. + This expression is deprecated in favor of L{pyparsing_common.comma_separated_list}.""" + +# some other useful expressions - using lower-case class name since we are really using this as a namespace +class pyparsing_common: + """ + Here are some common low-level expressions that may be useful in jump-starting parser development: + - numeric forms (L{integers}, L{reals}, L{scientific notation}) + - common L{programming identifiers} + - network addresses (L{MAC}, L{IPv4}, L{IPv6}) + - ISO8601 L{dates} and L{datetime} + - L{UUID} + - L{comma-separated list} + Parse actions: + - C{L{convertToInteger}} + - C{L{convertToFloat}} + - C{L{convertToDate}} + - C{L{convertToDatetime}} + - C{L{stripHTMLTags}} + - C{L{upcaseTokens}} + - C{L{downcaseTokens}} + + Example:: + pyparsing_common.number.runTests(''' + # any int or real number, returned as the appropriate type + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.fnumber.runTests(''' + # any int or real number, returned as float + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + ''') + + pyparsing_common.hex_integer.runTests(''' + # hex numbers + 100 + FF + ''') + + pyparsing_common.fraction.runTests(''' + # fractions + 1/2 + -3/4 + ''') + + pyparsing_common.mixed_integer.runTests(''' + # mixed fractions + 1 + 1/2 + -3/4 + 1-3/4 + ''') + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(''' + # uuid + 12345678-1234-5678-1234-567812345678 + ''') + prints:: + # any int or real number, returned as the appropriate type + 100 + [100] + + -100 + [-100] + + +100 + [100] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # any int or real number, returned as float + 100 + [100.0] + + -100 + [-100.0] + + +100 + [100.0] + + 3.14159 + [3.14159] + + 6.02e23 + [6.02e+23] + + 1e-12 + [1e-12] + + # hex numbers + 100 + [256] + + FF + [255] + + # fractions + 1/2 + [0.5] + + -3/4 + [-0.75] + + # mixed fractions + 1 + [1] + + 1/2 + [0.5] + + -3/4 + [-0.75] + + 1-3/4 + [1.75] + + # uuid + 12345678-1234-5678-1234-567812345678 + [UUID('12345678-1234-5678-1234-567812345678')] + """ + + convertToInteger = tokenMap(int) + """ + Parse action for converting parsed integers to Python int + """ + + convertToFloat = tokenMap(float) + """ + Parse action for converting parsed numbers to Python float + """ + + integer = Word(nums).setName("integer").setParseAction(convertToInteger) + """expression that parses an unsigned integer, returns an int""" + + hex_integer = Word(hexnums).setName("hex integer").setParseAction(tokenMap(int,16)) + """expression that parses a hexadecimal integer, returns an int""" + + signed_integer = Regex(r'[+-]?\d+').setName("signed integer").setParseAction(convertToInteger) + """expression that parses an integer with optional leading sign, returns an int""" + + fraction = (signed_integer().setParseAction(convertToFloat) + '/' + signed_integer().setParseAction(convertToFloat)).setName("fraction") + """fractional expression of an integer divided by an integer, returns a float""" + fraction.addParseAction(lambda t: t[0]/t[-1]) + + mixed_integer = (fraction | signed_integer + Optional(Optional('-').suppress() + fraction)).setName("fraction or mixed integer-fraction") + """mixed integer of the form 'integer - fraction', with optional leading integer, returns float""" + mixed_integer.addParseAction(sum) + + real = Regex(r'[+-]?\d+\.\d*').setName("real number").setParseAction(convertToFloat) + """expression that parses a floating point number and returns a float""" + + sci_real = Regex(r'[+-]?\d+([eE][+-]?\d+|\.\d*([eE][+-]?\d+)?)').setName("real number with scientific notation").setParseAction(convertToFloat) + """expression that parses a floating point number with optional scientific notation and returns a float""" + + # streamlining this expression makes the docs nicer-looking + number = (sci_real | real | signed_integer).streamline() + """any numeric expression, returns the corresponding Python type""" + + fnumber = Regex(r'[+-]?\d+\.?\d*([eE][+-]?\d+)?').setName("fnumber").setParseAction(convertToFloat) + """any int or real number, returned as float""" + + identifier = Word(alphas+'_', alphanums+'_').setName("identifier") + """typical code identifier (leading alpha or '_', followed by 0 or more alphas, nums, or '_')""" + + ipv4_address = Regex(r'(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})(\.(25[0-5]|2[0-4][0-9]|1?[0-9]{1,2})){3}').setName("IPv4 address") + "IPv4 address (C{0.0.0.0 - 255.255.255.255})" + + _ipv6_part = Regex(r'[0-9a-fA-F]{1,4}').setName("hex_integer") + _full_ipv6_address = (_ipv6_part + (':' + _ipv6_part)*7).setName("full IPv6 address") + _short_ipv6_address = (Optional(_ipv6_part + (':' + _ipv6_part)*(0,6)) + "::" + Optional(_ipv6_part + (':' + _ipv6_part)*(0,6))).setName("short IPv6 address") + _short_ipv6_address.addCondition(lambda t: sum(1 for tt in t if pyparsing_common._ipv6_part.matches(tt)) < 8) + _mixed_ipv6_address = ("::ffff:" + ipv4_address).setName("mixed IPv6 address") + ipv6_address = Combine((_full_ipv6_address | _mixed_ipv6_address | _short_ipv6_address).setName("IPv6 address")).setName("IPv6 address") + "IPv6 address (long, short, or mixed form)" + + mac_address = Regex(r'[0-9a-fA-F]{2}([:.-])[0-9a-fA-F]{2}(?:\1[0-9a-fA-F]{2}){4}').setName("MAC address") + "MAC address xx:xx:xx:xx:xx (may also have '-' or '.' delimiters)" + + @staticmethod + def convertToDate(fmt="%Y-%m-%d"): + """ + Helper to create a parse action for converting parsed date string to Python datetime.date + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%d"}) + + Example:: + date_expr = pyparsing_common.iso8601_date.copy() + date_expr.setParseAction(pyparsing_common.convertToDate()) + print(date_expr.parseString("1999-12-31")) + prints:: + [datetime.date(1999, 12, 31)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt).date() + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + @staticmethod + def convertToDatetime(fmt="%Y-%m-%dT%H:%M:%S.%f"): + """ + Helper to create a parse action for converting parsed datetime string to Python datetime.datetime + + Params - + - fmt - format to be passed to datetime.strptime (default=C{"%Y-%m-%dT%H:%M:%S.%f"}) + + Example:: + dt_expr = pyparsing_common.iso8601_datetime.copy() + dt_expr.setParseAction(pyparsing_common.convertToDatetime()) + print(dt_expr.parseString("1999-12-31T23:59:59.999")) + prints:: + [datetime.datetime(1999, 12, 31, 23, 59, 59, 999000)] + """ + def cvt_fn(s,l,t): + try: + return datetime.strptime(t[0], fmt) + except ValueError as ve: + raise ParseException(s, l, str(ve)) + return cvt_fn + + iso8601_date = Regex(r'(?P\d{4})(?:-(?P\d\d)(?:-(?P\d\d))?)?').setName("ISO8601 date") + "ISO8601 date (C{yyyy-mm-dd})" + + iso8601_datetime = Regex(r'(?P\d{4})-(?P\d\d)-(?P\d\d)[T ](?P\d\d):(?P\d\d)(:(?P\d\d(\.\d*)?)?)?(?PZ|[+-]\d\d:?\d\d)?').setName("ISO8601 datetime") + "ISO8601 datetime (C{yyyy-mm-ddThh:mm:ss.s(Z|+-00:00)}) - trailing seconds, milliseconds, and timezone optional; accepts separating C{'T'} or C{' '}" + + uuid = Regex(r'[0-9a-fA-F]{8}(-[0-9a-fA-F]{4}){3}-[0-9a-fA-F]{12}').setName("UUID") + "UUID (C{xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx})" + + _html_stripper = anyOpenTag.suppress() | anyCloseTag.suppress() + @staticmethod + def stripHTMLTags(s, l, tokens): + """ + Parse action to remove HTML tags from web page HTML source + + Example:: + # strip HTML links from normal text + text = 'More info at the
pyparsing wiki page' + td,td_end = makeHTMLTags("TD") + table_text = td + SkipTo(td_end).setParseAction(pyparsing_common.stripHTMLTags)("body") + td_end + + print(table_text.parseString(text).body) # -> 'More info at the pyparsing wiki page' + """ + return pyparsing_common._html_stripper.transformString(tokens[0]) + + _commasepitem = Combine(OneOrMore(~Literal(",") + ~LineEnd() + Word(printables, excludeChars=',') + + Optional( White(" \t") ) ) ).streamline().setName("commaItem") + comma_separated_list = delimitedList( Optional( quotedString.copy() | _commasepitem, default="") ).setName("comma separated list") + """Predefined expression of 1 or more printable words or quoted strings, separated by commas.""" + + upcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).upper())) + """Parse action to convert tokens to upper case.""" + + downcaseTokens = staticmethod(tokenMap(lambda t: _ustr(t).lower())) + """Parse action to convert tokens to lower case.""" + + +if __name__ == "__main__": + + selectToken = CaselessLiteral("select") + fromToken = CaselessLiteral("from") + + ident = Word(alphas, alphanums + "_$") + + columnName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + columnNameList = Group(delimitedList(columnName)).setName("columns") + columnSpec = ('*' | columnNameList) + + tableName = delimitedList(ident, ".", combine=True).setParseAction(upcaseTokens) + tableNameList = Group(delimitedList(tableName)).setName("tables") + + simpleSQL = selectToken("command") + columnSpec("columns") + fromToken + tableNameList("tables") + + # demo runTests method, including embedded comments in test string + simpleSQL.runTests(""" + # '*' as column list and dotted table name + select * from SYS.XYZZY + + # caseless match on "SELECT", and casts back to "select" + SELECT * from XYZZY, ABC + + # list of column names, and mixed case SELECT keyword + Select AA,BB,CC from Sys.dual + + # multiple tables + Select A, B, C from Sys.dual, Table2 + + # invalid SELECT keyword - should fail + Xelect A, B, C from Sys.dual + + # incomplete command - should fail + Select + + # invalid column name - should fail + Select ^^^ frox Sys.dual + + """) + + pyparsing_common.number.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + # any int or real number, returned as float + pyparsing_common.fnumber.runTests(""" + 100 + -100 + +100 + 3.14159 + 6.02e23 + 1e-12 + """) + + pyparsing_common.hex_integer.runTests(""" + 100 + FF + """) + + import uuid + pyparsing_common.uuid.setParseAction(tokenMap(uuid.UUID)) + pyparsing_common.uuid.runTests(""" + 12345678-1234-5678-1234-567812345678 + """) diff --git a/tools/ldgen/samples/esp32.lf b/tools/ldgen/samples/esp32.lf new file mode 100644 index 0000000000..03a9377011 --- /dev/null +++ b/tools/ldgen/samples/esp32.lf @@ -0,0 +1,80 @@ +[sections:text] +entries: + .text+ + .literal+ + +[sections:data] +entries: + .data+ + +[sections:bss] +entries: + .bss+ + +[sections:common] +entries: + COMMON + +[sections:rodata] +entries: + .rodata+ + +[sections:rtc_text] +entries: + .rtc.text + .rtc.literal + +[sections:rtc_data] +entries: + .rtc.data + +[sections:rtc_rodata] +entries: + .rtc.rodata + +[sections:rtc_bss] +entries: + .rtc.bss + +[sections:extram_bss] +entries: + .exram.bss + +[sections:iram] +entries: + .iram1+ + +[sections:dram] +entries: + .dram1+ + +[scheme:default] +entries: + text -> flash_text + rodata -> flash_rodata + data -> dram0_data + bss -> dram0_bss + common -> dram0_bss + iram -> iram0_text + dram -> dram0_data + rtc_text -> rtc_text + rtc_data -> rtc_data + rtc_rodata -> rtc_data + rtc_bss -> rtc_bss + +[scheme:rtc] +entries: + text -> rtc_text + data -> rtc_data + rodata -> rtc_data + bss -> rtc_bss + common -> rtc_bss + +[scheme:noflash] +entries: + text -> iram0_text + rodata -> dram0_data + +[scheme:noflash_data] +entries: + rodata -> dram0_data \ No newline at end of file diff --git a/tools/ldgen/samples/mappings.lf b/tools/ldgen/samples/mappings.lf new file mode 100644 index 0000000000..bd029e8582 --- /dev/null +++ b/tools/ldgen/samples/mappings.lf @@ -0,0 +1,62 @@ + +[mapping] +archive: libheap.a +entries: + multi_heap (noflash) + multi_heap_poisoning (noflash) + +[mapping] +archive: libsoc.a +entries: + * (noflash) + +[mapping] +archive: libfreertos.a +entries: + * (noflash) + +[mapping] +archive: libesp32.a +entries: + core_dump (noflash) + panic (noflash) + +[mapping] +archive: libapp_trace.a +entries: + * (noflash) + +[mapping] +archive: libxtensa-debug-module.a +entries: + eri (noflash) + +[mapping] +archive: libphy.a +entries: + * (noflash_data) + +[mapping] +archive: librtc.a +entries: + * (noflash) + +[mapping] +archive: libhal.a +entries: + * (noflash) + +[mapping] +archive: libgcc.a +entries: + lib2funcs (noflash) + +[mapping] +archive: libspi_flash.a +entries: + spi_flash_rom_patch (noflash) + +[mapping] +archive: libgcov.a +entries: + * (noflash) \ No newline at end of file diff --git a/tools/ldgen/samples/sdkconfig b/tools/ldgen/samples/sdkconfig new file mode 100644 index 0000000000..869e9bf0cb --- /dev/null +++ b/tools/ldgen/samples/sdkconfig @@ -0,0 +1,542 @@ +# +# SDK tool configuration +# +CONFIG_TOOLPREFIX="xtensa-esp32-elf-" +CONFIG_PYTHON="python" +CONFIG_MAKE_WARN_UNDEFINED_VARIABLES=y + +# +# Bootloader config +# +CONFIG_LOG_BOOTLOADER_LEVEL_NONE= +CONFIG_LOG_BOOTLOADER_LEVEL_ERROR= +CONFIG_LOG_BOOTLOADER_LEVEL_WARN=y +CONFIG_LOG_BOOTLOADER_LEVEL_INFO= +CONFIG_LOG_BOOTLOADER_LEVEL_DEBUG= +CONFIG_LOG_BOOTLOADER_LEVEL_VERBOSE= +CONFIG_LOG_BOOTLOADER_LEVEL=2 +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_8V= +CONFIG_BOOTLOADER_VDDSDIO_BOOST_1_9V=y + +# +# Security features +# +CONFIG_SECURE_BOOT_ENABLED= +CONFIG_FLASH_ENCRYPTION_ENABLED= + +# +# Serial flasher config +# +CONFIG_ESPTOOLPY_PORT="/dev/ttyUSB0" +CONFIG_ESPTOOLPY_BAUD_115200B=y +CONFIG_ESPTOOLPY_BAUD_230400B= +CONFIG_ESPTOOLPY_BAUD_921600B= +CONFIG_ESPTOOLPY_BAUD_2MB= +CONFIG_ESPTOOLPY_BAUD_OTHER= +CONFIG_ESPTOOLPY_BAUD_OTHER_VAL=115200 +CONFIG_ESPTOOLPY_BAUD=115200 +CONFIG_ESPTOOLPY_COMPRESSED= +CONFIG_FLASHMODE_QIO= +CONFIG_FLASHMODE_QOUT= +CONFIG_FLASHMODE_DIO=y +CONFIG_FLASHMODE_DOUT= +CONFIG_ESPTOOLPY_FLASHMODE="dio" +CONFIG_ESPTOOLPY_FLASHFREQ_80M= +CONFIG_ESPTOOLPY_FLASHFREQ_40M=y +CONFIG_ESPTOOLPY_FLASHFREQ_26M= +CONFIG_ESPTOOLPY_FLASHFREQ_20M= +CONFIG_ESPTOOLPY_FLASHFREQ="40m" +CONFIG_ESPTOOLPY_FLASHSIZE_1MB= +CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y +CONFIG_ESPTOOLPY_FLASHSIZE_4MB= +CONFIG_ESPTOOLPY_FLASHSIZE_8MB= +CONFIG_ESPTOOLPY_FLASHSIZE_16MB= +CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +CONFIG_ESPTOOLPY_FLASHSIZE_DETECT=y +CONFIG_ESPTOOLPY_BEFORE_RESET=y +CONFIG_ESPTOOLPY_BEFORE_NORESET= +CONFIG_ESPTOOLPY_BEFORE="default_reset" +CONFIG_ESPTOOLPY_AFTER_RESET=y +CONFIG_ESPTOOLPY_AFTER_NORESET= +CONFIG_ESPTOOLPY_AFTER="hard_reset" +CONFIG_MONITOR_BAUD_9600B= +CONFIG_MONITOR_BAUD_57600B= +CONFIG_MONITOR_BAUD_115200B=y +CONFIG_MONITOR_BAUD_230400B= +CONFIG_MONITOR_BAUD_921600B= +CONFIG_MONITOR_BAUD_2MB= +CONFIG_MONITOR_BAUD_OTHER= +CONFIG_MONITOR_BAUD_OTHER_VAL=115200 +CONFIG_MONITOR_BAUD=115200 + +# +# Partition Table +# +CONFIG_PARTITION_TABLE_SINGLE_APP=y +CONFIG_PARTITION_TABLE_TWO_OTA= +CONFIG_PARTITION_TABLE_CUSTOM= +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" +CONFIG_PARTITION_TABLE_CUSTOM_APP_BIN_OFFSET=0x10000 +CONFIG_PARTITION_TABLE_FILENAME="partitions_singleapp.csv" +CONFIG_APP_OFFSET=0x10000 +CONFIG_PARTITION_TABLE_MD5=y + +# +# Compiler options +# +CONFIG_OPTIMIZATION_LEVEL_DEBUG=y +CONFIG_OPTIMIZATION_LEVEL_RELEASE= +CONFIG_OPTIMIZATION_ASSERTIONS_ENABLED=y +CONFIG_OPTIMIZATION_ASSERTIONS_SILENT= +CONFIG_OPTIMIZATION_ASSERTIONS_DISABLED= +CONFIG_CXX_EXCEPTIONS= +CONFIG_STACK_CHECK_NONE=y +CONFIG_STACK_CHECK_NORM= +CONFIG_STACK_CHECK_STRONG= +CONFIG_STACK_CHECK_ALL= +CONFIG_STACK_CHECK= +CONFIG_WARN_WRITE_STRINGS= + +# +# Component config +# + +# +# Application Level Tracing +# +CONFIG_ESP32_APPTRACE_DEST_TRAX= +CONFIG_ESP32_APPTRACE_DEST_NONE=y +CONFIG_ESP32_APPTRACE_ENABLE= +CONFIG_ESP32_APPTRACE_LOCK_ENABLE=y + +# +# FreeRTOS SystemView Tracing +# +CONFIG_AWS_IOT_SDK= + +# +# Bluetooth +# +CONFIG_BT_ENABLED= +CONFIG_BTDM_CONTROLLER_PINNED_TO_CORE=0 +CONFIG_BT_RESERVE_DRAM=0 + +# +# ADC configuration +# +CONFIG_ADC_FORCE_XPD_FSM= +CONFIG_ADC2_DISABLE_DAC=y + +# +# ESP32-specific +# +CONFIG_ESP32_DEFAULT_CPU_FREQ_80= +CONFIG_ESP32_DEFAULT_CPU_FREQ_160= +CONFIG_ESP32_DEFAULT_CPU_FREQ_240=y +CONFIG_ESP32_DEFAULT_CPU_FREQ_MHZ=240 +CONFIG_SPIRAM_SUPPORT= +CONFIG_MEMMAP_TRACEMEM= +CONFIG_MEMMAP_TRACEMEM_TWOBANKS= +CONFIG_ESP32_TRAX= +CONFIG_TRACEMEM_RESERVE_DRAM=0x0 +CONFIG_ESP32_ENABLE_COREDUMP_TO_FLASH= +CONFIG_ESP32_ENABLE_COREDUMP_TO_UART= +CONFIG_ESP32_ENABLE_COREDUMP_TO_NONE=y +CONFIG_ESP32_ENABLE_COREDUMP= +CONFIG_TWO_UNIVERSAL_MAC_ADDRESS= +CONFIG_FOUR_UNIVERSAL_MAC_ADDRESS=y +CONFIG_NUMBER_OF_UNIVERSAL_MAC_ADDRESS=4 +CONFIG_SYSTEM_EVENT_QUEUE_SIZE=32 +CONFIG_SYSTEM_EVENT_TASK_STACK_SIZE=2048 +CONFIG_MAIN_TASK_STACK_SIZE=4096 +CONFIG_IPC_TASK_STACK_SIZE=1024 +CONFIG_TIMER_TASK_STACK_SIZE=3584 +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CRLF=y +CONFIG_NEWLIB_STDOUT_LINE_ENDING_LF= +CONFIG_NEWLIB_STDOUT_LINE_ENDING_CR= +CONFIG_NEWLIB_STDIN_LINE_ENDING_CRLF= +CONFIG_NEWLIB_STDIN_LINE_ENDING_LF= +CONFIG_NEWLIB_STDIN_LINE_ENDING_CR=y +CONFIG_NEWLIB_NANO_FORMAT= +CONFIG_CONSOLE_UART_DEFAULT=y +CONFIG_CONSOLE_UART_CUSTOM= +CONFIG_CONSOLE_UART_NONE= +CONFIG_CONSOLE_UART_NUM=0 +CONFIG_CONSOLE_UART_BAUDRATE=115200 +CONFIG_ULP_COPROC_ENABLED= +CONFIG_ULP_COPROC_RESERVE_MEM=0 +CONFIG_ESP32_PANIC_PRINT_HALT= +CONFIG_ESP32_PANIC_PRINT_REBOOT=y +CONFIG_ESP32_PANIC_SILENT_REBOOT= +CONFIG_ESP32_PANIC_GDBSTUB= +CONFIG_ESP32_DEBUG_OCDAWARE=y +CONFIG_INT_WDT=y +CONFIG_INT_WDT_TIMEOUT_MS=300 +CONFIG_TASK_WDT=y +CONFIG_TASK_WDT_PANIC= +CONFIG_TASK_WDT_TIMEOUT_S=5 +CONFIG_TASK_WDT_CHECK_IDLE_TASK_CPU0=y +CONFIG_BROWNOUT_DET=y +CONFIG_BROWNOUT_DET_LVL_SEL_0=y +CONFIG_BROWNOUT_DET_LVL_SEL_1= +CONFIG_BROWNOUT_DET_LVL_SEL_2= +CONFIG_BROWNOUT_DET_LVL_SEL_3= +CONFIG_BROWNOUT_DET_LVL_SEL_4= +CONFIG_BROWNOUT_DET_LVL_SEL_5= +CONFIG_BROWNOUT_DET_LVL_SEL_6= +CONFIG_BROWNOUT_DET_LVL_SEL_7= +CONFIG_BROWNOUT_DET_LVL=0 +CONFIG_ESP32_TIME_SYSCALL_USE_RTC_FRC1=y +CONFIG_ESP32_TIME_SYSCALL_USE_RTC= +CONFIG_ESP32_TIME_SYSCALL_USE_FRC1= +CONFIG_ESP32_TIME_SYSCALL_USE_NONE= +CONFIG_ESP32_RTC_CLOCK_SOURCE_INTERNAL_RC=y +CONFIG_ESP32_RTC_CLOCK_SOURCE_EXTERNAL_CRYSTAL= +CONFIG_ESP32_RTC_CLK_CAL_CYCLES=1024 +CONFIG_ESP32_RTC_XTAL_BOOTSTRAP_CYCLES=100 +CONFIG_ESP32_DEEP_SLEEP_WAKEUP_DELAY=2000 +CONFIG_ESP32_XTAL_FREQ_40=y +CONFIG_ESP32_XTAL_FREQ_26= +CONFIG_ESP32_XTAL_FREQ_AUTO= +CONFIG_ESP32_XTAL_FREQ=40 +CONFIG_DISABLE_BASIC_ROM_CONSOLE= +CONFIG_NO_BLOBS= +CONFIG_ESP_TIMER_PROFILING= +CONFIG_COMPATIBLE_PRE_V2_1_BOOTLOADERS= +CONFIG_ESP_ERR_TO_NAME_LOOKUP=y + +# +# Wi-Fi +# +CONFIG_ESP32_WIFI_STATIC_RX_BUFFER_NUM=10 +CONFIG_ESP32_WIFI_DYNAMIC_RX_BUFFER_NUM=32 +CONFIG_ESP32_WIFI_STATIC_TX_BUFFER= +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER=y +CONFIG_ESP32_WIFI_TX_BUFFER_TYPE=1 +CONFIG_ESP32_WIFI_DYNAMIC_TX_BUFFER_NUM=32 +CONFIG_ESP32_WIFI_AMPDU_TX_ENABLED=y +CONFIG_ESP32_WIFI_TX_BA_WIN=6 +CONFIG_ESP32_WIFI_AMPDU_RX_ENABLED=y +CONFIG_ESP32_WIFI_RX_BA_WIN=6 +CONFIG_ESP32_WIFI_NVS_ENABLED=y + +# +# PHY +# +CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE=y +CONFIG_ESP32_PHY_INIT_DATA_IN_PARTITION= +CONFIG_ESP32_PHY_MAX_WIFI_TX_POWER=20 +CONFIG_ESP32_PHY_MAX_TX_POWER=20 + +# +# Power Management +# +CONFIG_PM_ENABLE= + +# +# ADC-Calibration +# +CONFIG_ADC_CAL_EFUSE_TP_ENABLE=y +CONFIG_ADC_CAL_EFUSE_VREF_ENABLE=y +CONFIG_ADC_CAL_LUT_ENABLE=y + +# +# Ethernet +# +CONFIG_DMA_RX_BUF_NUM=10 +CONFIG_DMA_TX_BUF_NUM=10 +CONFIG_EMAC_L2_TO_L3_RX_BUF_MODE= +CONFIG_EMAC_TASK_PRIORITY=20 + +# +# FAT Filesystem support +# +CONFIG_FATFS_CODEPAGE_DYNAMIC= +CONFIG_FATFS_CODEPAGE_437=y +CONFIG_FATFS_CODEPAGE_720= +CONFIG_FATFS_CODEPAGE_737= +CONFIG_FATFS_CODEPAGE_771= +CONFIG_FATFS_CODEPAGE_775= +CONFIG_FATFS_CODEPAGE_850= +CONFIG_FATFS_CODEPAGE_852= +CONFIG_FATFS_CODEPAGE_855= +CONFIG_FATFS_CODEPAGE_857= +CONFIG_FATFS_CODEPAGE_860= +CONFIG_FATFS_CODEPAGE_861= +CONFIG_FATFS_CODEPAGE_862= +CONFIG_FATFS_CODEPAGE_863= +CONFIG_FATFS_CODEPAGE_864= +CONFIG_FATFS_CODEPAGE_865= +CONFIG_FATFS_CODEPAGE_866= +CONFIG_FATFS_CODEPAGE_869= +CONFIG_FATFS_CODEPAGE_932= +CONFIG_FATFS_CODEPAGE_936= +CONFIG_FATFS_CODEPAGE_949= +CONFIG_FATFS_CODEPAGE_950= +CONFIG_FATFS_CODEPAGE=437 +CONFIG_FATFS_LFN_NONE=y +CONFIG_FATFS_LFN_HEAP= +CONFIG_FATFS_LFN_STACK= +CONFIG_FATFS_FS_LOCK=0 +CONFIG_FATFS_TIMEOUT_MS=10000 +CONFIG_FATFS_PER_FILE_CACHE=y + +# +# FreeRTOS +# +CONFIG_FREERTOS_UNICORE=y +CONFIG_FREERTOS_CORETIMER_0=y +CONFIG_FREERTOS_CORETIMER_1= +CONFIG_FREERTOS_HZ=1000 +CONFIG_FREERTOS_ASSERT_ON_UNTESTED_FUNCTION=y +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_NONE= +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_PTRVAL=y +CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY= +CONFIG_FREERTOS_WATCHPOINT_END_OF_STACK= +CONFIG_FREERTOS_INTERRUPT_BACKTRACE=y +CONFIG_FREERTOS_THREAD_LOCAL_STORAGE_POINTERS=3 +CONFIG_FREERTOS_ASSERT_FAIL_ABORT=y +CONFIG_FREERTOS_ASSERT_FAIL_PRINT_CONTINUE= +CONFIG_FREERTOS_ASSERT_DISABLE= +CONFIG_FREERTOS_IDLE_TASK_STACKSIZE=1024 +CONFIG_FREERTOS_ISR_STACKSIZE=1536 +CONFIG_FREERTOS_LEGACY_HOOKS= +CONFIG_FREERTOS_MAX_TASK_NAME_LEN=16 +CONFIG_SUPPORT_STATIC_ALLOCATION= +CONFIG_TIMER_TASK_PRIORITY=1 +CONFIG_TIMER_TASK_STACK_DEPTH=2048 +CONFIG_TIMER_QUEUE_LENGTH=10 +CONFIG_FREERTOS_QUEUE_REGISTRY_SIZE=0 +CONFIG_FREERTOS_USE_TRACE_FACILITY= +CONFIG_FREERTOS_GENERATE_RUN_TIME_STATS= +CONFIG_FREERTOS_DEBUG_INTERNALS= + +# +# Heap memory debugging +# +CONFIG_HEAP_POISONING_DISABLED=y +CONFIG_HEAP_POISONING_LIGHT= +CONFIG_HEAP_POISONING_COMPREHENSIVE= +CONFIG_HEAP_TRACING= + +# +# libsodium +# +CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y + +# +# Log output +# +CONFIG_LOG_DEFAULT_LEVEL_NONE= +CONFIG_LOG_DEFAULT_LEVEL_ERROR= +CONFIG_LOG_DEFAULT_LEVEL_WARN= +CONFIG_LOG_DEFAULT_LEVEL_INFO=y +CONFIG_LOG_DEFAULT_LEVEL_DEBUG= +CONFIG_LOG_DEFAULT_LEVEL_VERBOSE= +CONFIG_LOG_DEFAULT_LEVEL=3 +CONFIG_LOG_COLORS=y + +# +# LWIP +# +CONFIG_L2_TO_L3_COPY= +CONFIG_LWIP_IRAM_OPTIMIZATION= +CONFIG_LWIP_MAX_SOCKETS=4 +CONFIG_LWIP_SO_REUSE= +CONFIG_LWIP_SO_RCVBUF= +CONFIG_LWIP_DHCP_MAX_NTP_SERVERS=1 +CONFIG_LWIP_IP_FRAG= +CONFIG_LWIP_IP_REASSEMBLY= +CONFIG_LWIP_STATS= +CONFIG_LWIP_ETHARP_TRUST_IP_MAC=y +CONFIG_TCPIP_RECVMBOX_SIZE=32 +CONFIG_LWIP_DHCP_DOES_ARP_CHECK=y + +# +# DHCP server +# +CONFIG_LWIP_DHCPS_LEASE_UNIT=60 +CONFIG_LWIP_DHCPS_MAX_STATION_NUM=8 +CONFIG_LWIP_AUTOIP= +CONFIG_LWIP_NETIF_LOOPBACK=y +CONFIG_LWIP_LOOPBACK_MAX_PBUFS=8 + +# +# TCP +# +CONFIG_LWIP_MAX_ACTIVE_TCP=16 +CONFIG_LWIP_MAX_LISTENING_TCP=16 +CONFIG_TCP_MAXRTX=12 +CONFIG_TCP_SYNMAXRTX=6 +CONFIG_TCP_MSS=1436 +CONFIG_TCP_MSL=60000 +CONFIG_TCP_SND_BUF_DEFAULT=5744 +CONFIG_TCP_WND_DEFAULT=5744 +CONFIG_TCP_RECVMBOX_SIZE=6 +CONFIG_TCP_QUEUE_OOSEQ=y +CONFIG_TCP_OVERSIZE_MSS=y +CONFIG_TCP_OVERSIZE_QUARTER_MSS= +CONFIG_TCP_OVERSIZE_DISABLE= + +# +# UDP +# +CONFIG_LWIP_MAX_UDP_PCBS=16 +CONFIG_UDP_RECVMBOX_SIZE=6 +CONFIG_TCPIP_TASK_STACK_SIZE=2048 +CONFIG_PPP_SUPPORT= + +# +# ICMP +# +CONFIG_LWIP_MULTICAST_PING= +CONFIG_LWIP_BROADCAST_PING= + +# +# LWIP RAW API +# +CONFIG_LWIP_MAX_RAW_PCBS=16 + +# +# mbedTLS +# +CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=16384 +CONFIG_MBEDTLS_DEBUG= +CONFIG_MBEDTLS_HARDWARE_AES=y +CONFIG_MBEDTLS_HARDWARE_MPI=y +CONFIG_MBEDTLS_MPI_USE_INTERRUPT=y +CONFIG_MBEDTLS_HARDWARE_SHA= +CONFIG_MBEDTLS_HAVE_TIME=y +CONFIG_MBEDTLS_HAVE_TIME_DATE= +CONFIG_MBEDTLS_TLS_SERVER_AND_CLIENT=y +CONFIG_MBEDTLS_TLS_SERVER_ONLY= +CONFIG_MBEDTLS_TLS_CLIENT_ONLY= +CONFIG_MBEDTLS_TLS_DISABLED= +CONFIG_MBEDTLS_TLS_SERVER=y +CONFIG_MBEDTLS_TLS_CLIENT=y +CONFIG_MBEDTLS_TLS_ENABLED=y + +# +# TLS Key Exchange Methods +# +CONFIG_MBEDTLS_PSK_MODES= +CONFIG_MBEDTLS_KEY_EXCHANGE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_DHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ELLIPTIC_CURVE=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_RSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA=y +CONFIG_MBEDTLS_KEY_EXCHANGE_ECDH_RSA=y +CONFIG_MBEDTLS_SSL_RENEGOTIATION=y +CONFIG_MBEDTLS_SSL_PROTO_SSL3= +CONFIG_MBEDTLS_SSL_PROTO_TLS1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_1=y +CONFIG_MBEDTLS_SSL_PROTO_TLS1_2=y +CONFIG_MBEDTLS_SSL_PROTO_DTLS= +CONFIG_MBEDTLS_SSL_ALPN=y +CONFIG_MBEDTLS_SSL_SESSION_TICKETS=y + +# +# Symmetric Ciphers +# +CONFIG_MBEDTLS_AES_C=y +CONFIG_MBEDTLS_CAMELLIA_C= +CONFIG_MBEDTLS_DES_C= +CONFIG_MBEDTLS_RC4_DISABLED=y +CONFIG_MBEDTLS_RC4_ENABLED_NO_DEFAULT= +CONFIG_MBEDTLS_RC4_ENABLED= +CONFIG_MBEDTLS_BLOWFISH_C= +CONFIG_MBEDTLS_XTEA_C= +CONFIG_MBEDTLS_CCM_C=y +CONFIG_MBEDTLS_GCM_C=y +CONFIG_MBEDTLS_RIPEMD160_C= + +# +# Certificates +# +CONFIG_MBEDTLS_PEM_PARSE_C=y +CONFIG_MBEDTLS_PEM_WRITE_C=y +CONFIG_MBEDTLS_X509_CRL_PARSE_C=y +CONFIG_MBEDTLS_X509_CSR_PARSE_C=y +CONFIG_MBEDTLS_ECP_C=y +CONFIG_MBEDTLS_ECDH_C=y +CONFIG_MBEDTLS_ECDSA_C=y +CONFIG_MBEDTLS_ECP_DP_SECP192R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP521R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP192K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP224K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_SECP256K1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP256R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP384R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_BP512R1_ENABLED=y +CONFIG_MBEDTLS_ECP_DP_CURVE25519_ENABLED=y +CONFIG_MBEDTLS_ECP_NIST_OPTIM=y + +# +# OpenSSL +# +CONFIG_OPENSSL_DEBUG= +CONFIG_OPENSSL_ASSERT_DO_NOTHING=y +CONFIG_OPENSSL_ASSERT_EXIT= + +# +# PThreads +# +CONFIG_ESP32_PTHREAD_TASK_PRIO_DEFAULT=5 +CONFIG_ESP32_PTHREAD_TASK_STACK_SIZE_DEFAULT=3072 + +# +# SPI Flash driver +# +CONFIG_SPI_FLASH_VERIFY_WRITE= +CONFIG_SPI_FLASH_ENABLE_COUNTERS= +CONFIG_SPI_FLASH_ROM_DRIVER_PATCH=y +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ABORTS=y +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_FAILS= +CONFIG_SPI_FLASH_WRITING_DANGEROUS_REGIONS_ALLOWED= + +# +# SPIFFS Configuration +# +CONFIG_SPIFFS_MAX_PARTITIONS=3 + +# +# SPIFFS Cache Configuration +# +CONFIG_SPIFFS_CACHE=y +CONFIG_SPIFFS_CACHE_WR=y +CONFIG_SPIFFS_CACHE_STATS= +CONFIG_SPIFFS_PAGE_CHECK=y +CONFIG_SPIFFS_GC_MAX_RUNS=10 +CONFIG_SPIFFS_GC_STATS= +CONFIG_SPIFFS_PAGE_SIZE=256 +CONFIG_SPIFFS_OBJ_NAME_LEN=32 +CONFIG_SPIFFS_USE_MAGIC=y +CONFIG_SPIFFS_USE_MAGIC_LENGTH=y +CONFIG_SPIFFS_META_LENGTH=4 +CONFIG_SPIFFS_USE_MTIME=y + +# +# Debug Configuration +# +CONFIG_SPIFFS_DBG= +CONFIG_SPIFFS_API_DBG= +CONFIG_SPIFFS_GC_DBG= +CONFIG_SPIFFS_CACHE_DBG= +CONFIG_SPIFFS_CHECK_DBG= +CONFIG_SPIFFS_TEST_VISUALISATION= + +# +# tcpip adapter +# +CONFIG_IP_LOST_TIMER_INTERVAL=120 + +# +# Wear Levelling +# +CONFIG_WL_SECTOR_SIZE_512= +CONFIG_WL_SECTOR_SIZE_4096=y +CONFIG_WL_SECTOR_SIZE=4096 diff --git a/tools/ldgen/samples/sections.info b/tools/ldgen/samples/sections.info new file mode 100644 index 0000000000..db450cfbae --- /dev/null +++ b/tools/ldgen/samples/sections.info @@ -0,0 +1,1626 @@ +In archive libfreertos.a: + +FreeRTOS-openocd.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 00000000 00000000 00000000 00000034 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .data 00000000 00000000 00000000 00000034 2**0 + CONTENTS, ALLOC, LOAD, DATA + 2 .bss 00000000 00000000 00000000 00000034 2**0 + ALLOC + 3 .dram1 00000004 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 4 .debug_info 0000008f 00000000 00000000 00000038 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 5 .debug_abbrev 0000003e 00000000 00000000 000000c7 2**0 + CONTENTS, READONLY, DEBUGGING + 6 .debug_aranges 00000018 00000000 00000000 00000105 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 7 .debug_line 0000005e 00000000 00000000 0000011d 2**0 + CONTENTS, READONLY, DEBUGGING + 8 .debug_str 0000018d 00000000 00000000 0000017b 2**0 + CONTENTS, READONLY, DEBUGGING + 9 .comment 0000003b 00000000 00000000 00000308 2**0 + CONTENTS, READONLY + 10 .xtensa.info 00000038 00000000 00000000 00000343 2**0 + CONTENTS, READONLY + 11 .xt.prop 0000000c 00000000 00000000 0000037b 2**0 + CONTENTS, RELOC, READONLY + +croutine.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.prvCheckPendingReadyList 00000018 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.prvCheckDelayedList 0000002c 00000000 00000000 0000004c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.xCoRoutineCreate 0000001c 00000000 00000000 00000078 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .literal.vCoRoutineAddToDelayedList 00000020 00000000 00000000 00000094 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 4 .literal.vCoRoutineSchedule 00000014 00000000 00000000 000000b4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .literal.xCoRoutineRemoveFromEventList 00000010 00000000 00000000 000000c8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .text 00000000 00000000 00000000 000000d8 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 7 .data 00000000 00000000 00000000 000000d8 2**0 + CONTENTS, ALLOC, LOAD, DATA + 8 .bss 00000000 00000000 00000000 000000d8 2**0 + ALLOC + 9 .text.prvCheckPendingReadyList 00000056 00000000 00000000 000000d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 10 .text.prvCheckDelayedList 000000ac 00000000 00000000 00000130 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 11 .rodata.str1.4 00000074 00000000 00000000 000001dc 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 12 .text.xCoRoutineCreate 00000028 00000000 00000000 00000250 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 13 .text.vCoRoutineAddToDelayedList 00000056 00000000 00000000 00000278 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 14 .text.vCoRoutineSchedule 0000007a 00000000 00000000 000002d0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 15 .text.xCoRoutineRemoveFromEventList 00000031 00000000 00000000 0000034c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 16 .rodata.__FUNCTION__$5025 00000011 00000000 00000000 00000380 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 17 .bss.xPassedTicks 00000004 00000000 00000000 00000394 2**2 + ALLOC + 18 .bss.xLastTickCount 00000004 00000000 00000000 00000394 2**2 + ALLOC + 19 .bss.xCoRoutineTickCount 00000004 00000000 00000000 00000394 2**2 + ALLOC + 20 .bss.uxTopCoRoutineReadyPriority 00000004 00000000 00000000 00000394 2**2 + ALLOC + 21 .bss.pxCurrentCoRoutine 00000004 00000000 00000000 00000394 2**2 + ALLOC + 22 .bss.xPendingReadyCoRoutineList 00000014 00000000 00000000 00000394 2**2 + ALLOC + 23 .bss.pxOverflowDelayedCoRoutineList 00000004 00000000 00000000 00000394 2**2 + ALLOC + 24 .bss.pxDelayedCoRoutineList 00000004 00000000 00000000 00000394 2**2 + ALLOC + 25 .bss.pxReadyCoRoutineLists 00000028 00000000 00000000 00000394 2**2 + ALLOC + 26 .debug_frame 000000a0 00000000 00000000 00000394 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 27 .debug_info 000006b8 00000000 00000000 00000434 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 28 .debug_abbrev 00000233 00000000 00000000 00000aec 2**0 + CONTENTS, READONLY, DEBUGGING + 29 .debug_loc 0000013b 00000000 00000000 00000d1f 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 30 .debug_aranges 00000048 00000000 00000000 00000e5a 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 31 .debug_ranges 00000038 00000000 00000000 00000ea2 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 32 .debug_line 0000037e 00000000 00000000 00000eda 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 33 .debug_str 00000533 00000000 00000000 00001258 2**0 + CONTENTS, READONLY, DEBUGGING + 34 .comment 0000003b 00000000 00000000 0000178b 2**0 + CONTENTS, READONLY + 35 .xtensa.info 00000038 00000000 00000000 000017c6 2**0 + CONTENTS, READONLY + 36 .xt.lit 00000030 00000000 00000000 000017fe 2**0 + CONTENTS, RELOC, READONLY + 37 .xt.prop 00000270 00000000 00000000 0000182e 2**0 + CONTENTS, RELOC, READONLY + +event_groups.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.xEventGroupCreate 0000000c 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.xEventGroupWaitBits 0000006c 00000000 00000000 00000040 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.xEventGroupClearBits 00000028 00000000 00000000 000000ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .literal.xEventGroupGetBitsFromISR 00000004 00000000 00000000 000000d4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 4 .literal.xEventGroupSetBits 0000003c 00000000 00000000 000000d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .literal.xEventGroupSync 0000005c 00000000 00000000 00000114 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .literal.vEventGroupDelete 00000030 00000000 00000000 00000170 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .literal.vEventGroupSetBitsCallback 00000004 00000000 00000000 000001a0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .literal.vEventGroupClearBitsCallback 00000004 00000000 00000000 000001a4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 9 .text 00000000 00000000 00000000 000001a8 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 10 .data 00000000 00000000 00000000 000001a8 2**0 + CONTENTS, ALLOC, LOAD, DATA + 11 .bss 00000000 00000000 00000000 000001a8 2**0 + ALLOC + 12 .text.prvTestWaitCondition 0000001e 00000000 00000000 000001a8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 13 .text.xEventGroupCreate 00000027 00000000 00000000 000001c8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 14 .rodata.str1.4 00000058 00000000 00000000 000001f0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 15 .text.xEventGroupWaitBits 00000140 00000000 00000000 00000248 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 16 .text.xEventGroupClearBits 00000060 00000000 00000000 00000388 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 17 .text.xEventGroupGetBitsFromISR 00000010 00000000 00000000 000003e8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 18 .text.xEventGroupSetBits 000000c3 00000000 00000000 000003f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 19 .text.xEventGroupSync 00000108 00000000 00000000 000004bc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 20 .text.vEventGroupDelete 0000005d 00000000 00000000 000005c4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 21 .text.vEventGroupSetBitsCallback 0000000f 00000000 00000000 00000624 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 22 .text.vEventGroupClearBitsCallback 0000000f 00000000 00000000 00000634 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 23 .rodata.__FUNCTION__$5129 00000012 00000000 00000000 00000644 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 24 .rodata.__FUNCTION__$5120 00000013 00000000 00000000 00000658 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 25 .rodata.__FUNCTION__$5100 00000015 00000000 00000000 0000066c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 26 .rodata.__FUNCTION__$5092 00000014 00000000 00000000 00000684 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 27 .rodata.__FUNCTION__$5078 00000010 00000000 00000000 00000698 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 28 .debug_frame 00000100 00000000 00000000 000006a8 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 29 .debug_info 00000e02 00000000 00000000 000007a8 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 30 .debug_abbrev 00000236 00000000 00000000 000015aa 2**0 + CONTENTS, READONLY, DEBUGGING + 31 .debug_loc 00000546 00000000 00000000 000017e0 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 32 .debug_aranges 00000068 00000000 00000000 00001d26 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 33 .debug_ranges 00000070 00000000 00000000 00001d8e 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 34 .debug_line 000006af 00000000 00000000 00001dfe 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 35 .debug_str 00000677 00000000 00000000 000024ad 2**0 + CONTENTS, READONLY, DEBUGGING + 36 .comment 0000003b 00000000 00000000 00002b24 2**0 + CONTENTS, READONLY + 37 .xtensa.info 00000038 00000000 00000000 00002b5f 2**0 + CONTENTS, READONLY + 38 .xt.lit 00000048 00000000 00000000 00002b97 2**0 + CONTENTS, RELOC, READONLY + 39 .xt.prop 00000468 00000000 00000000 00002bdf 2**0 + CONTENTS, RELOC, READONLY + +list.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 00000000 00000000 00000000 00000034 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .data 00000000 00000000 00000000 00000034 2**0 + CONTENTS, ALLOC, LOAD, DATA + 2 .bss 00000000 00000000 00000000 00000034 2**0 + ALLOC + 3 .text.vListInitialise 00000015 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 4 .text.vListInitialiseItem 00000009 00000000 00000000 0000004c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 5 .text.vListInsertEnd 0000001b 00000000 00000000 00000058 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 6 .text.vListInsert 0000002f 00000000 00000000 00000074 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .text.uxListRemove 00000026 00000000 00000000 000000a4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .debug_frame 00000088 00000000 00000000 000000cc 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 9 .debug_info 000002a1 00000000 00000000 00000154 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 10 .debug_abbrev 000000dc 00000000 00000000 000003f5 2**0 + CONTENTS, READONLY, DEBUGGING + 11 .debug_loc 00000081 00000000 00000000 000004d1 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 12 .debug_aranges 00000040 00000000 00000000 00000552 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 13 .debug_ranges 00000030 00000000 00000000 00000592 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 14 .debug_line 0000024c 00000000 00000000 000005c2 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 15 .debug_str 000002c2 00000000 00000000 0000080e 2**0 + CONTENTS, READONLY, DEBUGGING + 16 .comment 0000003b 00000000 00000000 00000ad0 2**0 + CONTENTS, READONLY + 17 .xtensa.info 00000038 00000000 00000000 00000b0b 2**0 + CONTENTS, READONLY + 18 .xt.prop 000000f0 00000000 00000000 00000b43 2**0 + CONTENTS, RELOC, READONLY + +port.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.pxPortInitialiseStack 00000018 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.xPortStartScheduler 00000014 00000000 00000000 0000004c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.xPortSysTickHandler 00000008 00000000 00000000 00000060 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .literal.vPortYieldOtherCore 00000004 00000000 00000000 00000068 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 4 .literal.vPortReleaseTaskMPUSettings 00000004 00000000 00000000 0000006c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .literal.xPortInIsrContext 00000008 00000000 00000000 00000070 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .iram1.literal 00000004 00000000 00000000 00000078 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .literal.vPortAssertIfInISR 00000018 00000000 00000000 0000007c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .literal.vPortCPUInitializeMutex 00000004 00000000 00000000 00000094 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 9 .literal.vPortCPUAcquireMutex 00000030 00000000 00000000 00000098 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 10 .literal.vPortCPUAcquireMutexTimeout 00000030 00000000 00000000 000000c8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 11 .literal.vPortCPUReleaseMutex 00000028 00000000 00000000 000000f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 12 .literal.vPortSetStackWatchpoint 00000008 00000000 00000000 00000120 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 13 .text 00000000 00000000 00000000 00000128 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 14 .data 00000000 00000000 00000000 00000128 2**0 + CONTENTS, ALLOC, LOAD, DATA + 15 .bss 00000000 00000000 00000000 00000128 2**0 + ALLOC + 16 .text.pxPortInitialiseStack 00000086 00000000 00000000 00000128 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 17 .text.vPortEndScheduler 00000005 00000000 00000000 000001b0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 18 .text.xPortStartScheduler 0000002e 00000000 00000000 000001b8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 19 .text.xPortSysTickHandler 00000016 00000000 00000000 000001e8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 20 .text.vPortYieldOtherCore 0000000e 00000000 00000000 00000200 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 21 .text.vPortStoreTaskMPUSettings 00000013 00000000 00000000 00000210 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 22 .text.vPortReleaseTaskMPUSettings 0000000e 00000000 00000000 00000224 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 23 .text.xPortInIsrContext 00000026 00000000 00000000 00000234 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 24 .iram1 0000001a 00000000 00000000 0000025c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 25 .rodata.str1.4 0000013b 00000000 00000000 00000278 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 26 .text.vPortAssertIfInISR 00000025 00000000 00000000 000003b4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 27 .text.vPortCPUInitializeMutex 0000000e 00000000 00000000 000003dc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 28 .text.vPortCPUAcquireMutex 00000088 00000000 00000000 000003ec 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 29 .text.vPortCPUAcquireMutexTimeout 000000ab 00000000 00000000 00000474 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 30 .text.vPortCPUReleaseMutex 00000061 00000000 00000000 00000520 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 31 .text.vPortSetStackWatchpoint 0000001a 00000000 00000000 00000584 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 32 .text.xPortGetTickRateHz 00000008 00000000 00000000 000005a0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 33 .rodata.__func__$5264 00000029 00000000 00000000 000005a8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 34 .rodata.__func__$5259 00000029 00000000 00000000 000005d4 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 35 .rodata.__FUNCTION__$5243 00000013 00000000 00000000 00000600 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 36 .bss.port_interruptNesting 00000008 00000000 00000000 00000614 2**2 + ALLOC + 37 .bss.port_xSchedulerRunning 00000008 00000000 00000000 00000614 2**2 + ALLOC + 38 .debug_frame 00000190 00000000 00000000 00000614 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 39 .debug_info 00000e78 00000000 00000000 000007a4 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 40 .debug_abbrev 00000404 00000000 00000000 0000161c 2**0 + CONTENTS, READONLY, DEBUGGING + 41 .debug_loc 000005f1 00000000 00000000 00001a20 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 42 .debug_aranges 00000098 00000000 00000000 00002011 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 43 .debug_ranges 000000a0 00000000 00000000 000020a9 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 44 .debug_line 000005fb 00000000 00000000 00002149 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 45 .debug_str 0000071f 00000000 00000000 00002744 2**0 + CONTENTS, READONLY, DEBUGGING + 46 .comment 0000003b 00000000 00000000 00002e63 2**0 + CONTENTS, READONLY + 47 .xtensa.info 00000038 00000000 00000000 00002e9e 2**0 + CONTENTS, READONLY + 48 .xt.lit 00000068 00000000 00000000 00002ed6 2**0 + CONTENTS, RELOC, READONLY + 49 .xt.prop 00000408 00000000 00000000 00002f3e 2**0 + CONTENTS, RELOC, READONLY + +portasm.S.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal 00000074 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .text 000001e0 00000000 00000000 000000a8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .data 00000c0c 00000000 00000000 00000290 2**4 + CONTENTS, ALLOC, LOAD, DATA + 3 .bss 00000000 00000000 00000000 00000e9c 2**0 + ALLOC + 4 .xtensa.info 00000038 00000000 00000000 00000e9c 2**0 + CONTENTS, READONLY + 5 .debug_line 00000432 00000000 00000000 00000ed4 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 6 .debug_info 00000093 00000000 00000000 00001306 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 7 .debug_abbrev 00000014 00000000 00000000 00001399 2**0 + CONTENTS, READONLY, DEBUGGING + 8 .debug_aranges 00000020 00000000 00000000 000013b0 2**3 + CONTENTS, RELOC, READONLY, DEBUGGING + 9 .xt.lit 00000008 00000000 00000000 000013d0 2**0 + CONTENTS, RELOC, READONLY + 10 .xt.prop 00000168 00000000 00000000 000013d8 2**0 + CONTENTS, RELOC, READONLY + +queue.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.prvIsQueueFull 00000008 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.prvCopyDataToQueue 0000000c 00000000 00000000 0000003c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.prvNotifyQueueSetContainer 0000002c 00000000 00000000 00000048 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .literal.prvCopyDataFromQueue 00000004 00000000 00000000 00000074 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 4 .literal.xQueueGenericReset 00000030 00000000 00000000 00000078 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .literal.prvInitialiseNewQueue 00000004 00000000 00000000 000000a8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .literal.xQueueGenericCreate 0000001c 00000000 00000000 000000ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .literal.xQueueGetMutexHolder 00000008 00000000 00000000 000000c8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .literal.xQueueCreateCountingSemaphore 00000028 00000000 00000000 000000d0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 9 .literal.xQueueGenericSend 0000007c 00000000 00000000 000000f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 10 .literal.prvInitialiseMutex 00000008 00000000 00000000 00000174 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 11 .literal.xQueueCreateMutex 00000008 00000000 00000000 0000017c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 12 .literal.xQueueGiveMutexRecursive 0000001c 00000000 00000000 00000184 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 13 .literal.xQueueGenericSendFromISR 0000003c 00000000 00000000 000001a0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 14 .literal.xQueueGiveFromISR 00000030 00000000 00000000 000001dc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 15 .literal.xQueueGenericReceive 00000078 00000000 00000000 0000020c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 16 .literal.xQueueTakeMutexRecursive 0000001c 00000000 00000000 00000284 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 17 .literal.xQueueReceiveFromISR 00000030 00000000 00000000 000002a0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 18 .literal.xQueuePeekFromISR 00000034 00000000 00000000 000002d0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 19 .literal.uxQueueMessagesWaiting 0000001c 00000000 00000000 00000304 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 20 .literal.uxQueueSpacesAvailable 0000001c 00000000 00000000 00000320 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 21 .literal.uxQueueMessagesWaitingFromISR 0000001c 00000000 00000000 0000033c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 22 .literal.vQueueDelete 00000018 00000000 00000000 00000358 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 23 .literal.xQueueIsQueueEmptyFromISR 0000001c 00000000 00000000 00000370 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 24 .literal.xQueueIsQueueFullFromISR 0000001c 00000000 00000000 0000038c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 25 .literal.vQueueWaitForMessageRestricted 0000000c 00000000 00000000 000003a8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 26 .literal.xQueueCreateSet 00000004 00000000 00000000 000003b4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 27 .literal.xQueueSelectFromSet 00000004 00000000 00000000 000003b8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 28 .literal.xQueueSelectFromSetFromISR 00000004 00000000 00000000 000003bc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 29 .text 00000000 00000000 00000000 000003c0 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 30 .data 00000000 00000000 00000000 000003c0 2**0 + CONTENTS, ALLOC, LOAD, DATA + 31 .bss 00000000 00000000 00000000 000003c0 2**0 + ALLOC + 32 .text.prvIsQueueEmpty 00000012 00000000 00000000 000003c0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 33 .text.prvIsQueueFull 0000002a 00000000 00000000 000003d4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 34 .text.prvCopyDataToQueue 0000009e 00000000 00000000 00000400 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 35 .rodata.str1.4 00000050 00000000 00000000 000004a0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 36 .text.prvNotifyQueueSetContainer 00000076 00000000 00000000 000004f0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 37 .text.prvCopyDataFromQueue 00000024 00000000 00000000 00000568 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 38 .text.xQueueGenericReset 00000096 00000000 00000000 0000058c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 39 .text.prvInitialiseNewQueue 00000023 00000000 00000000 00000624 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 40 .text.xQueueGenericCreate 0000004d 00000000 00000000 00000648 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 41 .text.xQueueGetMutexHolder 00000023 00000000 00000000 00000698 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 42 .text.xQueueCreateCountingSemaphore 0000006a 00000000 00000000 000006bc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 43 .text.xQueueGenericSend 0000018c 00000000 00000000 00000728 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 44 .text.prvInitialiseMutex 00000026 00000000 00000000 000008b4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 45 .text.xQueueCreateMutex 0000001a 00000000 00000000 000008dc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 46 .text.xQueueGiveMutexRecursive 0000004c 00000000 00000000 000008f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 47 .text.xQueueGenericSendFromISR 000000e6 00000000 00000000 00000944 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 48 .text.xQueueGiveFromISR 000000c2 00000000 00000000 00000a2c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 49 .text.xQueueGenericReceive 00000178 00000000 00000000 00000af0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 50 .text.xQueueTakeMutexRecursive 00000051 00000000 00000000 00000c68 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 51 .text.xQueueReceiveFromISR 000000a6 00000000 00000000 00000cbc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 52 .text.xQueuePeekFromISR 00000098 00000000 00000000 00000d64 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 53 .text.uxQueueMessagesWaiting 00000038 00000000 00000000 00000dfc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 54 .text.uxQueueSpacesAvailable 0000003e 00000000 00000000 00000e34 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 55 .text.uxQueueMessagesWaitingFromISR 00000038 00000000 00000000 00000e74 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 56 .text.vQueueDelete 00000028 00000000 00000000 00000eac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 57 .text.xQueueIsQueueEmptyFromISR 00000042 00000000 00000000 00000ed4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 58 .text.xQueueIsQueueFullFromISR 00000044 00000000 00000000 00000f18 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 59 .text.vQueueWaitForMessageRestricted 0000002a 00000000 00000000 00000f5c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 60 .text.xQueueCreateSet 00000014 00000000 00000000 00000f88 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 61 .text.xQueueAddToSet 0000001e 00000000 00000000 00000f9c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 62 .text.xQueueRemoveFromSet 00000020 00000000 00000000 00000fbc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 63 .text.xQueueSelectFromSet 00000018 00000000 00000000 00000fdc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 64 .text.xQueueSelectFromSetFromISR 00000015 00000000 00000000 00000ff4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 65 .rodata.__FUNCTION__$5459 00000019 00000000 00000000 0000100c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 66 .rodata.__FUNCTION__$5449 0000001a 00000000 00000000 00001028 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 67 .rodata.__FUNCTION__$5429 0000000d 00000000 00000000 00001044 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 68 .rodata.__FUNCTION__$5424 0000001e 00000000 00000000 00001054 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 69 .rodata.__FUNCTION__$5418 00000017 00000000 00000000 00001074 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 70 .rodata.__FUNCTION__$5412 00000017 00000000 00000000 0000108c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 71 .rodata.__FUNCTION__$5406 00000012 00000000 00000000 000010a4 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 72 .rodata.__FUNCTION__$5397 00000015 00000000 00000000 000010b8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 73 .rodata.__FUNCTION__$5387 00000015 00000000 00000000 000010d0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 74 .rodata.__FUNCTION__$5376 00000012 00000000 00000000 000010e8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 75 .rodata.__FUNCTION__$5368 00000019 00000000 00000000 000010fc 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 76 .rodata.__FUNCTION__$5495 0000001b 00000000 00000000 00001118 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 77 .rodata.__FUNCTION__$5357 00000012 00000000 00000000 00001134 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 78 .rodata.__FUNCTION__$5346 0000001e 00000000 00000000 00001148 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 79 .rodata.__FUNCTION__$5340 00000019 00000000 00000000 00001168 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 80 .rodata.__FUNCTION__$5333 00000019 00000000 00000000 00001184 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 81 .rodata.__FUNCTION__$5306 00000014 00000000 00000000 000011a0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 82 .rodata.__FUNCTION__$5297 00000013 00000000 00000000 000011b4 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 83 .debug_frame 00000310 00000000 00000000 000011c8 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 84 .debug_info 0000226e 00000000 00000000 000014d8 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 85 .debug_abbrev 00000247 00000000 00000000 00003746 2**0 + CONTENTS, READONLY, DEBUGGING + 86 .debug_loc 000010f0 00000000 00000000 0000398d 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 87 .debug_aranges 00000118 00000000 00000000 00004a7d 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 88 .debug_ranges 00000108 00000000 00000000 00004b95 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 89 .debug_line 00000e69 00000000 00000000 00004c9d 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 90 .debug_str 000009f1 00000000 00000000 00005b06 2**0 + CONTENTS, READONLY, DEBUGGING + 91 .comment 0000003b 00000000 00000000 000064f7 2**0 + CONTENTS, READONLY + 92 .xtensa.info 00000038 00000000 00000000 00006532 2**0 + CONTENTS, READONLY + 93 .xt.lit 000000e8 00000000 00000000 0000656a 2**0 + CONTENTS, RELOC, READONLY + 94 .xt.prop 00000e10 00000000 00000000 00006652 2**0 + CONTENTS, RELOC, READONLY + +ringbuf.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.returnItemToRingbufBytebuf 0000001c 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.returnItemToRingbufDefault 00000044 00000000 00000000 00000050 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.getItemFromRingbufDefault 00000024 00000000 00000000 00000094 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .literal.copyItemToRingbufNoSplit 00000024 00000000 00000000 000000b8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 4 .literal.copyItemToRingbufByteBuf 00000008 00000000 00000000 000000dc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .literal.copyItemToRingbufAllowSplit 00000034 00000000 00000000 000000e4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .literal.xRingbufferReceiveGeneric 00000020 00000000 00000000 00000118 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .literal.xRingbufferPrintInfo 00000020 00000000 00000000 00000138 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .literal.xRingbufferGetCurFreeSize 0000001c 00000000 00000000 00000158 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 9 .literal.xRingbufferCreate 00000064 00000000 00000000 00000174 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 10 .literal.xRingbufferCreateNoSplit 00000004 00000000 00000000 000001d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 11 .literal.vRingbufferDelete 00000010 00000000 00000000 000001dc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 12 .literal.xRingbufferGetMaxItemSize 00000014 00000000 00000000 000001ec 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 13 .literal.xRingbufferIsNextItemWrapped 00000014 00000000 00000000 00000200 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 14 .literal.xRingbufferSend 0000003c 00000000 00000000 00000214 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 15 .literal.xRingbufferSendFromISR 00000024 00000000 00000000 00000250 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 16 .literal.xRingbufferReceive 00000004 00000000 00000000 00000274 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 17 .literal.xRingbufferReceiveFromISR 0000001c 00000000 00000000 00000278 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 18 .literal.xRingbufferReceiveUpTo 00000020 00000000 00000000 00000294 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 19 .literal.xRingbufferReceiveUpToFromISR 00000024 00000000 00000000 000002b4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 20 .literal.vRingbufferReturnItem 0000000c 00000000 00000000 000002d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 21 .literal.vRingbufferReturnItemFromISR 0000000c 00000000 00000000 000002e4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 22 .literal.xRingbufferAddToQueueSetRead 00000018 00000000 00000000 000002f0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 23 .literal.xRingbufferAddToQueueSetWrite 00000018 00000000 00000000 00000308 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 24 .literal.xRingbufferRemoveFromQueueSetRead 00000018 00000000 00000000 00000320 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 25 .literal.xRingbufferRemoveFromQueueSetWrite 00000018 00000000 00000000 00000338 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 26 .text 00000000 00000000 00000000 00000350 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 27 .data 00000000 00000000 00000000 00000350 2**0 + CONTENTS, ALLOC, LOAD, DATA + 28 .bss 00000000 00000000 00000000 00000350 2**0 + ALLOC + 29 .text.ringbufferFreeMem 00000015 00000000 00000000 00000350 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 30 .text.getItemFromRingbufByteBuf 00000056 00000000 00000000 00000368 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 31 .text.getCurFreeSizeByteBuf 00000015 00000000 00000000 000003c0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 32 .text.getCurFreeSizeAllowSplit 00000030 00000000 00000000 000003d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 33 .text.getCurFreeSizeNoSplit 00000024 00000000 00000000 00000408 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 34 .rodata.str1.4 00000083 00000000 00000000 0000042c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 35 .text.returnItemToRingbufBytebuf 00000045 00000000 00000000 000004b0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 36 .text.returnItemToRingbufDefault 00000136 00000000 00000000 000004f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 37 .text.getItemFromRingbufDefault 000000a5 00000000 00000000 00000630 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 38 .text.copyItemToRingbufNoSplit 000000b0 00000000 00000000 000006d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 39 .text.copyItemToRingbufByteBuf 00000046 00000000 00000000 00000788 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 40 .text.copyItemToRingbufAllowSplit 00000124 00000000 00000000 000007d0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 41 .text.xRingbufferReceiveGeneric 00000070 00000000 00000000 000008f4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 42 .text.xRingbufferPrintInfo 00000046 00000000 00000000 00000964 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 43 .text.xRingbufferGetCurFreeSize 00000043 00000000 00000000 000009ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 44 .text.xRingbufferCreate 00000118 00000000 00000000 000009f0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 45 .text.xRingbufferCreateNoSplit 0000001c 00000000 00000000 00000b08 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 46 .text.vRingbufferDelete 0000002c 00000000 00000000 00000b24 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 47 .text.xRingbufferGetMaxItemSize 00000022 00000000 00000000 00000b50 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 48 .text.xRingbufferIsNextItemWrapped 00000030 00000000 00000000 00000b74 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 49 .text.xRingbufferSend 000000d4 00000000 00000000 00000ba4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 50 .text.xRingbufferSendFromISR 00000062 00000000 00000000 00000c78 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 51 .text.xRingbufferReceive 00000015 00000000 00000000 00000cdc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 52 .text.xRingbufferReceiveFromISR 00000040 00000000 00000000 00000cf4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 53 .text.xRingbufferReceiveUpTo 00000054 00000000 00000000 00000d34 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 54 .text.xRingbufferReceiveUpToFromISR 00000064 00000000 00000000 00000d88 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 55 .text.vRingbufferReturnItem 00000030 00000000 00000000 00000dec 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 56 .text.vRingbufferReturnItemFromISR 0000002c 00000000 00000000 00000e1c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 57 .text.xRingbufferAddToQueueSetRead 0000002c 00000000 00000000 00000e48 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 58 .text.xRingbufferAddToQueueSetWrite 0000002c 00000000 00000000 00000e74 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 59 .text.xRingbufferRemoveFromQueueSetRead 0000002c 00000000 00000000 00000ea0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 60 .text.xRingbufferRemoveFromQueueSetWrite 0000002c 00000000 00000000 00000ecc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 61 .rodata.__FUNCTION__$5577 00000023 00000000 00000000 00000ef8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 62 .rodata.__FUNCTION__$5571 00000022 00000000 00000000 00000f1c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 63 .rodata.__FUNCTION__$5565 0000001e 00000000 00000000 00000f40 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 64 .rodata.__FUNCTION__$5559 0000001d 00000000 00000000 00000f60 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 65 .rodata.__FUNCTION__$5542 0000001e 00000000 00000000 00000f80 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 66 .rodata.__FUNCTION__$5534 00000017 00000000 00000000 00000fa0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 67 .rodata.__FUNCTION__$5527 0000001a 00000000 00000000 00000fb8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 68 .rodata.__FUNCTION__$5508 0000001a 00000000 00000000 00000fd4 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 69 .rodata.__FUNCTION__$5497 00000017 00000000 00000000 00000ff0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 70 .rodata.__FUNCTION__$5482 00000010 00000000 00000000 00001008 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 71 .rodata.__FUNCTION__$5469 0000001d 00000000 00000000 00001018 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 72 .rodata.__FUNCTION__$5464 0000001a 00000000 00000000 00001038 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 73 .rodata.__FUNCTION__$5379 0000001c 00000000 00000000 00001054 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 74 .rodata.__FUNCTION__$5395 0000001a 00000000 00000000 00001070 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 75 .rodata.__FUNCTION__$5408 0000001b 00000000 00000000 0000108c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 76 .rodata.__FUNCTION__$5418 0000001b 00000000 00000000 000010a8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 77 .rodata.__FUNCTION__$5369 00000019 00000000 00000000 000010c4 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 78 .rodata.__FUNCTION__$5450 00000012 00000000 00000000 000010e0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 79 .rodata.__FUNCTION__$5428 0000001a 00000000 00000000 000010f4 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 80 .rodata.__FUNCTION__$5423 00000015 00000000 00000000 00001110 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 81 .debug_frame 000002f8 00000000 00000000 00001128 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 82 .debug_info 00001dc4 00000000 00000000 00001420 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 83 .debug_abbrev 000002c9 00000000 00000000 000031e4 2**0 + CONTENTS, READONLY, DEBUGGING + 84 .debug_loc 00000df4 00000000 00000000 000034ad 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 85 .debug_aranges 00000110 00000000 00000000 000042a1 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 86 .debug_ranges 00000130 00000000 00000000 000043b1 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 87 .debug_line 00000ce4 00000000 00000000 000044e1 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 88 .debug_str 000008b1 00000000 00000000 000051c5 2**0 + CONTENTS, READONLY, DEBUGGING + 89 .comment 0000003b 00000000 00000000 00005a76 2**0 + CONTENTS, READONLY + 90 .xtensa.info 00000038 00000000 00000000 00005ab1 2**0 + CONTENTS, READONLY + 91 .xt.lit 000000d0 00000000 00000000 00005ae9 2**0 + CONTENTS, RELOC, READONLY + 92 .xt.prop 00000bb8 00000000 00000000 00005bb9 2**0 + CONTENTS, RELOC, READONLY + +tasks.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.prvResetNextTaskUnblockTime 00000008 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.prvTaskGetSnapshotsFromList 00000004 00000000 00000000 0000003c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.prvDeleteTLS 00000018 00000000 00000000 00000040 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .literal.prvTaskIsTaskSuspended 0000001c 00000000 00000000 00000058 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 4 .literal.prvInitialiseNewTask 00000018 00000000 00000000 00000074 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .literal.prvInitialiseTaskLists 00000040 00000000 00000000 0000008c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .literal.prvDeleteTCB 0000002c 00000000 00000000 000000cc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .literal.prvAddCurrentTaskToDelayedList 0000001c 00000000 00000000 000000f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .literal.taskYIELD_OTHER_CORE 00000010 00000000 00000000 00000114 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 9 .literal.vTaskEndScheduler 00000008 00000000 00000000 00000124 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 10 .literal.vTaskSuspendAll 00000008 00000000 00000000 0000012c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 11 .literal.uxTaskGetNumberOfTasks 00000004 00000000 00000000 00000134 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 12 .literal.xTaskGetIdleTaskHandle 0000001c 00000000 00000000 00000138 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 13 .literal.xTaskGetIdleTaskHandleForCPU 0000001c 00000000 00000000 00000154 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 14 .literal.vTaskSwitchContext 0000003c 00000000 00000000 00000170 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 15 .literal.vTaskSetTimeOutState 00000020 00000000 00000000 000001ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 16 .literal.vTaskMissedYield 00000004 00000000 00000000 000001cc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 17 .literal.vTaskAllocateMPURegions 00000020 00000000 00000000 000001d0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 18 .literal.xTaskGetCurrentTaskHandle 00000008 00000000 00000000 000001f0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 19 .literal.__getreent 00000008 00000000 00000000 000001f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 20 .literal.pcTaskGetTaskName 0000001c 00000000 00000000 00000200 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 21 .literal.pvTaskGetThreadLocalStoragePointer 00000004 00000000 00000000 0000021c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 22 .literal.xTaskGetAffinity 00000004 00000000 00000000 00000220 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 23 .literal.uxTaskGetStackHighWaterMark 00000008 00000000 00000000 00000224 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 24 .literal.pxTaskGetStackStart 00000004 00000000 00000000 0000022c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 25 .literal.xTaskGetCurrentTaskHandleForCPU 00000004 00000000 00000000 00000230 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 26 .literal.xTaskGetSchedulerState 0000000c 00000000 00000000 00000234 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 27 .literal.vTaskEnterCritical 00000034 00000000 00000000 00000240 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 28 .literal.vTaskExitCritical 00000030 00000000 00000000 00000274 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 29 .literal.prvAddNewTaskToReadyList 00000058 00000000 00000000 000002a4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 30 .literal.xTaskCreateRestricted 00000028 00000000 00000000 000002fc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 31 .literal.xTaskCreatePinnedToCore 00000018 00000000 00000000 00000324 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 32 .literal.vTaskStartScheduler 00000038 00000000 00000000 0000033c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 33 .literal.vTaskDelete 00000060 00000000 00000000 00000374 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 34 .literal.vTaskDelayUntil 00000048 00000000 00000000 000003d4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 35 .literal.vTaskDelay 00000038 00000000 00000000 0000041c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 36 .literal.eTaskGetState 00000038 00000000 00000000 00000454 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 37 .literal.uxTaskPriorityGet 00000010 00000000 00000000 0000048c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 38 .literal.uxTaskPriorityGetFromISR 00000010 00000000 00000000 0000049c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 39 .literal.vTaskPrioritySet 00000044 00000000 00000000 000004ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 40 .literal.vTaskSuspend 00000060 00000000 00000000 000004f0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 41 .literal.vTaskResume 00000044 00000000 00000000 00000550 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 42 .literal.xTaskResumeFromISR 0000004c 00000000 00000000 00000594 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 43 .literal.prvCheckTasksWaitingTermination 00000030 00000000 00000000 000005e0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 44 .literal.prvIdleTask 00000008 00000000 00000000 00000610 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 45 .literal.xTaskGetTickCount 00000010 00000000 00000000 00000618 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 46 .literal.xTaskGetTickCountFromISR 00000010 00000000 00000000 00000628 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 47 .literal.xTaskIncrementTick 00000078 00000000 00000000 00000638 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 48 .literal.xTaskResumeAll 0000005c 00000000 00000000 000006b0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 49 .literal.vTaskPlaceOnEventList 00000040 00000000 00000000 0000070c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 50 .literal.vTaskPlaceOnUnorderedEventList 00000054 00000000 00000000 0000074c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 51 .literal.vTaskPlaceOnEventListRestricted 00000038 00000000 00000000 000007a0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 52 .literal.xTaskRemoveFromEventList 00000058 00000000 00000000 000007d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 53 .literal.xTaskRemoveFromUnorderedEventList 0000005c 00000000 00000000 00000830 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 54 .literal.xTaskCheckForTimeOut 0000003c 00000000 00000000 0000088c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 55 .literal.vTaskSetThreadLocalStoragePointerAndDelCallback 00000010 00000000 00000000 000008c8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 56 .literal.vTaskSetThreadLocalStoragePointer 00000004 00000000 00000000 000008d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 57 .literal.vTaskPriorityInherit 0000002c 00000000 00000000 000008dc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 58 .literal.xTaskPriorityDisinherit 00000040 00000000 00000000 00000908 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 59 .literal.uxTaskResetEventItemValue 00000010 00000000 00000000 00000948 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 60 .literal.pvTaskIncrementMutexHeldCount 00000010 00000000 00000000 00000958 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 61 .literal.ulTaskNotifyTake 00000030 00000000 00000000 00000968 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 62 .literal.xTaskNotifyWait 00000030 00000000 00000000 00000998 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 63 .literal.xTaskNotify 00000050 00000000 00000000 000009c8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 64 .literal.xTaskNotifyFromISR 00000058 00000000 00000000 00000a18 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 65 .literal.vTaskNotifyGiveFromISR 00000058 00000000 00000000 00000a70 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 66 .literal.uxTaskGetSnapshotAll 00000030 00000000 00000000 00000ac8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 67 .text 00000000 00000000 00000000 00000af8 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 68 .data 00000000 00000000 00000000 00000af8 2**0 + CONTENTS, ALLOC, LOAD, DATA + 69 .bss 00000000 00000000 00000000 00000af8 2**0 + ALLOC + 70 .text.prvTaskCheckFreeStackSpace 00000019 00000000 00000000 00000af8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 71 .text.prvResetNextTaskUnblockTime 00000034 00000000 00000000 00000b14 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 72 .text.prvTaskGetSnapshot 00000036 00000000 00000000 00000b48 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 73 .text.prvTaskGetSnapshotsFromList 00000047 00000000 00000000 00000b80 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 74 .rodata.str1.4 00000161 00000000 00000000 00000bc8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 75 .text.prvDeleteTLS 00000040 00000000 00000000 00000d2c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 76 .text.prvTaskIsTaskSuspended 0000004e 00000000 00000000 00000d6c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 77 .text.prvInitialiseNewTask 000000d0 00000000 00000000 00000dbc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 78 .text.prvInitialiseTaskLists 0000006e 00000000 00000000 00000e8c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 79 .text.prvDeleteTCB 0000005d 00000000 00000000 00000efc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 80 .text.prvAddCurrentTaskToDelayedList 0000006a 00000000 00000000 00000f5c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 81 .text.taskYIELD_OTHER_CORE 00000053 00000000 00000000 00000fc8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 82 .text.vTaskEndScheduler 00000018 00000000 00000000 0000101c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 83 .text.vTaskSuspendAll 00000026 00000000 00000000 00001034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 84 .text.uxTaskGetNumberOfTasks 0000000d 00000000 00000000 0000105c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 85 .text.xTaskGetIdleTaskHandle 0000003b 00000000 00000000 0000106c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 86 .text.xTaskGetIdleTaskHandleForCPU 0000002e 00000000 00000000 000010a8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 87 .text.vTaskSwitchContext 0000028a 00000000 00000000 000010d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 88 .text.vTaskSetTimeOutState 00000034 00000000 00000000 00001364 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 89 .text.vTaskMissedYield 00000018 00000000 00000000 00001398 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 90 .text.vTaskAllocateMPURegions 00000028 00000000 00000000 000013b0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 91 .text.xTaskGetCurrentTaskHandle 0000001f 00000000 00000000 000013d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 92 .text.__getreent 00000019 00000000 00000000 000013f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 93 .text.pcTaskGetTaskName 0000002d 00000000 00000000 00001414 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 94 .text.pvTaskGetThreadLocalStoragePointer 0000001e 00000000 00000000 00001444 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 95 .text.xTaskGetAffinity 00000013 00000000 00000000 00001464 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 96 .text.uxTaskGetStackHighWaterMark 0000001a 00000000 00000000 00001478 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 97 .text.pxTaskGetStackStart 00000012 00000000 00000000 00001494 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 98 .text.xTaskGetCurrentTaskHandleForCPU 00000018 00000000 00000000 000014a8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 99 .text.xTaskGetSchedulerState 00000037 00000000 00000000 000014c0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +100 .text.vTaskEnterCritical 000000b3 00000000 00000000 000014f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +101 .text.vTaskExitCritical 0000008a 00000000 00000000 000015ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +102 .text.prvAddNewTaskToReadyList 00000173 00000000 00000000 00001638 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +103 .text.xTaskCreateRestricted 00000074 00000000 00000000 000017ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +104 .text.xTaskCreatePinnedToCore 00000076 00000000 00000000 00001820 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +105 .text.vTaskStartScheduler 00000072 00000000 00000000 00001898 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +106 .text.vTaskDelete 00000122 00000000 00000000 0000190c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +107 .text.vTaskDelayUntil 000000e7 00000000 00000000 00001a30 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +108 .text.vTaskDelay 00000080 00000000 00000000 00001b18 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +109 .text.eTaskGetState 000000aa 00000000 00000000 00001b98 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +110 .text.uxTaskPriorityGet 00000023 00000000 00000000 00001c44 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +111 .text.uxTaskPriorityGetFromISR 00000023 00000000 00000000 00001c68 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +112 .text.vTaskPrioritySet 00000143 00000000 00000000 00001c8c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +113 .text.vTaskSuspend 00000106 00000000 00000000 00001dd0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +114 .text.vTaskResume 000000d8 00000000 00000000 00001ed8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +115 .text.xTaskResumeFromISR 000000f6 00000000 00000000 00001fb0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +116 .text.prvCheckTasksWaitingTermination 000000c6 00000000 00000000 000020a8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +117 .text.prvIdleTask 00000012 00000000 00000000 00002170 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +118 .text.xTaskGetTickCount 00000020 00000000 00000000 00002184 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +119 .text.xTaskGetTickCountFromISR 00000020 00000000 00000000 000021a4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +120 .text.xTaskIncrementTick 000001ce 00000000 00000000 000021c4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +121 .text.xTaskResumeAll 00000186 00000000 00000000 00002394 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +122 .text.vTaskPlaceOnEventList 00000097 00000000 00000000 0000251c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +123 .text.vTaskPlaceOnUnorderedEventList 000000cf 00000000 00000000 000025b4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +124 .text.vTaskPlaceOnEventListRestricted 0000006f 00000000 00000000 00002684 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +125 .text.xTaskRemoveFromEventList 00000143 00000000 00000000 000026f4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +126 .text.xTaskRemoveFromUnorderedEventList 000000ff 00000000 00000000 00002838 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +127 .text.xTaskCheckForTimeOut 00000096 00000000 00000000 00002938 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +128 .text.vTaskSetThreadLocalStoragePointerAndDelCallback 0000002f 00000000 00000000 000029d0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +129 .text.vTaskSetThreadLocalStoragePointer 00000013 00000000 00000000 00002a00 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +130 .text.vTaskPriorityInherit 000000db 00000000 00000000 00002a14 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +131 .text.xTaskPriorityDisinherit 000000aa 00000000 00000000 00002af0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +132 .text.uxTaskResetEventItemValue 0000003e 00000000 00000000 00002b9c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +133 .text.pvTaskIncrementMutexHeldCount 00000054 00000000 00000000 00002bdc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +134 .text.ulTaskNotifyTake 0000012e 00000000 00000000 00002c30 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +135 .text.xTaskNotifyWait 00000156 00000000 00000000 00002d60 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +136 .text.xTaskNotify 0000014a 00000000 00000000 00002eb8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +137 .text.xTaskNotifyFromISR 00000172 00000000 00000000 00003004 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +138 .text.vTaskNotifyGiveFromISR 0000011c 00000000 00000000 00003178 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +139 .text.uxTaskGetSnapshotAll 0000009c 00000000 00000000 00003294 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +140 .rodata.__FUNCTION__$5930 00000017 00000000 00000000 00003330 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +141 .rodata.__FUNCTION__$5917 00000013 00000000 00000000 00003348 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +142 .rodata.__FUNCTION__$5901 0000000c 00000000 00000000 0000335c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +143 .rodata.__func__$5851 00000029 00000000 00000000 00003368 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +144 .rodata.__func__$5846 00000029 00000000 00000000 00003394 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +145 .rodata.__FUNCTION__$5808 00000018 00000000 00000000 000033c0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +146 .rodata.__FUNCTION__$5718 00000018 00000000 00000000 000033d8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +147 .rodata.__FUNCTION__$5683 00000015 00000000 00000000 000033f0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +148 .rodata.__FUNCTION__$5677 00000015 00000000 00000000 00003408 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +149 .rodata.__FUNCTION__$5673 00000022 00000000 00000000 00003420 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +150 .rodata.__FUNCTION__$5663 00000019 00000000 00000000 00003444 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +151 .rodata.__FUNCTION__$5654 00000020 00000000 00000000 00003460 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +152 .rodata.__FUNCTION__$5648 0000001f 00000000 00000000 00003480 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +153 .rodata.__FUNCTION__$5641 00000016 00000000 00000000 000034a0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +154 .rodata.ucExpectedStackBytes$5613 00000014 00000000 00000000 000034b8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +155 .rodata.__FUNCTION__$5605 00000013 00000000 00000000 000034cc 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +156 .rodata.__FUNCTION__$5596 0000001d 00000000 00000000 000034e0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +157 .rodata.__FUNCTION__$5591 00000017 00000000 00000000 00003500 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +158 .rodata.__FUNCTION__$5587 00000012 00000000 00000000 00003518 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +159 .rodata.__FUNCTION__$5565 0000000f 00000000 00000000 0000352c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +160 .rodata.__FUNCTION__$5547 00000014 00000000 00000000 0000353c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +161 .rodata.__FUNCTION__$5536 00000013 00000000 00000000 00003550 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +162 .rodata.__FUNCTION__$5525 00000017 00000000 00000000 00003564 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +163 .rodata.__FUNCTION__$5530 0000000c 00000000 00000000 0000357c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +164 .rodata.__FUNCTION__$5519 0000000d 00000000 00000000 00003588 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +165 .rodata.__FUNCTION__$5513 00000011 00000000 00000000 00003598 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +166 .rodata.__FUNCTION__$5494 0000000e 00000000 00000000 000035ac 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +167 .rodata.__FUNCTION__$5485 0000000b 00000000 00000000 000035bc 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +168 .rodata.__FUNCTION__$5478 00000010 00000000 00000000 000035c8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +169 .rodata.__FUNCTION__$5772 0000000d 00000000 00000000 000035d8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +170 .rodata.__FUNCTION__$5776 0000000d 00000000 00000000 000035e8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +171 .rodata.__FUNCTION__$5470 0000000c 00000000 00000000 000035f8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +172 .rodata.__FUNCTION__$5463 00000019 00000000 00000000 00003604 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +173 .rodata.__FUNCTION__$5421 00000016 00000000 00000000 00003620 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +174 .bss.xSwitchingContext 00000008 00000000 00000000 00003638 2**2 + ALLOC +175 .data.xTickCountMutex 00000008 00000000 00000000 00003638 2**2 + CONTENTS, ALLOC, LOAD, DATA +176 .data.xTaskQueueMutex 00000008 00000000 00000000 00003640 2**2 + CONTENTS, ALLOC, LOAD, DATA +177 .bss.uxSchedulerSuspended 00000008 00000000 00000000 00003648 2**2 + ALLOC +178 .data.xNextTaskUnblockTime 00000004 00000000 00000000 00003648 2**2 + CONTENTS, ALLOC, LOAD, DATA +179 .bss.uxTaskNumber 00000004 00000000 00000000 0000364c 2**2 + ALLOC +180 .bss.xNumOfOverflows 00000004 00000000 00000000 0000364c 2**2 + ALLOC +181 .bss.xYieldPending 00000008 00000000 00000000 0000364c 2**2 + ALLOC +182 .bss.uxPendedTicks 00000004 00000000 00000000 0000364c 2**2 + ALLOC +183 .bss.xSchedulerRunning 00000004 00000000 00000000 0000364c 2**2 + ALLOC +184 .bss.uxTopReadyPriority 00000004 00000000 00000000 0000364c 2**2 + ALLOC +185 .bss.xTickCount 00000004 00000000 00000000 0000364c 2**2 + ALLOC +186 .bss.uxCurrentNumberOfTasks 00000004 00000000 00000000 0000364c 2**2 + ALLOC +187 .bss.xIdleTaskHandle 00000008 00000000 00000000 0000364c 2**2 + ALLOC +188 .bss.xSuspendedTaskList 00000014 00000000 00000000 0000364c 2**2 + ALLOC +189 .bss.uxTasksDeleted 00000004 00000000 00000000 0000364c 2**2 + ALLOC +190 .bss.xTasksWaitingTermination 00000014 00000000 00000000 0000364c 2**2 + ALLOC +191 .bss.xPendingReadyList 00000028 00000000 00000000 0000364c 2**2 + ALLOC +192 .bss.pxOverflowDelayedTaskList 00000004 00000000 00000000 0000364c 2**2 + ALLOC +193 .bss.pxDelayedTaskList 00000004 00000000 00000000 0000364c 2**2 + ALLOC +194 .bss.xDelayedTaskList2 00000014 00000000 00000000 0000364c 2**2 + ALLOC +195 .bss.xDelayedTaskList1 00000014 00000000 00000000 0000364c 2**2 + ALLOC +196 .bss.pxReadyTasksLists 000001f4 00000000 00000000 0000364c 2**2 + ALLOC +197 .bss.pxCurrentTCB 00000008 00000000 00000000 0000364c 2**2 + ALLOC +198 .debug_frame 00000688 00000000 00000000 0000364c 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING +199 .debug_info 00005e20 00000000 00000000 00003cd4 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING +200 .debug_abbrev 0000046f 00000000 00000000 00009af4 2**0 + CONTENTS, READONLY, DEBUGGING +201 .debug_loc 000022ef 00000000 00000000 00009f63 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING +202 .debug_aranges 00000240 00000000 00000000 0000c252 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING +203 .debug_ranges 000002c8 00000000 00000000 0000c492 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING +204 .debug_line 0000291c 00000000 00000000 0000c75a 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING +205 .debug_str 0000190d 00000000 00000000 0000f076 2**0 + CONTENTS, READONLY, DEBUGGING +206 .comment 0000003b 00000000 00000000 00010983 2**0 + CONTENTS, READONLY +207 .xtensa.info 00000038 00000000 00000000 000109be 2**0 + CONTENTS, READONLY +208 .xt.lit 00000218 00000000 00000000 000109f6 2**0 + CONTENTS, RELOC, READONLY +209 .xt.prop 00002154 00000000 00000000 00010c0e 2**0 + CONTENTS, RELOC, READONLY + +timers.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.prvGetNextExpireTime 00000004 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.prvInsertTimerInActiveList 00000010 00000000 00000000 00000038 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.prvCheckForValidListAndQueue 00000044 00000000 00000000 00000048 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .literal.prvInitialiseNewTimer 0000001c 00000000 00000000 0000008c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 4 .literal.xTimerCreateTimerTask 0000002c 00000000 00000000 000000a8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .literal.xTimerCreate 00000008 00000000 00000000 000000d4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .literal.xTimerGenericCommand 00000014 00000000 00000000 000000dc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .literal.prvSwitchTimerLists 00000028 00000000 00000000 000000f0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .literal.prvSampleTimeNow 0000000c 00000000 00000000 00000118 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 9 .literal.prvProcessExpiredTimer 00000024 00000000 00000000 00000124 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 10 .literal.prvProcessTimerOrBlockTask 00000024 00000000 00000000 00000148 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 11 .literal.prvProcessReceivedCommands 00000040 00000000 00000000 0000016c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 12 .literal.prvTimerTask 0000000c 00000000 00000000 000001ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 13 .literal.xTimerGetPeriod 00000014 00000000 00000000 000001b8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 14 .literal.xTimerGetExpiryTime 00000014 00000000 00000000 000001cc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 15 .literal.xTimerIsTimerActive 0000000c 00000000 00000000 000001e0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 16 .literal.vTimerSetTimerID 00000014 00000000 00000000 000001ec 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 17 .literal.xTimerPendFunctionCallFromISR 00000008 00000000 00000000 00000200 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 18 .literal.xTimerPendFunctionCall 0000001c 00000000 00000000 00000208 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 19 .text 00000000 00000000 00000000 00000224 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 20 .data 00000000 00000000 00000000 00000224 2**0 + CONTENTS, ALLOC, LOAD, DATA + 21 .bss 00000000 00000000 00000000 00000224 2**0 + ALLOC + 22 .text.prvGetNextExpireTime 00000020 00000000 00000000 00000224 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 23 .text.prvInsertTimerInActiveList 00000054 00000000 00000000 00000244 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 24 .rodata.str1.4 00000058 00000000 00000000 00000298 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 25 .text.prvCheckForValidListAndQueue 0000007e 00000000 00000000 000002f0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 26 .text.prvInitialiseNewTimer 0000003a 00000000 00000000 00000370 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 27 .text.xTimerCreateTimerTask 0000004c 00000000 00000000 000003ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 28 .text.xTimerCreate 00000026 00000000 00000000 000003f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 29 .text.xTimerGenericCommand 0000005d 00000000 00000000 00000420 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 30 .text.prvSwitchTimerLists 00000082 00000000 00000000 00000480 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 31 .text.prvSampleTimeNow 0000002f 00000000 00000000 00000504 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 32 .text.prvProcessExpiredTimer 0000005f 00000000 00000000 00000534 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 33 .text.prvProcessTimerOrBlockTask 0000006c 00000000 00000000 00000594 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 34 .text.prvProcessReceivedCommands 000000e6 00000000 00000000 00000600 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 35 .rodata.prvProcessReceivedCommands 00000028 00000000 00000000 000006e8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA + 36 .text.prvTimerTask 0000001d 00000000 00000000 00000710 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 37 .text.xTimerGetPeriod 00000022 00000000 00000000 00000730 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 38 .text.xTimerGetExpiryTime 00000022 00000000 00000000 00000754 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 39 .text.pcTimerGetTimerName 00000007 00000000 00000000 00000778 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 40 .text.xTimerIsTimerActive 00000024 00000000 00000000 00000780 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 41 .text.pvTimerGetTimerID 00000007 00000000 00000000 000007a4 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 42 .text.vTimerSetTimerID 00000022 00000000 00000000 000007ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 43 .text.xTimerPendFunctionCallFromISR 00000022 00000000 00000000 000007d0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 44 .text.xTimerPendFunctionCall 0000003c 00000000 00000000 000007f4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 45 .rodata.__FUNCTION__$5352 00000017 00000000 00000000 00000830 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 46 .rodata.__FUNCTION__$5335 00000011 00000000 00000000 00000848 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 47 .rodata.__FUNCTION__$5240 00000014 00000000 00000000 0000085c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 48 .rodata.__FUNCTION__$5234 00000010 00000000 00000000 00000870 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 49 .rodata.__FUNCTION__$5220 00000016 00000000 00000000 00000880 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 50 .rodata.__FUNCTION__$5320 0000001d 00000000 00000000 00000898 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 51 .rodata.__FUNCTION__$5289 0000001b 00000000 00000000 000008b8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 52 .rodata.__FUNCTION__$5251 00000017 00000000 00000000 000008d4 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 53 .rodata.__FUNCTION__$5313 00000014 00000000 00000000 000008ec 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 54 .bss.xLastTime$5272 00000004 00000000 00000000 00000900 2**2 + ALLOC + 55 .rodata.__FUNCTION__$5203 00000016 00000000 00000000 00000900 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 56 .data.xTimerMux 00000008 00000000 00000000 00000918 2**2 + CONTENTS, ALLOC, LOAD, DATA + 57 .bss.xTimerQueue 00000004 00000000 00000000 00000920 2**2 + ALLOC + 58 .bss.pxOverflowTimerList 00000004 00000000 00000000 00000920 2**2 + ALLOC + 59 .bss.pxCurrentTimerList 00000004 00000000 00000000 00000920 2**2 + ALLOC + 60 .bss.xActiveTimerList2 00000014 00000000 00000000 00000920 2**2 + ALLOC + 61 .bss.xActiveTimerList1 00000014 00000000 00000000 00000920 2**2 + ALLOC + 62 .debug_frame 00000208 00000000 00000000 00000920 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 63 .debug_info 00001405 00000000 00000000 00000b28 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 64 .debug_abbrev 00000279 00000000 00000000 00001f2d 2**0 + CONTENTS, READONLY, DEBUGGING + 65 .debug_loc 0000062f 00000000 00000000 000021a6 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 66 .debug_aranges 000000c0 00000000 00000000 000027d5 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 67 .debug_ranges 000000b0 00000000 00000000 00002895 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 68 .debug_line 00000771 00000000 00000000 00002945 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 69 .debug_str 00000934 00000000 00000000 000030b6 2**0 + CONTENTS, READONLY, DEBUGGING + 70 .comment 0000003b 00000000 00000000 000039ea 2**0 + CONTENTS, READONLY + 71 .xtensa.info 00000038 00000000 00000000 00003a25 2**0 + CONTENTS, READONLY + 72 .xt.lit 00000098 00000000 00000000 00003a5d 2**0 + CONTENTS, RELOC, READONLY + 73 .xt.prop 00000714 00000000 00000000 00003af5 2**0 + CONTENTS, RELOC, READONLY + +xtensa_context.S.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal 00000024 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .text 0000013a 00000000 00000000 00000058 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .data 00000000 00000000 00000000 00000192 2**0 + CONTENTS, ALLOC, LOAD, DATA + 3 .bss 00000000 00000000 00000000 00000192 2**0 + ALLOC + 4 .xtensa.info 00000038 00000000 00000000 00000192 2**0 + CONTENTS, READONLY + 5 .debug_line 00000313 00000000 00000000 000001ca 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 6 .debug_info 0000009a 00000000 00000000 000004dd 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 7 .debug_abbrev 00000014 00000000 00000000 00000577 2**0 + CONTENTS, READONLY, DEBUGGING + 8 .debug_aranges 00000020 00000000 00000000 00000590 2**3 + CONTENTS, RELOC, READONLY, DEBUGGING + 9 .xt.lit 00000008 00000000 00000000 000005b0 2**0 + CONTENTS, RELOC, READONLY + 10 .xt.prop 000000e4 00000000 00000000 000005b8 2**0 + CONTENTS, RELOC, READONLY + +xtensa_init.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal._xt_tick_divisor_init 0000000c 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.xt_clock_freq 00000004 00000000 00000000 00000040 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .text 00000000 00000000 00000000 00000044 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 3 .data 00000000 00000000 00000000 00000044 2**0 + CONTENTS, ALLOC, LOAD, DATA + 4 .bss 00000000 00000000 00000000 00000044 2**0 + ALLOC + 5 .text._xt_tick_divisor_init 0000001f 00000000 00000000 00000044 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .text.xt_clock_freq 0000000d 00000000 00000000 00000064 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .bss._xt_tick_divisor 00000004 00000000 00000000 00000074 2**2 + ALLOC + 8 .debug_frame 00000040 00000000 00000000 00000074 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 9 .debug_info 000000d4 00000000 00000000 000000b4 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 10 .debug_abbrev 0000008b 00000000 00000000 00000188 2**0 + CONTENTS, READONLY, DEBUGGING + 11 .debug_aranges 00000028 00000000 00000000 00000213 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 12 .debug_ranges 00000018 00000000 00000000 0000023b 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 13 .debug_line 000000c8 00000000 00000000 00000253 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 14 .debug_str 00000180 00000000 00000000 0000031b 2**0 + CONTENTS, READONLY, DEBUGGING + 15 .comment 0000003b 00000000 00000000 0000049b 2**0 + CONTENTS, READONLY + 16 .xtensa.info 00000038 00000000 00000000 000004d6 2**0 + CONTENTS, READONLY + 17 .xt.lit 00000010 00000000 00000000 0000050e 2**0 + CONTENTS, RELOC, READONLY + 18 .xt.prop 0000006c 00000000 00000000 0000051e 2**0 + CONTENTS, RELOC, READONLY + +xtensa_intr.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.xt_unhandled_interrupt 00000008 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.xt_set_exception_handler 00000008 00000000 00000000 0000003c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.xt_set_interrupt_handler 0000000c 00000000 00000000 00000044 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .text 00000000 00000000 00000000 00000050 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 4 .data 00000000 00000000 00000000 00000050 2**0 + CONTENTS, ALLOC, LOAD, DATA + 5 .bss 00000000 00000000 00000000 00000050 2**0 + ALLOC + 6 .rodata.str1.4 00000023 00000000 00000000 00000050 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 7 .text.xt_unhandled_interrupt 00000016 00000000 00000000 00000074 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .text.xt_set_exception_handler 00000042 00000000 00000000 0000008c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 9 .text.xt_set_interrupt_handler 00000046 00000000 00000000 000000d0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 10 .debug_frame 00000058 00000000 00000000 00000118 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 11 .debug_info 0000042d 00000000 00000000 00000170 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 12 .debug_abbrev 000001b6 00000000 00000000 0000059d 2**0 + CONTENTS, READONLY, DEBUGGING + 13 .debug_loc 0000015c 00000000 00000000 00000753 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 14 .debug_aranges 00000030 00000000 00000000 000008af 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 15 .debug_ranges 00000020 00000000 00000000 000008df 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 16 .debug_line 000002b8 00000000 00000000 000008ff 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 17 .debug_str 000002a5 00000000 00000000 00000bb7 2**0 + CONTENTS, READONLY, DEBUGGING + 18 .comment 0000003b 00000000 00000000 00000e5c 2**0 + CONTENTS, READONLY + 19 .xtensa.info 00000038 00000000 00000000 00000e97 2**0 + CONTENTS, READONLY + 20 .xt.lit 00000018 00000000 00000000 00000ecf 2**0 + CONTENTS, RELOC, READONLY + 21 .xt.prop 00000120 00000000 00000000 00000ee7 2**0 + CONTENTS, RELOC, READONLY + +xtensa_intr_asm.S.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 00000033 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .data 00000400 00000000 00000000 00000068 2**3 + CONTENTS, ALLOC, LOAD, RELOC, DATA + 2 .bss 00000000 00000000 00000000 00000468 2**0 + ALLOC + 3 .xtensa.info 00000038 00000000 00000000 00000468 2**0 + CONTENTS, READONLY + 4 .debug_line 000000da 00000000 00000000 000004a0 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 5 .debug_info 0000009b 00000000 00000000 0000057a 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 6 .debug_abbrev 00000014 00000000 00000000 00000615 2**0 + CONTENTS, READONLY, DEBUGGING + 7 .debug_aranges 00000020 00000000 00000000 00000630 2**3 + CONTENTS, RELOC, READONLY, DEBUGGING + 8 .xt.prop 00000054 00000000 00000000 00000650 2**0 + CONTENTS, RELOC, READONLY + +xtensa_overlay_os_hook.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.xt_overlay_init_os 00000008 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.xt_overlay_lock 00000008 00000000 00000000 0000003c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.xt_overlay_unlock 00000008 00000000 00000000 00000044 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .text 00000000 00000000 00000000 0000004c 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 4 .data 00000000 00000000 00000000 0000004c 2**0 + CONTENTS, ALLOC, LOAD, DATA + 5 .bss 00000000 00000000 00000000 0000004c 2**0 + ALLOC + 6 .text.xt_overlay_init_os 00000013 00000000 00000000 0000004c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .text.xt_overlay_lock 00000016 00000000 00000000 00000060 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .text.xt_overlay_unlock 00000016 00000000 00000000 00000078 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 9 .bss.xt_overlay_mutex 00000004 00000000 00000000 00000090 2**2 + ALLOC + 10 .debug_frame 00000058 00000000 00000000 00000090 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 11 .debug_info 00000193 00000000 00000000 000000e8 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 12 .debug_abbrev 0000008f 00000000 00000000 0000027b 2**0 + CONTENTS, READONLY, DEBUGGING + 13 .debug_aranges 00000030 00000000 00000000 0000030a 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 14 .debug_ranges 00000020 00000000 00000000 0000033a 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 15 .debug_line 00000192 00000000 00000000 0000035a 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 16 .debug_str 0000025c 00000000 00000000 000004ec 2**0 + CONTENTS, READONLY, DEBUGGING + 17 .comment 0000003b 00000000 00000000 00000748 2**0 + CONTENTS, READONLY + 18 .xtensa.info 00000038 00000000 00000000 00000783 2**0 + CONTENTS, READONLY + 19 .xt.lit 00000018 00000000 00000000 000007bb 2**0 + CONTENTS, RELOC, READONLY + 20 .xt.prop 0000009c 00000000 00000000 000007d3 2**0 + CONTENTS, RELOC, READONLY + +xtensa_vector_defaults.S.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .iram1.literal 00000004 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .text 00000000 00000000 00000000 00000038 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 2 .data 00000000 00000000 00000000 00000038 2**0 + CONTENTS, ALLOC, LOAD, DATA + 3 .bss 00000000 00000000 00000000 00000038 2**0 + ALLOC + 4 .iram1 00000032 00000000 00000000 00000038 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .xtensa.info 00000038 00000000 00000000 0000006a 2**0 + CONTENTS, READONLY + 6 .debug_line 000000c2 00000000 00000000 000000a2 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 7 .debug_info 000000a2 00000000 00000000 00000164 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 8 .debug_abbrev 00000014 00000000 00000000 00000206 2**0 + CONTENTS, READONLY, DEBUGGING + 9 .debug_aranges 00000020 00000000 00000000 00000220 2**3 + CONTENTS, RELOC, READONLY, DEBUGGING + 10 .xt.lit 00000008 00000000 00000000 00000240 2**0 + CONTENTS, RELOC, READONLY + 11 .xt.prop 00000078 00000000 00000000 00000248 2**0 + CONTENTS, RELOC, READONLY + +xtensa_vectors.S.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .iram1.literal 000000a8 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .DebugExceptionVector.literal 00000004 00000000 00000000 000000dc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .DoubleExceptionVector.literal 00000004 00000000 00000000 000000e0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .KernelExceptionVector.literal 00000004 00000000 00000000 000000e4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 4 .UserExceptionVector.literal 00000004 00000000 00000000 000000e8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .Level2InterruptVector.literal 00000004 00000000 00000000 000000ec 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .Level3InterruptVector.literal 00000004 00000000 00000000 000000f0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .Level4InterruptVector.literal 00000004 00000000 00000000 000000f4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .Level5InterruptVector.literal 00000004 00000000 00000000 000000f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 9 .NMIExceptionVector.literal 00000004 00000000 00000000 000000fc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 10 .text 00000000 00000000 00000000 00000100 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 11 .data 00000008 00000000 00000000 00000100 2**4 + CONTENTS, ALLOC, LOAD, DATA + 12 .bss 00000000 00000000 00000000 00000108 2**0 + ALLOC + 13 .iram1 000004ec 00000000 00000000 00000108 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 14 .rodata 00000024 00000000 00000000 00000600 2**4 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 15 .DebugExceptionVector.text 00000009 00000000 00000000 00000624 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 16 .DoubleExceptionVector.text 00000011 00000000 00000000 00000630 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 17 .KernelExceptionVector.text 00000009 00000000 00000000 00000644 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 18 .UserExceptionVector.text 00000009 00000000 00000000 00000650 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 19 .Level2InterruptVector.text 00000009 00000000 00000000 0000065c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 20 .Level3InterruptVector.text 00000009 00000000 00000000 00000668 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 21 .Level4InterruptVector.text 00000009 00000000 00000000 00000674 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 22 .Level5InterruptVector.text 00000009 00000000 00000000 00000680 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 23 .NMIExceptionVector.text 00000009 00000000 00000000 0000068c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 24 .WindowVectors.text 0000016a 00000000 00000000 00000698 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 25 .UserEnter.text 00000000 00000000 00000000 00000804 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 26 .xtensa.info 00000038 00000000 00000000 00000804 2**0 + CONTENTS, READONLY + 27 .debug_line 000009b8 00000000 00000000 0000083c 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 28 .debug_info 00000096 00000000 00000000 000011f4 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 29 .debug_abbrev 00000012 00000000 00000000 0000128a 2**0 + CONTENTS, READONLY, DEBUGGING + 30 .debug_aranges 00000070 00000000 00000000 000012a0 2**3 + CONTENTS, RELOC, READONLY, DEBUGGING + 31 .debug_ranges 00000068 00000000 00000000 00001310 2**3 + CONTENTS, RELOC, READONLY, DEBUGGING + 32 .xt.lit 00000050 00000000 00000000 00001378 2**0 + CONTENTS, RELOC, READONLY + 33 .xt.prop 000004f8 00000000 00000000 000013c8 2**0 + CONTENTS, RELOC, READONLY diff --git a/tools/ldgen/samples/template.ld b/tools/ldgen/samples/template.ld new file mode 100644 index 0000000000..02a0d21cb9 --- /dev/null +++ b/tools/ldgen/samples/template.ld @@ -0,0 +1,217 @@ +/* Default entry point: */ +ENTRY(call_start_cpu0); + +SECTIONS +{ + /* RTC fast memory holds RTC wake stub code, + including from any source file named rtc_wake_stub*.c + */ + .rtc.text : + { + . = ALIGN(4); + + mapping[rtc_text] + + *rtc_wake_stub*.o(.literal .text .literal.* .text.*) + } >rtc_iram_seg + + /* RTC slow memory holds RTC wake stub + data/rodata, including from any source file + named rtc_wake_stub*.c + */ + .rtc.data : + { + _rtc_data_start = ABSOLUTE(.); + + mapping[rtc_data] + + *rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*) + _rtc_data_end = ABSOLUTE(.); + } > rtc_slow_seg + + /* RTC bss, from any source file named rtc_wake_stub*.c */ + .rtc.bss (NOLOAD) : + { + _rtc_bss_start = ABSOLUTE(.); + + mapping[rtc_bss] + + *rtc_wake_stub*.o(.bss .bss.*) + *rtc_wake_stub*.o(COMMON) + _rtc_bss_end = ABSOLUTE(.); + } > rtc_slow_seg + + /* Send .iram0 code to iram */ + .iram0.vectors : + { + /* Vectors go to IRAM */ + _init_start = ABSOLUTE(.); + /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */ + . = 0x0; + KEEP(*(.WindowVectors.text)); + . = 0x180; + KEEP(*(.Level2InterruptVector.text)); + . = 0x1c0; + KEEP(*(.Level3InterruptVector.text)); + . = 0x200; + KEEP(*(.Level4InterruptVector.text)); + . = 0x240; + KEEP(*(.Level5InterruptVector.text)); + . = 0x280; + KEEP(*(.DebugExceptionVector.text)); + . = 0x2c0; + KEEP(*(.NMIExceptionVector.text)); + . = 0x300; + KEEP(*(.KernelExceptionVector.text)); + . = 0x340; + KEEP(*(.UserExceptionVector.text)); + . = 0x3C0; + KEEP(*(.DoubleExceptionVector.text)); + . = 0x400; + *(.*Vector.literal) + + *(.UserEnter.literal); + *(.UserEnter.text); + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + _init_end = ABSOLUTE(.); + + /* This goes here, not at top of linker script, so addr2line finds it last, + and uses it in preference to the first symbol in IRAM */ + _iram_start = ABSOLUTE(0); + } > iram0_0_seg + + .iram0.text : + { + /* Code marked as runnning out of IRAM */ + _iram_text_start = ABSOLUTE(.); + + mapping[iram0_text] + + INCLUDE esp32.spiram.rom-functions-iram.ld + _iram_text_end = ABSOLUTE(.); + } > iram0_0_seg + + .dram0.data : + { + _data_start = ABSOLUTE(.); + + mapping[dram0_data] + + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + INCLUDE esp32.spiram.rom-functions-dram.ld + _data_end = ABSOLUTE(.); + . = ALIGN(4); + } >dram0_0_seg + + /* Shared RAM */ + .dram0.bss (NOLOAD) : + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + + mapping[dram0_bss] + + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.share.mem) + *(.gnu.linkonce.b.*) + + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + _heap_start = ABSOLUTE(.); + } >dram0_0_seg + + .flash.rodata : + { + _rodata_start = ABSOLUTE(.); + + mapping[flash_rodata] + + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + . = (. + 3) & ~ 3; + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; + /* C++ constructor and destructor tables, properly ordered: */ + __init_array_start = ABSOLUTE(.); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __init_array_end = ABSOLUTE(.); + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + _rodata_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + _thread_local_start = ABSOLUTE(.); + *(.tdata) + *(.tdata.*) + *(.tbss) + *(.tbss.*) + _thread_local_end = ABSOLUTE(.); + . = ALIGN(4); + } >drom0_0_seg + + .flash.text : + { + _stext = .; + _text_start = ABSOLUTE(.); + + mapping[flash_text] + + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.fini.literal) + *(.fini) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + + /* Similar to _iram_start, this symbol goes here so it is + resolved by addr2line in preference to the first symbol in + the flash.text segment. + */ + _flash_cache_start = ABSOLUTE(0); + } >iram0_2_seg +} diff --git a/tools/ldgen/sdkconfig.py b/tools/ldgen/sdkconfig.py new file mode 100644 index 0000000000..9ef23ec84f --- /dev/null +++ b/tools/ldgen/sdkconfig.py @@ -0,0 +1,87 @@ +#!/usr/bin/env python +# +# Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import os +from pyparsing import * + +import sys +parent_dir_name = os.path.dirname(os.path.dirname(os.path.realpath(__file__))) +kconfig_new_dir = os.path.abspath(parent_dir_name + "/kconfig_new") +sys.path.append(kconfig_new_dir) +import kconfiglib + + + +""" +Encapsulates an sdkconfig file. Defines grammar of a configuration entry, and enables +evaluation of logical expressions involving those entries. +""" +class SDKConfig: + + # A configuration entry is in the form CONFIG=VALUE. Definitions of components of that grammar + IDENTIFIER = Word(printables.upper()) + + HEX = Combine("0x" + Word(hexnums)).setParseAction(lambda t:int(t[0], 16)) + DECIMAL = Combine(Optional(Literal("+") | Literal("-")) + Word(nums)).setParseAction(lambda t:int(t[0])) + LITERAL = Word(printables) + QUOTED_LITERAL = quotedString.setParseAction(removeQuotes) + + VALUE = HEX | DECIMAL | LITERAL | QUOTED_LITERAL + + # Operators supported by the expression evaluation + OPERATOR = oneOf(["=", "!=", ">", "<", "<=", ">="]) + + def __init__(self, kconfig_file, sdkconfig_file, env = []): + env = [ (name, value) for (name,value) in ( e.split("=",1) for e in env) ] + + for name, value in env: + value = " ".join(value.split()) + os.environ[name] = value + + self.config = kconfiglib.Kconfig(kconfig_file.name) + self.config.load_config(sdkconfig_file.name) + + def evaluate_expression(self, expression): + result = self.config.eval_string(expression) + + if result == 0: # n + return False + elif result == 2: # y + return True + else: # m + raise Exception("Unsupported config expression result.") + + @staticmethod + def get_expression_grammar(): + identifier = SDKConfig.IDENTIFIER.setResultsName("identifier") + operator = SDKConfig.OPERATOR.setResultsName("operator") + value = SDKConfig.VALUE.setResultsName("value") + + test_binary = identifier + operator + value + test_single = identifier + + test = test_binary | test_single + + condition = Group(Optional("(").suppress() + test + Optional(")").suppress()) + + grammar = infixNotation( + condition, [ + ("!", 1, opAssoc.RIGHT), + ("&&", 2, opAssoc.LEFT), + ("||", 2, opAssoc.LEFT)]) + + return grammar \ No newline at end of file diff --git a/tools/ldgen/test/data/Kconfig b/tools/ldgen/test/data/Kconfig new file mode 100644 index 0000000000..17993d0c33 --- /dev/null +++ b/tools/ldgen/test/data/Kconfig @@ -0,0 +1,7 @@ +menu "Test config" + +config PERFORMANCE_LEVEL + int "Performance level" + range 0 3 + +endmenu diff --git a/tools/ldgen/test/data/sample.lf b/tools/ldgen/test/data/sample.lf new file mode 100644 index 0000000000..45cb85dcd8 --- /dev/null +++ b/tools/ldgen/test/data/sample.lf @@ -0,0 +1,84 @@ +[sections:text] +entries: + .text+ + .literal+ + +[sections:data] +entries: + .data+ + +[sections:bss] +entries: + .bss+ + +[sections:common] +entries: + COMMON + +[sections:rodata] +entries: + .rodata+ + +[sections:rtc_text] +entries: + .rtc.text + .rtc.literal + +[sections:rtc_data] +entries: + .rtc.data + +[sections:rtc_rodata] +entries: + .rtc.rodata + +[sections:rtc_bss] +entries: + .rtc.bss + +[sections:extram_bss] +entries: + .exram.bss + +[sections:iram] +entries: + .iram+ + +[sections:dram] +entries: + .dram+ + +[scheme:default] +entries: + text -> flash_text + rodata -> flash_rodata + data -> dram0_data + bss -> dram0_bss + common -> dram0_bss + iram -> iram0_text + dram -> dram0_data + rtc_text -> rtc_text + rtc_data -> rtc_data + rtc_rodata -> rtc_data + rtc_bss -> rtc_bss + +[scheme:rtc] +entries: + text -> rtc_text + data -> rtc_data + rodata -> rtc_data + bss -> rtc_bss + common -> rtc_bss + +[scheme:noflash] +entries: + text -> iram0_text + rodata -> dram0_data + +[scheme:noflash_text] +entries: + text -> iram0_text + +[scheme:noflash_data] +entries: + rodata -> dram0_data \ No newline at end of file diff --git a/tools/ldgen/test/data/sdkconfig b/tools/ldgen/test/data/sdkconfig new file mode 100644 index 0000000000..b9e025fae3 --- /dev/null +++ b/tools/ldgen/test/data/sdkconfig @@ -0,0 +1,8 @@ +CONFIG_TEST_STRING="This Is~AString#$^#$&^(*&^#(*&^)(*@_)(#*_)(*_(*}Value" +CONFIG_TEST_NON_STRING=y +CONFIG_TEST_WHITESPACE= y +CONFIG_TEST_EMPTY= +CONFIG_TEST_POSITIVE_INT=110 +CONFIG_TEST_HEX_INT=0x8000 +CONFIG_TEST_NEGATIVE_INT=-9 +CONFIG_PERFORMANCE_LEVEL=0 \ No newline at end of file diff --git a/tools/ldgen/test/data/sections.info b/tools/ldgen/test/data/sections.info new file mode 100644 index 0000000000..db450cfbae --- /dev/null +++ b/tools/ldgen/test/data/sections.info @@ -0,0 +1,1626 @@ +In archive libfreertos.a: + +FreeRTOS-openocd.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 00000000 00000000 00000000 00000034 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .data 00000000 00000000 00000000 00000034 2**0 + CONTENTS, ALLOC, LOAD, DATA + 2 .bss 00000000 00000000 00000000 00000034 2**0 + ALLOC + 3 .dram1 00000004 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 4 .debug_info 0000008f 00000000 00000000 00000038 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 5 .debug_abbrev 0000003e 00000000 00000000 000000c7 2**0 + CONTENTS, READONLY, DEBUGGING + 6 .debug_aranges 00000018 00000000 00000000 00000105 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 7 .debug_line 0000005e 00000000 00000000 0000011d 2**0 + CONTENTS, READONLY, DEBUGGING + 8 .debug_str 0000018d 00000000 00000000 0000017b 2**0 + CONTENTS, READONLY, DEBUGGING + 9 .comment 0000003b 00000000 00000000 00000308 2**0 + CONTENTS, READONLY + 10 .xtensa.info 00000038 00000000 00000000 00000343 2**0 + CONTENTS, READONLY + 11 .xt.prop 0000000c 00000000 00000000 0000037b 2**0 + CONTENTS, RELOC, READONLY + +croutine.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.prvCheckPendingReadyList 00000018 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.prvCheckDelayedList 0000002c 00000000 00000000 0000004c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.xCoRoutineCreate 0000001c 00000000 00000000 00000078 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .literal.vCoRoutineAddToDelayedList 00000020 00000000 00000000 00000094 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 4 .literal.vCoRoutineSchedule 00000014 00000000 00000000 000000b4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .literal.xCoRoutineRemoveFromEventList 00000010 00000000 00000000 000000c8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .text 00000000 00000000 00000000 000000d8 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 7 .data 00000000 00000000 00000000 000000d8 2**0 + CONTENTS, ALLOC, LOAD, DATA + 8 .bss 00000000 00000000 00000000 000000d8 2**0 + ALLOC + 9 .text.prvCheckPendingReadyList 00000056 00000000 00000000 000000d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 10 .text.prvCheckDelayedList 000000ac 00000000 00000000 00000130 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 11 .rodata.str1.4 00000074 00000000 00000000 000001dc 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 12 .text.xCoRoutineCreate 00000028 00000000 00000000 00000250 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 13 .text.vCoRoutineAddToDelayedList 00000056 00000000 00000000 00000278 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 14 .text.vCoRoutineSchedule 0000007a 00000000 00000000 000002d0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 15 .text.xCoRoutineRemoveFromEventList 00000031 00000000 00000000 0000034c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 16 .rodata.__FUNCTION__$5025 00000011 00000000 00000000 00000380 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 17 .bss.xPassedTicks 00000004 00000000 00000000 00000394 2**2 + ALLOC + 18 .bss.xLastTickCount 00000004 00000000 00000000 00000394 2**2 + ALLOC + 19 .bss.xCoRoutineTickCount 00000004 00000000 00000000 00000394 2**2 + ALLOC + 20 .bss.uxTopCoRoutineReadyPriority 00000004 00000000 00000000 00000394 2**2 + ALLOC + 21 .bss.pxCurrentCoRoutine 00000004 00000000 00000000 00000394 2**2 + ALLOC + 22 .bss.xPendingReadyCoRoutineList 00000014 00000000 00000000 00000394 2**2 + ALLOC + 23 .bss.pxOverflowDelayedCoRoutineList 00000004 00000000 00000000 00000394 2**2 + ALLOC + 24 .bss.pxDelayedCoRoutineList 00000004 00000000 00000000 00000394 2**2 + ALLOC + 25 .bss.pxReadyCoRoutineLists 00000028 00000000 00000000 00000394 2**2 + ALLOC + 26 .debug_frame 000000a0 00000000 00000000 00000394 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 27 .debug_info 000006b8 00000000 00000000 00000434 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 28 .debug_abbrev 00000233 00000000 00000000 00000aec 2**0 + CONTENTS, READONLY, DEBUGGING + 29 .debug_loc 0000013b 00000000 00000000 00000d1f 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 30 .debug_aranges 00000048 00000000 00000000 00000e5a 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 31 .debug_ranges 00000038 00000000 00000000 00000ea2 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 32 .debug_line 0000037e 00000000 00000000 00000eda 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 33 .debug_str 00000533 00000000 00000000 00001258 2**0 + CONTENTS, READONLY, DEBUGGING + 34 .comment 0000003b 00000000 00000000 0000178b 2**0 + CONTENTS, READONLY + 35 .xtensa.info 00000038 00000000 00000000 000017c6 2**0 + CONTENTS, READONLY + 36 .xt.lit 00000030 00000000 00000000 000017fe 2**0 + CONTENTS, RELOC, READONLY + 37 .xt.prop 00000270 00000000 00000000 0000182e 2**0 + CONTENTS, RELOC, READONLY + +event_groups.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.xEventGroupCreate 0000000c 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.xEventGroupWaitBits 0000006c 00000000 00000000 00000040 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.xEventGroupClearBits 00000028 00000000 00000000 000000ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .literal.xEventGroupGetBitsFromISR 00000004 00000000 00000000 000000d4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 4 .literal.xEventGroupSetBits 0000003c 00000000 00000000 000000d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .literal.xEventGroupSync 0000005c 00000000 00000000 00000114 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .literal.vEventGroupDelete 00000030 00000000 00000000 00000170 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .literal.vEventGroupSetBitsCallback 00000004 00000000 00000000 000001a0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .literal.vEventGroupClearBitsCallback 00000004 00000000 00000000 000001a4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 9 .text 00000000 00000000 00000000 000001a8 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 10 .data 00000000 00000000 00000000 000001a8 2**0 + CONTENTS, ALLOC, LOAD, DATA + 11 .bss 00000000 00000000 00000000 000001a8 2**0 + ALLOC + 12 .text.prvTestWaitCondition 0000001e 00000000 00000000 000001a8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 13 .text.xEventGroupCreate 00000027 00000000 00000000 000001c8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 14 .rodata.str1.4 00000058 00000000 00000000 000001f0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 15 .text.xEventGroupWaitBits 00000140 00000000 00000000 00000248 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 16 .text.xEventGroupClearBits 00000060 00000000 00000000 00000388 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 17 .text.xEventGroupGetBitsFromISR 00000010 00000000 00000000 000003e8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 18 .text.xEventGroupSetBits 000000c3 00000000 00000000 000003f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 19 .text.xEventGroupSync 00000108 00000000 00000000 000004bc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 20 .text.vEventGroupDelete 0000005d 00000000 00000000 000005c4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 21 .text.vEventGroupSetBitsCallback 0000000f 00000000 00000000 00000624 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 22 .text.vEventGroupClearBitsCallback 0000000f 00000000 00000000 00000634 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 23 .rodata.__FUNCTION__$5129 00000012 00000000 00000000 00000644 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 24 .rodata.__FUNCTION__$5120 00000013 00000000 00000000 00000658 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 25 .rodata.__FUNCTION__$5100 00000015 00000000 00000000 0000066c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 26 .rodata.__FUNCTION__$5092 00000014 00000000 00000000 00000684 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 27 .rodata.__FUNCTION__$5078 00000010 00000000 00000000 00000698 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 28 .debug_frame 00000100 00000000 00000000 000006a8 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 29 .debug_info 00000e02 00000000 00000000 000007a8 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 30 .debug_abbrev 00000236 00000000 00000000 000015aa 2**0 + CONTENTS, READONLY, DEBUGGING + 31 .debug_loc 00000546 00000000 00000000 000017e0 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 32 .debug_aranges 00000068 00000000 00000000 00001d26 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 33 .debug_ranges 00000070 00000000 00000000 00001d8e 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 34 .debug_line 000006af 00000000 00000000 00001dfe 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 35 .debug_str 00000677 00000000 00000000 000024ad 2**0 + CONTENTS, READONLY, DEBUGGING + 36 .comment 0000003b 00000000 00000000 00002b24 2**0 + CONTENTS, READONLY + 37 .xtensa.info 00000038 00000000 00000000 00002b5f 2**0 + CONTENTS, READONLY + 38 .xt.lit 00000048 00000000 00000000 00002b97 2**0 + CONTENTS, RELOC, READONLY + 39 .xt.prop 00000468 00000000 00000000 00002bdf 2**0 + CONTENTS, RELOC, READONLY + +list.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 00000000 00000000 00000000 00000034 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .data 00000000 00000000 00000000 00000034 2**0 + CONTENTS, ALLOC, LOAD, DATA + 2 .bss 00000000 00000000 00000000 00000034 2**0 + ALLOC + 3 .text.vListInitialise 00000015 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 4 .text.vListInitialiseItem 00000009 00000000 00000000 0000004c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 5 .text.vListInsertEnd 0000001b 00000000 00000000 00000058 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 6 .text.vListInsert 0000002f 00000000 00000000 00000074 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .text.uxListRemove 00000026 00000000 00000000 000000a4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .debug_frame 00000088 00000000 00000000 000000cc 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 9 .debug_info 000002a1 00000000 00000000 00000154 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 10 .debug_abbrev 000000dc 00000000 00000000 000003f5 2**0 + CONTENTS, READONLY, DEBUGGING + 11 .debug_loc 00000081 00000000 00000000 000004d1 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 12 .debug_aranges 00000040 00000000 00000000 00000552 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 13 .debug_ranges 00000030 00000000 00000000 00000592 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 14 .debug_line 0000024c 00000000 00000000 000005c2 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 15 .debug_str 000002c2 00000000 00000000 0000080e 2**0 + CONTENTS, READONLY, DEBUGGING + 16 .comment 0000003b 00000000 00000000 00000ad0 2**0 + CONTENTS, READONLY + 17 .xtensa.info 00000038 00000000 00000000 00000b0b 2**0 + CONTENTS, READONLY + 18 .xt.prop 000000f0 00000000 00000000 00000b43 2**0 + CONTENTS, RELOC, READONLY + +port.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.pxPortInitialiseStack 00000018 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.xPortStartScheduler 00000014 00000000 00000000 0000004c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.xPortSysTickHandler 00000008 00000000 00000000 00000060 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .literal.vPortYieldOtherCore 00000004 00000000 00000000 00000068 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 4 .literal.vPortReleaseTaskMPUSettings 00000004 00000000 00000000 0000006c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .literal.xPortInIsrContext 00000008 00000000 00000000 00000070 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .iram1.literal 00000004 00000000 00000000 00000078 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .literal.vPortAssertIfInISR 00000018 00000000 00000000 0000007c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .literal.vPortCPUInitializeMutex 00000004 00000000 00000000 00000094 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 9 .literal.vPortCPUAcquireMutex 00000030 00000000 00000000 00000098 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 10 .literal.vPortCPUAcquireMutexTimeout 00000030 00000000 00000000 000000c8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 11 .literal.vPortCPUReleaseMutex 00000028 00000000 00000000 000000f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 12 .literal.vPortSetStackWatchpoint 00000008 00000000 00000000 00000120 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 13 .text 00000000 00000000 00000000 00000128 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 14 .data 00000000 00000000 00000000 00000128 2**0 + CONTENTS, ALLOC, LOAD, DATA + 15 .bss 00000000 00000000 00000000 00000128 2**0 + ALLOC + 16 .text.pxPortInitialiseStack 00000086 00000000 00000000 00000128 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 17 .text.vPortEndScheduler 00000005 00000000 00000000 000001b0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 18 .text.xPortStartScheduler 0000002e 00000000 00000000 000001b8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 19 .text.xPortSysTickHandler 00000016 00000000 00000000 000001e8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 20 .text.vPortYieldOtherCore 0000000e 00000000 00000000 00000200 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 21 .text.vPortStoreTaskMPUSettings 00000013 00000000 00000000 00000210 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 22 .text.vPortReleaseTaskMPUSettings 0000000e 00000000 00000000 00000224 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 23 .text.xPortInIsrContext 00000026 00000000 00000000 00000234 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 24 .iram1 0000001a 00000000 00000000 0000025c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 25 .rodata.str1.4 0000013b 00000000 00000000 00000278 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 26 .text.vPortAssertIfInISR 00000025 00000000 00000000 000003b4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 27 .text.vPortCPUInitializeMutex 0000000e 00000000 00000000 000003dc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 28 .text.vPortCPUAcquireMutex 00000088 00000000 00000000 000003ec 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 29 .text.vPortCPUAcquireMutexTimeout 000000ab 00000000 00000000 00000474 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 30 .text.vPortCPUReleaseMutex 00000061 00000000 00000000 00000520 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 31 .text.vPortSetStackWatchpoint 0000001a 00000000 00000000 00000584 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 32 .text.xPortGetTickRateHz 00000008 00000000 00000000 000005a0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 33 .rodata.__func__$5264 00000029 00000000 00000000 000005a8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 34 .rodata.__func__$5259 00000029 00000000 00000000 000005d4 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 35 .rodata.__FUNCTION__$5243 00000013 00000000 00000000 00000600 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 36 .bss.port_interruptNesting 00000008 00000000 00000000 00000614 2**2 + ALLOC + 37 .bss.port_xSchedulerRunning 00000008 00000000 00000000 00000614 2**2 + ALLOC + 38 .debug_frame 00000190 00000000 00000000 00000614 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 39 .debug_info 00000e78 00000000 00000000 000007a4 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 40 .debug_abbrev 00000404 00000000 00000000 0000161c 2**0 + CONTENTS, READONLY, DEBUGGING + 41 .debug_loc 000005f1 00000000 00000000 00001a20 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 42 .debug_aranges 00000098 00000000 00000000 00002011 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 43 .debug_ranges 000000a0 00000000 00000000 000020a9 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 44 .debug_line 000005fb 00000000 00000000 00002149 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 45 .debug_str 0000071f 00000000 00000000 00002744 2**0 + CONTENTS, READONLY, DEBUGGING + 46 .comment 0000003b 00000000 00000000 00002e63 2**0 + CONTENTS, READONLY + 47 .xtensa.info 00000038 00000000 00000000 00002e9e 2**0 + CONTENTS, READONLY + 48 .xt.lit 00000068 00000000 00000000 00002ed6 2**0 + CONTENTS, RELOC, READONLY + 49 .xt.prop 00000408 00000000 00000000 00002f3e 2**0 + CONTENTS, RELOC, READONLY + +portasm.S.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal 00000074 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .text 000001e0 00000000 00000000 000000a8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .data 00000c0c 00000000 00000000 00000290 2**4 + CONTENTS, ALLOC, LOAD, DATA + 3 .bss 00000000 00000000 00000000 00000e9c 2**0 + ALLOC + 4 .xtensa.info 00000038 00000000 00000000 00000e9c 2**0 + CONTENTS, READONLY + 5 .debug_line 00000432 00000000 00000000 00000ed4 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 6 .debug_info 00000093 00000000 00000000 00001306 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 7 .debug_abbrev 00000014 00000000 00000000 00001399 2**0 + CONTENTS, READONLY, DEBUGGING + 8 .debug_aranges 00000020 00000000 00000000 000013b0 2**3 + CONTENTS, RELOC, READONLY, DEBUGGING + 9 .xt.lit 00000008 00000000 00000000 000013d0 2**0 + CONTENTS, RELOC, READONLY + 10 .xt.prop 00000168 00000000 00000000 000013d8 2**0 + CONTENTS, RELOC, READONLY + +queue.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.prvIsQueueFull 00000008 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.prvCopyDataToQueue 0000000c 00000000 00000000 0000003c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.prvNotifyQueueSetContainer 0000002c 00000000 00000000 00000048 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .literal.prvCopyDataFromQueue 00000004 00000000 00000000 00000074 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 4 .literal.xQueueGenericReset 00000030 00000000 00000000 00000078 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .literal.prvInitialiseNewQueue 00000004 00000000 00000000 000000a8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .literal.xQueueGenericCreate 0000001c 00000000 00000000 000000ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .literal.xQueueGetMutexHolder 00000008 00000000 00000000 000000c8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .literal.xQueueCreateCountingSemaphore 00000028 00000000 00000000 000000d0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 9 .literal.xQueueGenericSend 0000007c 00000000 00000000 000000f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 10 .literal.prvInitialiseMutex 00000008 00000000 00000000 00000174 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 11 .literal.xQueueCreateMutex 00000008 00000000 00000000 0000017c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 12 .literal.xQueueGiveMutexRecursive 0000001c 00000000 00000000 00000184 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 13 .literal.xQueueGenericSendFromISR 0000003c 00000000 00000000 000001a0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 14 .literal.xQueueGiveFromISR 00000030 00000000 00000000 000001dc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 15 .literal.xQueueGenericReceive 00000078 00000000 00000000 0000020c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 16 .literal.xQueueTakeMutexRecursive 0000001c 00000000 00000000 00000284 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 17 .literal.xQueueReceiveFromISR 00000030 00000000 00000000 000002a0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 18 .literal.xQueuePeekFromISR 00000034 00000000 00000000 000002d0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 19 .literal.uxQueueMessagesWaiting 0000001c 00000000 00000000 00000304 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 20 .literal.uxQueueSpacesAvailable 0000001c 00000000 00000000 00000320 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 21 .literal.uxQueueMessagesWaitingFromISR 0000001c 00000000 00000000 0000033c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 22 .literal.vQueueDelete 00000018 00000000 00000000 00000358 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 23 .literal.xQueueIsQueueEmptyFromISR 0000001c 00000000 00000000 00000370 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 24 .literal.xQueueIsQueueFullFromISR 0000001c 00000000 00000000 0000038c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 25 .literal.vQueueWaitForMessageRestricted 0000000c 00000000 00000000 000003a8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 26 .literal.xQueueCreateSet 00000004 00000000 00000000 000003b4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 27 .literal.xQueueSelectFromSet 00000004 00000000 00000000 000003b8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 28 .literal.xQueueSelectFromSetFromISR 00000004 00000000 00000000 000003bc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 29 .text 00000000 00000000 00000000 000003c0 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 30 .data 00000000 00000000 00000000 000003c0 2**0 + CONTENTS, ALLOC, LOAD, DATA + 31 .bss 00000000 00000000 00000000 000003c0 2**0 + ALLOC + 32 .text.prvIsQueueEmpty 00000012 00000000 00000000 000003c0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 33 .text.prvIsQueueFull 0000002a 00000000 00000000 000003d4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 34 .text.prvCopyDataToQueue 0000009e 00000000 00000000 00000400 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 35 .rodata.str1.4 00000050 00000000 00000000 000004a0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 36 .text.prvNotifyQueueSetContainer 00000076 00000000 00000000 000004f0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 37 .text.prvCopyDataFromQueue 00000024 00000000 00000000 00000568 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 38 .text.xQueueGenericReset 00000096 00000000 00000000 0000058c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 39 .text.prvInitialiseNewQueue 00000023 00000000 00000000 00000624 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 40 .text.xQueueGenericCreate 0000004d 00000000 00000000 00000648 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 41 .text.xQueueGetMutexHolder 00000023 00000000 00000000 00000698 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 42 .text.xQueueCreateCountingSemaphore 0000006a 00000000 00000000 000006bc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 43 .text.xQueueGenericSend 0000018c 00000000 00000000 00000728 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 44 .text.prvInitialiseMutex 00000026 00000000 00000000 000008b4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 45 .text.xQueueCreateMutex 0000001a 00000000 00000000 000008dc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 46 .text.xQueueGiveMutexRecursive 0000004c 00000000 00000000 000008f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 47 .text.xQueueGenericSendFromISR 000000e6 00000000 00000000 00000944 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 48 .text.xQueueGiveFromISR 000000c2 00000000 00000000 00000a2c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 49 .text.xQueueGenericReceive 00000178 00000000 00000000 00000af0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 50 .text.xQueueTakeMutexRecursive 00000051 00000000 00000000 00000c68 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 51 .text.xQueueReceiveFromISR 000000a6 00000000 00000000 00000cbc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 52 .text.xQueuePeekFromISR 00000098 00000000 00000000 00000d64 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 53 .text.uxQueueMessagesWaiting 00000038 00000000 00000000 00000dfc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 54 .text.uxQueueSpacesAvailable 0000003e 00000000 00000000 00000e34 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 55 .text.uxQueueMessagesWaitingFromISR 00000038 00000000 00000000 00000e74 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 56 .text.vQueueDelete 00000028 00000000 00000000 00000eac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 57 .text.xQueueIsQueueEmptyFromISR 00000042 00000000 00000000 00000ed4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 58 .text.xQueueIsQueueFullFromISR 00000044 00000000 00000000 00000f18 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 59 .text.vQueueWaitForMessageRestricted 0000002a 00000000 00000000 00000f5c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 60 .text.xQueueCreateSet 00000014 00000000 00000000 00000f88 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 61 .text.xQueueAddToSet 0000001e 00000000 00000000 00000f9c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 62 .text.xQueueRemoveFromSet 00000020 00000000 00000000 00000fbc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 63 .text.xQueueSelectFromSet 00000018 00000000 00000000 00000fdc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 64 .text.xQueueSelectFromSetFromISR 00000015 00000000 00000000 00000ff4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 65 .rodata.__FUNCTION__$5459 00000019 00000000 00000000 0000100c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 66 .rodata.__FUNCTION__$5449 0000001a 00000000 00000000 00001028 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 67 .rodata.__FUNCTION__$5429 0000000d 00000000 00000000 00001044 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 68 .rodata.__FUNCTION__$5424 0000001e 00000000 00000000 00001054 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 69 .rodata.__FUNCTION__$5418 00000017 00000000 00000000 00001074 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 70 .rodata.__FUNCTION__$5412 00000017 00000000 00000000 0000108c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 71 .rodata.__FUNCTION__$5406 00000012 00000000 00000000 000010a4 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 72 .rodata.__FUNCTION__$5397 00000015 00000000 00000000 000010b8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 73 .rodata.__FUNCTION__$5387 00000015 00000000 00000000 000010d0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 74 .rodata.__FUNCTION__$5376 00000012 00000000 00000000 000010e8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 75 .rodata.__FUNCTION__$5368 00000019 00000000 00000000 000010fc 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 76 .rodata.__FUNCTION__$5495 0000001b 00000000 00000000 00001118 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 77 .rodata.__FUNCTION__$5357 00000012 00000000 00000000 00001134 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 78 .rodata.__FUNCTION__$5346 0000001e 00000000 00000000 00001148 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 79 .rodata.__FUNCTION__$5340 00000019 00000000 00000000 00001168 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 80 .rodata.__FUNCTION__$5333 00000019 00000000 00000000 00001184 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 81 .rodata.__FUNCTION__$5306 00000014 00000000 00000000 000011a0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 82 .rodata.__FUNCTION__$5297 00000013 00000000 00000000 000011b4 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 83 .debug_frame 00000310 00000000 00000000 000011c8 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 84 .debug_info 0000226e 00000000 00000000 000014d8 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 85 .debug_abbrev 00000247 00000000 00000000 00003746 2**0 + CONTENTS, READONLY, DEBUGGING + 86 .debug_loc 000010f0 00000000 00000000 0000398d 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 87 .debug_aranges 00000118 00000000 00000000 00004a7d 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 88 .debug_ranges 00000108 00000000 00000000 00004b95 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 89 .debug_line 00000e69 00000000 00000000 00004c9d 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 90 .debug_str 000009f1 00000000 00000000 00005b06 2**0 + CONTENTS, READONLY, DEBUGGING + 91 .comment 0000003b 00000000 00000000 000064f7 2**0 + CONTENTS, READONLY + 92 .xtensa.info 00000038 00000000 00000000 00006532 2**0 + CONTENTS, READONLY + 93 .xt.lit 000000e8 00000000 00000000 0000656a 2**0 + CONTENTS, RELOC, READONLY + 94 .xt.prop 00000e10 00000000 00000000 00006652 2**0 + CONTENTS, RELOC, READONLY + +ringbuf.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.returnItemToRingbufBytebuf 0000001c 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.returnItemToRingbufDefault 00000044 00000000 00000000 00000050 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.getItemFromRingbufDefault 00000024 00000000 00000000 00000094 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .literal.copyItemToRingbufNoSplit 00000024 00000000 00000000 000000b8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 4 .literal.copyItemToRingbufByteBuf 00000008 00000000 00000000 000000dc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .literal.copyItemToRingbufAllowSplit 00000034 00000000 00000000 000000e4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .literal.xRingbufferReceiveGeneric 00000020 00000000 00000000 00000118 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .literal.xRingbufferPrintInfo 00000020 00000000 00000000 00000138 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .literal.xRingbufferGetCurFreeSize 0000001c 00000000 00000000 00000158 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 9 .literal.xRingbufferCreate 00000064 00000000 00000000 00000174 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 10 .literal.xRingbufferCreateNoSplit 00000004 00000000 00000000 000001d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 11 .literal.vRingbufferDelete 00000010 00000000 00000000 000001dc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 12 .literal.xRingbufferGetMaxItemSize 00000014 00000000 00000000 000001ec 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 13 .literal.xRingbufferIsNextItemWrapped 00000014 00000000 00000000 00000200 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 14 .literal.xRingbufferSend 0000003c 00000000 00000000 00000214 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 15 .literal.xRingbufferSendFromISR 00000024 00000000 00000000 00000250 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 16 .literal.xRingbufferReceive 00000004 00000000 00000000 00000274 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 17 .literal.xRingbufferReceiveFromISR 0000001c 00000000 00000000 00000278 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 18 .literal.xRingbufferReceiveUpTo 00000020 00000000 00000000 00000294 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 19 .literal.xRingbufferReceiveUpToFromISR 00000024 00000000 00000000 000002b4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 20 .literal.vRingbufferReturnItem 0000000c 00000000 00000000 000002d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 21 .literal.vRingbufferReturnItemFromISR 0000000c 00000000 00000000 000002e4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 22 .literal.xRingbufferAddToQueueSetRead 00000018 00000000 00000000 000002f0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 23 .literal.xRingbufferAddToQueueSetWrite 00000018 00000000 00000000 00000308 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 24 .literal.xRingbufferRemoveFromQueueSetRead 00000018 00000000 00000000 00000320 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 25 .literal.xRingbufferRemoveFromQueueSetWrite 00000018 00000000 00000000 00000338 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 26 .text 00000000 00000000 00000000 00000350 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 27 .data 00000000 00000000 00000000 00000350 2**0 + CONTENTS, ALLOC, LOAD, DATA + 28 .bss 00000000 00000000 00000000 00000350 2**0 + ALLOC + 29 .text.ringbufferFreeMem 00000015 00000000 00000000 00000350 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 30 .text.getItemFromRingbufByteBuf 00000056 00000000 00000000 00000368 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 31 .text.getCurFreeSizeByteBuf 00000015 00000000 00000000 000003c0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 32 .text.getCurFreeSizeAllowSplit 00000030 00000000 00000000 000003d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 33 .text.getCurFreeSizeNoSplit 00000024 00000000 00000000 00000408 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 34 .rodata.str1.4 00000083 00000000 00000000 0000042c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 35 .text.returnItemToRingbufBytebuf 00000045 00000000 00000000 000004b0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 36 .text.returnItemToRingbufDefault 00000136 00000000 00000000 000004f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 37 .text.getItemFromRingbufDefault 000000a5 00000000 00000000 00000630 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 38 .text.copyItemToRingbufNoSplit 000000b0 00000000 00000000 000006d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 39 .text.copyItemToRingbufByteBuf 00000046 00000000 00000000 00000788 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 40 .text.copyItemToRingbufAllowSplit 00000124 00000000 00000000 000007d0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 41 .text.xRingbufferReceiveGeneric 00000070 00000000 00000000 000008f4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 42 .text.xRingbufferPrintInfo 00000046 00000000 00000000 00000964 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 43 .text.xRingbufferGetCurFreeSize 00000043 00000000 00000000 000009ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 44 .text.xRingbufferCreate 00000118 00000000 00000000 000009f0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 45 .text.xRingbufferCreateNoSplit 0000001c 00000000 00000000 00000b08 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 46 .text.vRingbufferDelete 0000002c 00000000 00000000 00000b24 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 47 .text.xRingbufferGetMaxItemSize 00000022 00000000 00000000 00000b50 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 48 .text.xRingbufferIsNextItemWrapped 00000030 00000000 00000000 00000b74 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 49 .text.xRingbufferSend 000000d4 00000000 00000000 00000ba4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 50 .text.xRingbufferSendFromISR 00000062 00000000 00000000 00000c78 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 51 .text.xRingbufferReceive 00000015 00000000 00000000 00000cdc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 52 .text.xRingbufferReceiveFromISR 00000040 00000000 00000000 00000cf4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 53 .text.xRingbufferReceiveUpTo 00000054 00000000 00000000 00000d34 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 54 .text.xRingbufferReceiveUpToFromISR 00000064 00000000 00000000 00000d88 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 55 .text.vRingbufferReturnItem 00000030 00000000 00000000 00000dec 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 56 .text.vRingbufferReturnItemFromISR 0000002c 00000000 00000000 00000e1c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 57 .text.xRingbufferAddToQueueSetRead 0000002c 00000000 00000000 00000e48 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 58 .text.xRingbufferAddToQueueSetWrite 0000002c 00000000 00000000 00000e74 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 59 .text.xRingbufferRemoveFromQueueSetRead 0000002c 00000000 00000000 00000ea0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 60 .text.xRingbufferRemoveFromQueueSetWrite 0000002c 00000000 00000000 00000ecc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 61 .rodata.__FUNCTION__$5577 00000023 00000000 00000000 00000ef8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 62 .rodata.__FUNCTION__$5571 00000022 00000000 00000000 00000f1c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 63 .rodata.__FUNCTION__$5565 0000001e 00000000 00000000 00000f40 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 64 .rodata.__FUNCTION__$5559 0000001d 00000000 00000000 00000f60 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 65 .rodata.__FUNCTION__$5542 0000001e 00000000 00000000 00000f80 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 66 .rodata.__FUNCTION__$5534 00000017 00000000 00000000 00000fa0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 67 .rodata.__FUNCTION__$5527 0000001a 00000000 00000000 00000fb8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 68 .rodata.__FUNCTION__$5508 0000001a 00000000 00000000 00000fd4 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 69 .rodata.__FUNCTION__$5497 00000017 00000000 00000000 00000ff0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 70 .rodata.__FUNCTION__$5482 00000010 00000000 00000000 00001008 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 71 .rodata.__FUNCTION__$5469 0000001d 00000000 00000000 00001018 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 72 .rodata.__FUNCTION__$5464 0000001a 00000000 00000000 00001038 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 73 .rodata.__FUNCTION__$5379 0000001c 00000000 00000000 00001054 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 74 .rodata.__FUNCTION__$5395 0000001a 00000000 00000000 00001070 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 75 .rodata.__FUNCTION__$5408 0000001b 00000000 00000000 0000108c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 76 .rodata.__FUNCTION__$5418 0000001b 00000000 00000000 000010a8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 77 .rodata.__FUNCTION__$5369 00000019 00000000 00000000 000010c4 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 78 .rodata.__FUNCTION__$5450 00000012 00000000 00000000 000010e0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 79 .rodata.__FUNCTION__$5428 0000001a 00000000 00000000 000010f4 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 80 .rodata.__FUNCTION__$5423 00000015 00000000 00000000 00001110 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 81 .debug_frame 000002f8 00000000 00000000 00001128 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 82 .debug_info 00001dc4 00000000 00000000 00001420 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 83 .debug_abbrev 000002c9 00000000 00000000 000031e4 2**0 + CONTENTS, READONLY, DEBUGGING + 84 .debug_loc 00000df4 00000000 00000000 000034ad 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 85 .debug_aranges 00000110 00000000 00000000 000042a1 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 86 .debug_ranges 00000130 00000000 00000000 000043b1 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 87 .debug_line 00000ce4 00000000 00000000 000044e1 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 88 .debug_str 000008b1 00000000 00000000 000051c5 2**0 + CONTENTS, READONLY, DEBUGGING + 89 .comment 0000003b 00000000 00000000 00005a76 2**0 + CONTENTS, READONLY + 90 .xtensa.info 00000038 00000000 00000000 00005ab1 2**0 + CONTENTS, READONLY + 91 .xt.lit 000000d0 00000000 00000000 00005ae9 2**0 + CONTENTS, RELOC, READONLY + 92 .xt.prop 00000bb8 00000000 00000000 00005bb9 2**0 + CONTENTS, RELOC, READONLY + +tasks.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.prvResetNextTaskUnblockTime 00000008 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.prvTaskGetSnapshotsFromList 00000004 00000000 00000000 0000003c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.prvDeleteTLS 00000018 00000000 00000000 00000040 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .literal.prvTaskIsTaskSuspended 0000001c 00000000 00000000 00000058 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 4 .literal.prvInitialiseNewTask 00000018 00000000 00000000 00000074 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .literal.prvInitialiseTaskLists 00000040 00000000 00000000 0000008c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .literal.prvDeleteTCB 0000002c 00000000 00000000 000000cc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .literal.prvAddCurrentTaskToDelayedList 0000001c 00000000 00000000 000000f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .literal.taskYIELD_OTHER_CORE 00000010 00000000 00000000 00000114 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 9 .literal.vTaskEndScheduler 00000008 00000000 00000000 00000124 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 10 .literal.vTaskSuspendAll 00000008 00000000 00000000 0000012c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 11 .literal.uxTaskGetNumberOfTasks 00000004 00000000 00000000 00000134 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 12 .literal.xTaskGetIdleTaskHandle 0000001c 00000000 00000000 00000138 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 13 .literal.xTaskGetIdleTaskHandleForCPU 0000001c 00000000 00000000 00000154 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 14 .literal.vTaskSwitchContext 0000003c 00000000 00000000 00000170 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 15 .literal.vTaskSetTimeOutState 00000020 00000000 00000000 000001ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 16 .literal.vTaskMissedYield 00000004 00000000 00000000 000001cc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 17 .literal.vTaskAllocateMPURegions 00000020 00000000 00000000 000001d0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 18 .literal.xTaskGetCurrentTaskHandle 00000008 00000000 00000000 000001f0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 19 .literal.__getreent 00000008 00000000 00000000 000001f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 20 .literal.pcTaskGetTaskName 0000001c 00000000 00000000 00000200 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 21 .literal.pvTaskGetThreadLocalStoragePointer 00000004 00000000 00000000 0000021c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 22 .literal.xTaskGetAffinity 00000004 00000000 00000000 00000220 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 23 .literal.uxTaskGetStackHighWaterMark 00000008 00000000 00000000 00000224 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 24 .literal.pxTaskGetStackStart 00000004 00000000 00000000 0000022c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 25 .literal.xTaskGetCurrentTaskHandleForCPU 00000004 00000000 00000000 00000230 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 26 .literal.xTaskGetSchedulerState 0000000c 00000000 00000000 00000234 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 27 .literal.vTaskEnterCritical 00000034 00000000 00000000 00000240 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 28 .literal.vTaskExitCritical 00000030 00000000 00000000 00000274 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 29 .literal.prvAddNewTaskToReadyList 00000058 00000000 00000000 000002a4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 30 .literal.xTaskCreateRestricted 00000028 00000000 00000000 000002fc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 31 .literal.xTaskCreatePinnedToCore 00000018 00000000 00000000 00000324 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 32 .literal.vTaskStartScheduler 00000038 00000000 00000000 0000033c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 33 .literal.vTaskDelete 00000060 00000000 00000000 00000374 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 34 .literal.vTaskDelayUntil 00000048 00000000 00000000 000003d4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 35 .literal.vTaskDelay 00000038 00000000 00000000 0000041c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 36 .literal.eTaskGetState 00000038 00000000 00000000 00000454 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 37 .literal.uxTaskPriorityGet 00000010 00000000 00000000 0000048c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 38 .literal.uxTaskPriorityGetFromISR 00000010 00000000 00000000 0000049c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 39 .literal.vTaskPrioritySet 00000044 00000000 00000000 000004ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 40 .literal.vTaskSuspend 00000060 00000000 00000000 000004f0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 41 .literal.vTaskResume 00000044 00000000 00000000 00000550 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 42 .literal.xTaskResumeFromISR 0000004c 00000000 00000000 00000594 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 43 .literal.prvCheckTasksWaitingTermination 00000030 00000000 00000000 000005e0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 44 .literal.prvIdleTask 00000008 00000000 00000000 00000610 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 45 .literal.xTaskGetTickCount 00000010 00000000 00000000 00000618 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 46 .literal.xTaskGetTickCountFromISR 00000010 00000000 00000000 00000628 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 47 .literal.xTaskIncrementTick 00000078 00000000 00000000 00000638 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 48 .literal.xTaskResumeAll 0000005c 00000000 00000000 000006b0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 49 .literal.vTaskPlaceOnEventList 00000040 00000000 00000000 0000070c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 50 .literal.vTaskPlaceOnUnorderedEventList 00000054 00000000 00000000 0000074c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 51 .literal.vTaskPlaceOnEventListRestricted 00000038 00000000 00000000 000007a0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 52 .literal.xTaskRemoveFromEventList 00000058 00000000 00000000 000007d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 53 .literal.xTaskRemoveFromUnorderedEventList 0000005c 00000000 00000000 00000830 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 54 .literal.xTaskCheckForTimeOut 0000003c 00000000 00000000 0000088c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 55 .literal.vTaskSetThreadLocalStoragePointerAndDelCallback 00000010 00000000 00000000 000008c8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 56 .literal.vTaskSetThreadLocalStoragePointer 00000004 00000000 00000000 000008d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 57 .literal.vTaskPriorityInherit 0000002c 00000000 00000000 000008dc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 58 .literal.xTaskPriorityDisinherit 00000040 00000000 00000000 00000908 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 59 .literal.uxTaskResetEventItemValue 00000010 00000000 00000000 00000948 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 60 .literal.pvTaskIncrementMutexHeldCount 00000010 00000000 00000000 00000958 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 61 .literal.ulTaskNotifyTake 00000030 00000000 00000000 00000968 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 62 .literal.xTaskNotifyWait 00000030 00000000 00000000 00000998 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 63 .literal.xTaskNotify 00000050 00000000 00000000 000009c8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 64 .literal.xTaskNotifyFromISR 00000058 00000000 00000000 00000a18 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 65 .literal.vTaskNotifyGiveFromISR 00000058 00000000 00000000 00000a70 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 66 .literal.uxTaskGetSnapshotAll 00000030 00000000 00000000 00000ac8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 67 .text 00000000 00000000 00000000 00000af8 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 68 .data 00000000 00000000 00000000 00000af8 2**0 + CONTENTS, ALLOC, LOAD, DATA + 69 .bss 00000000 00000000 00000000 00000af8 2**0 + ALLOC + 70 .text.prvTaskCheckFreeStackSpace 00000019 00000000 00000000 00000af8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 71 .text.prvResetNextTaskUnblockTime 00000034 00000000 00000000 00000b14 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 72 .text.prvTaskGetSnapshot 00000036 00000000 00000000 00000b48 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 73 .text.prvTaskGetSnapshotsFromList 00000047 00000000 00000000 00000b80 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 74 .rodata.str1.4 00000161 00000000 00000000 00000bc8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 75 .text.prvDeleteTLS 00000040 00000000 00000000 00000d2c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 76 .text.prvTaskIsTaskSuspended 0000004e 00000000 00000000 00000d6c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 77 .text.prvInitialiseNewTask 000000d0 00000000 00000000 00000dbc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 78 .text.prvInitialiseTaskLists 0000006e 00000000 00000000 00000e8c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 79 .text.prvDeleteTCB 0000005d 00000000 00000000 00000efc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 80 .text.prvAddCurrentTaskToDelayedList 0000006a 00000000 00000000 00000f5c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 81 .text.taskYIELD_OTHER_CORE 00000053 00000000 00000000 00000fc8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 82 .text.vTaskEndScheduler 00000018 00000000 00000000 0000101c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 83 .text.vTaskSuspendAll 00000026 00000000 00000000 00001034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 84 .text.uxTaskGetNumberOfTasks 0000000d 00000000 00000000 0000105c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 85 .text.xTaskGetIdleTaskHandle 0000003b 00000000 00000000 0000106c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 86 .text.xTaskGetIdleTaskHandleForCPU 0000002e 00000000 00000000 000010a8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 87 .text.vTaskSwitchContext 0000028a 00000000 00000000 000010d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 88 .text.vTaskSetTimeOutState 00000034 00000000 00000000 00001364 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 89 .text.vTaskMissedYield 00000018 00000000 00000000 00001398 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 90 .text.vTaskAllocateMPURegions 00000028 00000000 00000000 000013b0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 91 .text.xTaskGetCurrentTaskHandle 0000001f 00000000 00000000 000013d8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 92 .text.__getreent 00000019 00000000 00000000 000013f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 93 .text.pcTaskGetTaskName 0000002d 00000000 00000000 00001414 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 94 .text.pvTaskGetThreadLocalStoragePointer 0000001e 00000000 00000000 00001444 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 95 .text.xTaskGetAffinity 00000013 00000000 00000000 00001464 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 96 .text.uxTaskGetStackHighWaterMark 0000001a 00000000 00000000 00001478 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 97 .text.pxTaskGetStackStart 00000012 00000000 00000000 00001494 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 98 .text.xTaskGetCurrentTaskHandleForCPU 00000018 00000000 00000000 000014a8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 99 .text.xTaskGetSchedulerState 00000037 00000000 00000000 000014c0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +100 .text.vTaskEnterCritical 000000b3 00000000 00000000 000014f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +101 .text.vTaskExitCritical 0000008a 00000000 00000000 000015ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +102 .text.prvAddNewTaskToReadyList 00000173 00000000 00000000 00001638 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +103 .text.xTaskCreateRestricted 00000074 00000000 00000000 000017ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +104 .text.xTaskCreatePinnedToCore 00000076 00000000 00000000 00001820 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +105 .text.vTaskStartScheduler 00000072 00000000 00000000 00001898 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +106 .text.vTaskDelete 00000122 00000000 00000000 0000190c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +107 .text.vTaskDelayUntil 000000e7 00000000 00000000 00001a30 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +108 .text.vTaskDelay 00000080 00000000 00000000 00001b18 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +109 .text.eTaskGetState 000000aa 00000000 00000000 00001b98 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +110 .text.uxTaskPriorityGet 00000023 00000000 00000000 00001c44 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +111 .text.uxTaskPriorityGetFromISR 00000023 00000000 00000000 00001c68 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +112 .text.vTaskPrioritySet 00000143 00000000 00000000 00001c8c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +113 .text.vTaskSuspend 00000106 00000000 00000000 00001dd0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +114 .text.vTaskResume 000000d8 00000000 00000000 00001ed8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +115 .text.xTaskResumeFromISR 000000f6 00000000 00000000 00001fb0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +116 .text.prvCheckTasksWaitingTermination 000000c6 00000000 00000000 000020a8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +117 .text.prvIdleTask 00000012 00000000 00000000 00002170 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +118 .text.xTaskGetTickCount 00000020 00000000 00000000 00002184 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +119 .text.xTaskGetTickCountFromISR 00000020 00000000 00000000 000021a4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +120 .text.xTaskIncrementTick 000001ce 00000000 00000000 000021c4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +121 .text.xTaskResumeAll 00000186 00000000 00000000 00002394 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +122 .text.vTaskPlaceOnEventList 00000097 00000000 00000000 0000251c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +123 .text.vTaskPlaceOnUnorderedEventList 000000cf 00000000 00000000 000025b4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +124 .text.vTaskPlaceOnEventListRestricted 0000006f 00000000 00000000 00002684 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +125 .text.xTaskRemoveFromEventList 00000143 00000000 00000000 000026f4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +126 .text.xTaskRemoveFromUnorderedEventList 000000ff 00000000 00000000 00002838 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +127 .text.xTaskCheckForTimeOut 00000096 00000000 00000000 00002938 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +128 .text.vTaskSetThreadLocalStoragePointerAndDelCallback 0000002f 00000000 00000000 000029d0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +129 .text.vTaskSetThreadLocalStoragePointer 00000013 00000000 00000000 00002a00 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +130 .text.vTaskPriorityInherit 000000db 00000000 00000000 00002a14 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +131 .text.xTaskPriorityDisinherit 000000aa 00000000 00000000 00002af0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +132 .text.uxTaskResetEventItemValue 0000003e 00000000 00000000 00002b9c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +133 .text.pvTaskIncrementMutexHeldCount 00000054 00000000 00000000 00002bdc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +134 .text.ulTaskNotifyTake 0000012e 00000000 00000000 00002c30 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +135 .text.xTaskNotifyWait 00000156 00000000 00000000 00002d60 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +136 .text.xTaskNotify 0000014a 00000000 00000000 00002eb8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +137 .text.xTaskNotifyFromISR 00000172 00000000 00000000 00003004 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +138 .text.vTaskNotifyGiveFromISR 0000011c 00000000 00000000 00003178 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +139 .text.uxTaskGetSnapshotAll 0000009c 00000000 00000000 00003294 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE +140 .rodata.__FUNCTION__$5930 00000017 00000000 00000000 00003330 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +141 .rodata.__FUNCTION__$5917 00000013 00000000 00000000 00003348 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +142 .rodata.__FUNCTION__$5901 0000000c 00000000 00000000 0000335c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +143 .rodata.__func__$5851 00000029 00000000 00000000 00003368 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +144 .rodata.__func__$5846 00000029 00000000 00000000 00003394 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +145 .rodata.__FUNCTION__$5808 00000018 00000000 00000000 000033c0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +146 .rodata.__FUNCTION__$5718 00000018 00000000 00000000 000033d8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +147 .rodata.__FUNCTION__$5683 00000015 00000000 00000000 000033f0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +148 .rodata.__FUNCTION__$5677 00000015 00000000 00000000 00003408 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +149 .rodata.__FUNCTION__$5673 00000022 00000000 00000000 00003420 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +150 .rodata.__FUNCTION__$5663 00000019 00000000 00000000 00003444 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +151 .rodata.__FUNCTION__$5654 00000020 00000000 00000000 00003460 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +152 .rodata.__FUNCTION__$5648 0000001f 00000000 00000000 00003480 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +153 .rodata.__FUNCTION__$5641 00000016 00000000 00000000 000034a0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +154 .rodata.ucExpectedStackBytes$5613 00000014 00000000 00000000 000034b8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +155 .rodata.__FUNCTION__$5605 00000013 00000000 00000000 000034cc 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +156 .rodata.__FUNCTION__$5596 0000001d 00000000 00000000 000034e0 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +157 .rodata.__FUNCTION__$5591 00000017 00000000 00000000 00003500 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +158 .rodata.__FUNCTION__$5587 00000012 00000000 00000000 00003518 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +159 .rodata.__FUNCTION__$5565 0000000f 00000000 00000000 0000352c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +160 .rodata.__FUNCTION__$5547 00000014 00000000 00000000 0000353c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +161 .rodata.__FUNCTION__$5536 00000013 00000000 00000000 00003550 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +162 .rodata.__FUNCTION__$5525 00000017 00000000 00000000 00003564 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +163 .rodata.__FUNCTION__$5530 0000000c 00000000 00000000 0000357c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +164 .rodata.__FUNCTION__$5519 0000000d 00000000 00000000 00003588 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +165 .rodata.__FUNCTION__$5513 00000011 00000000 00000000 00003598 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +166 .rodata.__FUNCTION__$5494 0000000e 00000000 00000000 000035ac 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +167 .rodata.__FUNCTION__$5485 0000000b 00000000 00000000 000035bc 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +168 .rodata.__FUNCTION__$5478 00000010 00000000 00000000 000035c8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +169 .rodata.__FUNCTION__$5772 0000000d 00000000 00000000 000035d8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +170 .rodata.__FUNCTION__$5776 0000000d 00000000 00000000 000035e8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +171 .rodata.__FUNCTION__$5470 0000000c 00000000 00000000 000035f8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +172 .rodata.__FUNCTION__$5463 00000019 00000000 00000000 00003604 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +173 .rodata.__FUNCTION__$5421 00000016 00000000 00000000 00003620 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA +174 .bss.xSwitchingContext 00000008 00000000 00000000 00003638 2**2 + ALLOC +175 .data.xTickCountMutex 00000008 00000000 00000000 00003638 2**2 + CONTENTS, ALLOC, LOAD, DATA +176 .data.xTaskQueueMutex 00000008 00000000 00000000 00003640 2**2 + CONTENTS, ALLOC, LOAD, DATA +177 .bss.uxSchedulerSuspended 00000008 00000000 00000000 00003648 2**2 + ALLOC +178 .data.xNextTaskUnblockTime 00000004 00000000 00000000 00003648 2**2 + CONTENTS, ALLOC, LOAD, DATA +179 .bss.uxTaskNumber 00000004 00000000 00000000 0000364c 2**2 + ALLOC +180 .bss.xNumOfOverflows 00000004 00000000 00000000 0000364c 2**2 + ALLOC +181 .bss.xYieldPending 00000008 00000000 00000000 0000364c 2**2 + ALLOC +182 .bss.uxPendedTicks 00000004 00000000 00000000 0000364c 2**2 + ALLOC +183 .bss.xSchedulerRunning 00000004 00000000 00000000 0000364c 2**2 + ALLOC +184 .bss.uxTopReadyPriority 00000004 00000000 00000000 0000364c 2**2 + ALLOC +185 .bss.xTickCount 00000004 00000000 00000000 0000364c 2**2 + ALLOC +186 .bss.uxCurrentNumberOfTasks 00000004 00000000 00000000 0000364c 2**2 + ALLOC +187 .bss.xIdleTaskHandle 00000008 00000000 00000000 0000364c 2**2 + ALLOC +188 .bss.xSuspendedTaskList 00000014 00000000 00000000 0000364c 2**2 + ALLOC +189 .bss.uxTasksDeleted 00000004 00000000 00000000 0000364c 2**2 + ALLOC +190 .bss.xTasksWaitingTermination 00000014 00000000 00000000 0000364c 2**2 + ALLOC +191 .bss.xPendingReadyList 00000028 00000000 00000000 0000364c 2**2 + ALLOC +192 .bss.pxOverflowDelayedTaskList 00000004 00000000 00000000 0000364c 2**2 + ALLOC +193 .bss.pxDelayedTaskList 00000004 00000000 00000000 0000364c 2**2 + ALLOC +194 .bss.xDelayedTaskList2 00000014 00000000 00000000 0000364c 2**2 + ALLOC +195 .bss.xDelayedTaskList1 00000014 00000000 00000000 0000364c 2**2 + ALLOC +196 .bss.pxReadyTasksLists 000001f4 00000000 00000000 0000364c 2**2 + ALLOC +197 .bss.pxCurrentTCB 00000008 00000000 00000000 0000364c 2**2 + ALLOC +198 .debug_frame 00000688 00000000 00000000 0000364c 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING +199 .debug_info 00005e20 00000000 00000000 00003cd4 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING +200 .debug_abbrev 0000046f 00000000 00000000 00009af4 2**0 + CONTENTS, READONLY, DEBUGGING +201 .debug_loc 000022ef 00000000 00000000 00009f63 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING +202 .debug_aranges 00000240 00000000 00000000 0000c252 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING +203 .debug_ranges 000002c8 00000000 00000000 0000c492 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING +204 .debug_line 0000291c 00000000 00000000 0000c75a 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING +205 .debug_str 0000190d 00000000 00000000 0000f076 2**0 + CONTENTS, READONLY, DEBUGGING +206 .comment 0000003b 00000000 00000000 00010983 2**0 + CONTENTS, READONLY +207 .xtensa.info 00000038 00000000 00000000 000109be 2**0 + CONTENTS, READONLY +208 .xt.lit 00000218 00000000 00000000 000109f6 2**0 + CONTENTS, RELOC, READONLY +209 .xt.prop 00002154 00000000 00000000 00010c0e 2**0 + CONTENTS, RELOC, READONLY + +timers.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.prvGetNextExpireTime 00000004 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.prvInsertTimerInActiveList 00000010 00000000 00000000 00000038 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.prvCheckForValidListAndQueue 00000044 00000000 00000000 00000048 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .literal.prvInitialiseNewTimer 0000001c 00000000 00000000 0000008c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 4 .literal.xTimerCreateTimerTask 0000002c 00000000 00000000 000000a8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .literal.xTimerCreate 00000008 00000000 00000000 000000d4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .literal.xTimerGenericCommand 00000014 00000000 00000000 000000dc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .literal.prvSwitchTimerLists 00000028 00000000 00000000 000000f0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .literal.prvSampleTimeNow 0000000c 00000000 00000000 00000118 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 9 .literal.prvProcessExpiredTimer 00000024 00000000 00000000 00000124 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 10 .literal.prvProcessTimerOrBlockTask 00000024 00000000 00000000 00000148 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 11 .literal.prvProcessReceivedCommands 00000040 00000000 00000000 0000016c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 12 .literal.prvTimerTask 0000000c 00000000 00000000 000001ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 13 .literal.xTimerGetPeriod 00000014 00000000 00000000 000001b8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 14 .literal.xTimerGetExpiryTime 00000014 00000000 00000000 000001cc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 15 .literal.xTimerIsTimerActive 0000000c 00000000 00000000 000001e0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 16 .literal.vTimerSetTimerID 00000014 00000000 00000000 000001ec 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 17 .literal.xTimerPendFunctionCallFromISR 00000008 00000000 00000000 00000200 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 18 .literal.xTimerPendFunctionCall 0000001c 00000000 00000000 00000208 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 19 .text 00000000 00000000 00000000 00000224 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 20 .data 00000000 00000000 00000000 00000224 2**0 + CONTENTS, ALLOC, LOAD, DATA + 21 .bss 00000000 00000000 00000000 00000224 2**0 + ALLOC + 22 .text.prvGetNextExpireTime 00000020 00000000 00000000 00000224 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 23 .text.prvInsertTimerInActiveList 00000054 00000000 00000000 00000244 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 24 .rodata.str1.4 00000058 00000000 00000000 00000298 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 25 .text.prvCheckForValidListAndQueue 0000007e 00000000 00000000 000002f0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 26 .text.prvInitialiseNewTimer 0000003a 00000000 00000000 00000370 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 27 .text.xTimerCreateTimerTask 0000004c 00000000 00000000 000003ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 28 .text.xTimerCreate 00000026 00000000 00000000 000003f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 29 .text.xTimerGenericCommand 0000005d 00000000 00000000 00000420 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 30 .text.prvSwitchTimerLists 00000082 00000000 00000000 00000480 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 31 .text.prvSampleTimeNow 0000002f 00000000 00000000 00000504 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 32 .text.prvProcessExpiredTimer 0000005f 00000000 00000000 00000534 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 33 .text.prvProcessTimerOrBlockTask 0000006c 00000000 00000000 00000594 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 34 .text.prvProcessReceivedCommands 000000e6 00000000 00000000 00000600 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 35 .rodata.prvProcessReceivedCommands 00000028 00000000 00000000 000006e8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, DATA + 36 .text.prvTimerTask 0000001d 00000000 00000000 00000710 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 37 .text.xTimerGetPeriod 00000022 00000000 00000000 00000730 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 38 .text.xTimerGetExpiryTime 00000022 00000000 00000000 00000754 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 39 .text.pcTimerGetTimerName 00000007 00000000 00000000 00000778 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 40 .text.xTimerIsTimerActive 00000024 00000000 00000000 00000780 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 41 .text.pvTimerGetTimerID 00000007 00000000 00000000 000007a4 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 42 .text.vTimerSetTimerID 00000022 00000000 00000000 000007ac 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 43 .text.xTimerPendFunctionCallFromISR 00000022 00000000 00000000 000007d0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 44 .text.xTimerPendFunctionCall 0000003c 00000000 00000000 000007f4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 45 .rodata.__FUNCTION__$5352 00000017 00000000 00000000 00000830 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 46 .rodata.__FUNCTION__$5335 00000011 00000000 00000000 00000848 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 47 .rodata.__FUNCTION__$5240 00000014 00000000 00000000 0000085c 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 48 .rodata.__FUNCTION__$5234 00000010 00000000 00000000 00000870 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 49 .rodata.__FUNCTION__$5220 00000016 00000000 00000000 00000880 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 50 .rodata.__FUNCTION__$5320 0000001d 00000000 00000000 00000898 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 51 .rodata.__FUNCTION__$5289 0000001b 00000000 00000000 000008b8 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 52 .rodata.__FUNCTION__$5251 00000017 00000000 00000000 000008d4 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 53 .rodata.__FUNCTION__$5313 00000014 00000000 00000000 000008ec 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 54 .bss.xLastTime$5272 00000004 00000000 00000000 00000900 2**2 + ALLOC + 55 .rodata.__FUNCTION__$5203 00000016 00000000 00000000 00000900 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 56 .data.xTimerMux 00000008 00000000 00000000 00000918 2**2 + CONTENTS, ALLOC, LOAD, DATA + 57 .bss.xTimerQueue 00000004 00000000 00000000 00000920 2**2 + ALLOC + 58 .bss.pxOverflowTimerList 00000004 00000000 00000000 00000920 2**2 + ALLOC + 59 .bss.pxCurrentTimerList 00000004 00000000 00000000 00000920 2**2 + ALLOC + 60 .bss.xActiveTimerList2 00000014 00000000 00000000 00000920 2**2 + ALLOC + 61 .bss.xActiveTimerList1 00000014 00000000 00000000 00000920 2**2 + ALLOC + 62 .debug_frame 00000208 00000000 00000000 00000920 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 63 .debug_info 00001405 00000000 00000000 00000b28 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 64 .debug_abbrev 00000279 00000000 00000000 00001f2d 2**0 + CONTENTS, READONLY, DEBUGGING + 65 .debug_loc 0000062f 00000000 00000000 000021a6 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 66 .debug_aranges 000000c0 00000000 00000000 000027d5 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 67 .debug_ranges 000000b0 00000000 00000000 00002895 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 68 .debug_line 00000771 00000000 00000000 00002945 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 69 .debug_str 00000934 00000000 00000000 000030b6 2**0 + CONTENTS, READONLY, DEBUGGING + 70 .comment 0000003b 00000000 00000000 000039ea 2**0 + CONTENTS, READONLY + 71 .xtensa.info 00000038 00000000 00000000 00003a25 2**0 + CONTENTS, READONLY + 72 .xt.lit 00000098 00000000 00000000 00003a5d 2**0 + CONTENTS, RELOC, READONLY + 73 .xt.prop 00000714 00000000 00000000 00003af5 2**0 + CONTENTS, RELOC, READONLY + +xtensa_context.S.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal 00000024 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .text 0000013a 00000000 00000000 00000058 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .data 00000000 00000000 00000000 00000192 2**0 + CONTENTS, ALLOC, LOAD, DATA + 3 .bss 00000000 00000000 00000000 00000192 2**0 + ALLOC + 4 .xtensa.info 00000038 00000000 00000000 00000192 2**0 + CONTENTS, READONLY + 5 .debug_line 00000313 00000000 00000000 000001ca 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 6 .debug_info 0000009a 00000000 00000000 000004dd 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 7 .debug_abbrev 00000014 00000000 00000000 00000577 2**0 + CONTENTS, READONLY, DEBUGGING + 8 .debug_aranges 00000020 00000000 00000000 00000590 2**3 + CONTENTS, RELOC, READONLY, DEBUGGING + 9 .xt.lit 00000008 00000000 00000000 000005b0 2**0 + CONTENTS, RELOC, READONLY + 10 .xt.prop 000000e4 00000000 00000000 000005b8 2**0 + CONTENTS, RELOC, READONLY + +xtensa_init.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal._xt_tick_divisor_init 0000000c 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.xt_clock_freq 00000004 00000000 00000000 00000040 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .text 00000000 00000000 00000000 00000044 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 3 .data 00000000 00000000 00000000 00000044 2**0 + CONTENTS, ALLOC, LOAD, DATA + 4 .bss 00000000 00000000 00000000 00000044 2**0 + ALLOC + 5 .text._xt_tick_divisor_init 0000001f 00000000 00000000 00000044 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .text.xt_clock_freq 0000000d 00000000 00000000 00000064 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .bss._xt_tick_divisor 00000004 00000000 00000000 00000074 2**2 + ALLOC + 8 .debug_frame 00000040 00000000 00000000 00000074 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 9 .debug_info 000000d4 00000000 00000000 000000b4 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 10 .debug_abbrev 0000008b 00000000 00000000 00000188 2**0 + CONTENTS, READONLY, DEBUGGING + 11 .debug_aranges 00000028 00000000 00000000 00000213 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 12 .debug_ranges 00000018 00000000 00000000 0000023b 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 13 .debug_line 000000c8 00000000 00000000 00000253 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 14 .debug_str 00000180 00000000 00000000 0000031b 2**0 + CONTENTS, READONLY, DEBUGGING + 15 .comment 0000003b 00000000 00000000 0000049b 2**0 + CONTENTS, READONLY + 16 .xtensa.info 00000038 00000000 00000000 000004d6 2**0 + CONTENTS, READONLY + 17 .xt.lit 00000010 00000000 00000000 0000050e 2**0 + CONTENTS, RELOC, READONLY + 18 .xt.prop 0000006c 00000000 00000000 0000051e 2**0 + CONTENTS, RELOC, READONLY + +xtensa_intr.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.xt_unhandled_interrupt 00000008 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.xt_set_exception_handler 00000008 00000000 00000000 0000003c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.xt_set_interrupt_handler 0000000c 00000000 00000000 00000044 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .text 00000000 00000000 00000000 00000050 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 4 .data 00000000 00000000 00000000 00000050 2**0 + CONTENTS, ALLOC, LOAD, DATA + 5 .bss 00000000 00000000 00000000 00000050 2**0 + ALLOC + 6 .rodata.str1.4 00000023 00000000 00000000 00000050 2**2 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 7 .text.xt_unhandled_interrupt 00000016 00000000 00000000 00000074 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .text.xt_set_exception_handler 00000042 00000000 00000000 0000008c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 9 .text.xt_set_interrupt_handler 00000046 00000000 00000000 000000d0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 10 .debug_frame 00000058 00000000 00000000 00000118 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 11 .debug_info 0000042d 00000000 00000000 00000170 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 12 .debug_abbrev 000001b6 00000000 00000000 0000059d 2**0 + CONTENTS, READONLY, DEBUGGING + 13 .debug_loc 0000015c 00000000 00000000 00000753 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 14 .debug_aranges 00000030 00000000 00000000 000008af 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 15 .debug_ranges 00000020 00000000 00000000 000008df 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 16 .debug_line 000002b8 00000000 00000000 000008ff 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 17 .debug_str 000002a5 00000000 00000000 00000bb7 2**0 + CONTENTS, READONLY, DEBUGGING + 18 .comment 0000003b 00000000 00000000 00000e5c 2**0 + CONTENTS, READONLY + 19 .xtensa.info 00000038 00000000 00000000 00000e97 2**0 + CONTENTS, READONLY + 20 .xt.lit 00000018 00000000 00000000 00000ecf 2**0 + CONTENTS, RELOC, READONLY + 21 .xt.prop 00000120 00000000 00000000 00000ee7 2**0 + CONTENTS, RELOC, READONLY + +xtensa_intr_asm.S.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .text 00000033 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 1 .data 00000400 00000000 00000000 00000068 2**3 + CONTENTS, ALLOC, LOAD, RELOC, DATA + 2 .bss 00000000 00000000 00000000 00000468 2**0 + ALLOC + 3 .xtensa.info 00000038 00000000 00000000 00000468 2**0 + CONTENTS, READONLY + 4 .debug_line 000000da 00000000 00000000 000004a0 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 5 .debug_info 0000009b 00000000 00000000 0000057a 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 6 .debug_abbrev 00000014 00000000 00000000 00000615 2**0 + CONTENTS, READONLY, DEBUGGING + 7 .debug_aranges 00000020 00000000 00000000 00000630 2**3 + CONTENTS, RELOC, READONLY, DEBUGGING + 8 .xt.prop 00000054 00000000 00000000 00000650 2**0 + CONTENTS, RELOC, READONLY + +xtensa_overlay_os_hook.c.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .literal.xt_overlay_init_os 00000008 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .literal.xt_overlay_lock 00000008 00000000 00000000 0000003c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .literal.xt_overlay_unlock 00000008 00000000 00000000 00000044 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .text 00000000 00000000 00000000 0000004c 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 4 .data 00000000 00000000 00000000 0000004c 2**0 + CONTENTS, ALLOC, LOAD, DATA + 5 .bss 00000000 00000000 00000000 0000004c 2**0 + ALLOC + 6 .text.xt_overlay_init_os 00000013 00000000 00000000 0000004c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .text.xt_overlay_lock 00000016 00000000 00000000 00000060 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .text.xt_overlay_unlock 00000016 00000000 00000000 00000078 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 9 .bss.xt_overlay_mutex 00000004 00000000 00000000 00000090 2**2 + ALLOC + 10 .debug_frame 00000058 00000000 00000000 00000090 2**2 + CONTENTS, RELOC, READONLY, DEBUGGING + 11 .debug_info 00000193 00000000 00000000 000000e8 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 12 .debug_abbrev 0000008f 00000000 00000000 0000027b 2**0 + CONTENTS, READONLY, DEBUGGING + 13 .debug_aranges 00000030 00000000 00000000 0000030a 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 14 .debug_ranges 00000020 00000000 00000000 0000033a 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 15 .debug_line 00000192 00000000 00000000 0000035a 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 16 .debug_str 0000025c 00000000 00000000 000004ec 2**0 + CONTENTS, READONLY, DEBUGGING + 17 .comment 0000003b 00000000 00000000 00000748 2**0 + CONTENTS, READONLY + 18 .xtensa.info 00000038 00000000 00000000 00000783 2**0 + CONTENTS, READONLY + 19 .xt.lit 00000018 00000000 00000000 000007bb 2**0 + CONTENTS, RELOC, READONLY + 20 .xt.prop 0000009c 00000000 00000000 000007d3 2**0 + CONTENTS, RELOC, READONLY + +xtensa_vector_defaults.S.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .iram1.literal 00000004 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .text 00000000 00000000 00000000 00000038 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 2 .data 00000000 00000000 00000000 00000038 2**0 + CONTENTS, ALLOC, LOAD, DATA + 3 .bss 00000000 00000000 00000000 00000038 2**0 + ALLOC + 4 .iram1 00000032 00000000 00000000 00000038 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .xtensa.info 00000038 00000000 00000000 0000006a 2**0 + CONTENTS, READONLY + 6 .debug_line 000000c2 00000000 00000000 000000a2 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 7 .debug_info 000000a2 00000000 00000000 00000164 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 8 .debug_abbrev 00000014 00000000 00000000 00000206 2**0 + CONTENTS, READONLY, DEBUGGING + 9 .debug_aranges 00000020 00000000 00000000 00000220 2**3 + CONTENTS, RELOC, READONLY, DEBUGGING + 10 .xt.lit 00000008 00000000 00000000 00000240 2**0 + CONTENTS, RELOC, READONLY + 11 .xt.prop 00000078 00000000 00000000 00000248 2**0 + CONTENTS, RELOC, READONLY + +xtensa_vectors.S.obj: file format elf32-xtensa-le + +Sections: +Idx Name Size VMA LMA File off Algn + 0 .iram1.literal 000000a8 00000000 00000000 00000034 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 1 .DebugExceptionVector.literal 00000004 00000000 00000000 000000dc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 2 .DoubleExceptionVector.literal 00000004 00000000 00000000 000000e0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 3 .KernelExceptionVector.literal 00000004 00000000 00000000 000000e4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 4 .UserExceptionVector.literal 00000004 00000000 00000000 000000e8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 5 .Level2InterruptVector.literal 00000004 00000000 00000000 000000ec 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 6 .Level3InterruptVector.literal 00000004 00000000 00000000 000000f0 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 7 .Level4InterruptVector.literal 00000004 00000000 00000000 000000f4 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 8 .Level5InterruptVector.literal 00000004 00000000 00000000 000000f8 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 9 .NMIExceptionVector.literal 00000004 00000000 00000000 000000fc 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 10 .text 00000000 00000000 00000000 00000100 2**0 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 11 .data 00000008 00000000 00000000 00000100 2**4 + CONTENTS, ALLOC, LOAD, DATA + 12 .bss 00000000 00000000 00000000 00000108 2**0 + ALLOC + 13 .iram1 000004ec 00000000 00000000 00000108 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 14 .rodata 00000024 00000000 00000000 00000600 2**4 + CONTENTS, ALLOC, LOAD, READONLY, DATA + 15 .DebugExceptionVector.text 00000009 00000000 00000000 00000624 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 16 .DoubleExceptionVector.text 00000011 00000000 00000000 00000630 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 17 .KernelExceptionVector.text 00000009 00000000 00000000 00000644 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 18 .UserExceptionVector.text 00000009 00000000 00000000 00000650 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 19 .Level2InterruptVector.text 00000009 00000000 00000000 0000065c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 20 .Level3InterruptVector.text 00000009 00000000 00000000 00000668 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 21 .Level4InterruptVector.text 00000009 00000000 00000000 00000674 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 22 .Level5InterruptVector.text 00000009 00000000 00000000 00000680 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 23 .NMIExceptionVector.text 00000009 00000000 00000000 0000068c 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 24 .WindowVectors.text 0000016a 00000000 00000000 00000698 2**2 + CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE + 25 .UserEnter.text 00000000 00000000 00000000 00000804 2**2 + CONTENTS, ALLOC, LOAD, READONLY, CODE + 26 .xtensa.info 00000038 00000000 00000000 00000804 2**0 + CONTENTS, READONLY + 27 .debug_line 000009b8 00000000 00000000 0000083c 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 28 .debug_info 00000096 00000000 00000000 000011f4 2**0 + CONTENTS, RELOC, READONLY, DEBUGGING + 29 .debug_abbrev 00000012 00000000 00000000 0000128a 2**0 + CONTENTS, READONLY, DEBUGGING + 30 .debug_aranges 00000070 00000000 00000000 000012a0 2**3 + CONTENTS, RELOC, READONLY, DEBUGGING + 31 .debug_ranges 00000068 00000000 00000000 00001310 2**3 + CONTENTS, RELOC, READONLY, DEBUGGING + 32 .xt.lit 00000050 00000000 00000000 00001378 2**0 + CONTENTS, RELOC, READONLY + 33 .xt.prop 000004f8 00000000 00000000 000013c8 2**0 + CONTENTS, RELOC, READONLY diff --git a/tools/ldgen/test/data/template.ld b/tools/ldgen/test/data/template.ld new file mode 100644 index 0000000000..02a0d21cb9 --- /dev/null +++ b/tools/ldgen/test/data/template.ld @@ -0,0 +1,217 @@ +/* Default entry point: */ +ENTRY(call_start_cpu0); + +SECTIONS +{ + /* RTC fast memory holds RTC wake stub code, + including from any source file named rtc_wake_stub*.c + */ + .rtc.text : + { + . = ALIGN(4); + + mapping[rtc_text] + + *rtc_wake_stub*.o(.literal .text .literal.* .text.*) + } >rtc_iram_seg + + /* RTC slow memory holds RTC wake stub + data/rodata, including from any source file + named rtc_wake_stub*.c + */ + .rtc.data : + { + _rtc_data_start = ABSOLUTE(.); + + mapping[rtc_data] + + *rtc_wake_stub*.o(.data .rodata .data.* .rodata.* .bss .bss.*) + _rtc_data_end = ABSOLUTE(.); + } > rtc_slow_seg + + /* RTC bss, from any source file named rtc_wake_stub*.c */ + .rtc.bss (NOLOAD) : + { + _rtc_bss_start = ABSOLUTE(.); + + mapping[rtc_bss] + + *rtc_wake_stub*.o(.bss .bss.*) + *rtc_wake_stub*.o(COMMON) + _rtc_bss_end = ABSOLUTE(.); + } > rtc_slow_seg + + /* Send .iram0 code to iram */ + .iram0.vectors : + { + /* Vectors go to IRAM */ + _init_start = ABSOLUTE(.); + /* Vectors according to builds/RF-2015.2-win32/esp108_v1_2_s5_512int_2/config.html */ + . = 0x0; + KEEP(*(.WindowVectors.text)); + . = 0x180; + KEEP(*(.Level2InterruptVector.text)); + . = 0x1c0; + KEEP(*(.Level3InterruptVector.text)); + . = 0x200; + KEEP(*(.Level4InterruptVector.text)); + . = 0x240; + KEEP(*(.Level5InterruptVector.text)); + . = 0x280; + KEEP(*(.DebugExceptionVector.text)); + . = 0x2c0; + KEEP(*(.NMIExceptionVector.text)); + . = 0x300; + KEEP(*(.KernelExceptionVector.text)); + . = 0x340; + KEEP(*(.UserExceptionVector.text)); + . = 0x3C0; + KEEP(*(.DoubleExceptionVector.text)); + . = 0x400; + *(.*Vector.literal) + + *(.UserEnter.literal); + *(.UserEnter.text); + . = ALIGN (16); + *(.entry.text) + *(.init.literal) + *(.init) + _init_end = ABSOLUTE(.); + + /* This goes here, not at top of linker script, so addr2line finds it last, + and uses it in preference to the first symbol in IRAM */ + _iram_start = ABSOLUTE(0); + } > iram0_0_seg + + .iram0.text : + { + /* Code marked as runnning out of IRAM */ + _iram_text_start = ABSOLUTE(.); + + mapping[iram0_text] + + INCLUDE esp32.spiram.rom-functions-iram.ld + _iram_text_end = ABSOLUTE(.); + } > iram0_0_seg + + .dram0.data : + { + _data_start = ABSOLUTE(.); + + mapping[dram0_data] + + *(.gnu.linkonce.d.*) + *(.data1) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + *(.jcr) + INCLUDE esp32.spiram.rom-functions-dram.ld + _data_end = ABSOLUTE(.); + . = ALIGN(4); + } >dram0_0_seg + + /* Shared RAM */ + .dram0.bss (NOLOAD) : + { + . = ALIGN (8); + _bss_start = ABSOLUTE(.); + + mapping[dram0_bss] + + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) + *(.dynbss) + *(.share.mem) + *(.gnu.linkonce.b.*) + + . = ALIGN (8); + _bss_end = ABSOLUTE(.); + _heap_start = ABSOLUTE(.); + } >dram0_0_seg + + .flash.rodata : + { + _rodata_start = ABSOLUTE(.); + + mapping[flash_rodata] + + *(.irom1.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.gnu.linkonce.r.*) + *(.rodata1) + __XT_EXCEPTION_TABLE_ = ABSOLUTE(.); + *(.xt_except_table) + *(.gcc_except_table .gcc_except_table.*) + *(.gnu.linkonce.e.*) + *(.gnu.version_r) + . = (. + 3) & ~ 3; + __eh_frame = ABSOLUTE(.); + KEEP(*(.eh_frame)) + . = (. + 7) & ~ 3; + /* C++ constructor and destructor tables, properly ordered: */ + __init_array_start = ABSOLUTE(.); + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + __init_array_end = ABSOLUTE(.); + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + /* C++ exception handlers table: */ + __XT_EXCEPTION_DESCS_ = ABSOLUTE(.); + *(.xt_except_desc) + *(.gnu.linkonce.h.*) + __XT_EXCEPTION_DESCS_END__ = ABSOLUTE(.); + *(.xt_except_desc_end) + *(.dynamic) + *(.gnu.version_d) + _rodata_end = ABSOLUTE(.); + /* Literals are also RO data. */ + _lit4_start = ABSOLUTE(.); + *(*.lit4) + *(.lit4.*) + *(.gnu.linkonce.lit4.*) + _lit4_end = ABSOLUTE(.); + . = ALIGN(4); + _thread_local_start = ABSOLUTE(.); + *(.tdata) + *(.tdata.*) + *(.tbss) + *(.tbss.*) + _thread_local_end = ABSOLUTE(.); + . = ALIGN(4); + } >drom0_0_seg + + .flash.text : + { + _stext = .; + _text_start = ABSOLUTE(.); + + mapping[flash_text] + + *(.stub .gnu.warning .gnu.linkonce.literal.* .gnu.linkonce.t.*.literal .gnu.linkonce.t.*) + *(.irom0.text) /* catch stray ICACHE_RODATA_ATTR */ + *(.fini.literal) + *(.fini) + *(.gnu.version) + _text_end = ABSOLUTE(.); + _etext = .; + + /* Similar to _iram_start, this symbol goes here so it is + resolved by addr2line in preference to the first symbol in + the flash.text segment. + */ + _flash_cache_start = ABSOLUTE(0); + } >iram0_2_seg +} diff --git a/tools/ldgen/test/test_fragments.py b/tools/ldgen/test/test_fragments.py new file mode 100755 index 0000000000..084079d8f3 --- /dev/null +++ b/tools/ldgen/test/test_fragments.py @@ -0,0 +1,632 @@ +#!/usr/bin/env python +# +# Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import unittest +import sys +import os + +sys.path.append('../') +from fragments import * +from pyparsing import * +from sdkconfig import * + +class FragmentTest(unittest.TestCase): + + def parse(self, text): + self.parser.ignore("#" + restOfLine) + fragment = self.parser.parseString(text, parseAll=True) + return fragment[0] + +class SectionsTest(FragmentTest): + + def setUp(self): + self.parser = Sections.get_fragment_grammar() + + def test_valid_entries(self): + valid_entries = """ + [sections:test] + entries: + .section1 + .section2 + + # Section 3 should not exist + # section3 + .section4 + + # This is a comment + + .section5 + """ + + sections = self.parse(valid_entries) + + self.assertEqual("test", sections.name) + + entries = sections.entries + + expected = { + ".section1", + ".section2", + ".section4", + ".section5" + } + + self.assertEqual(set(entries), expected) + + def test_blank_entries(self): + blank_entries = """ + [sections:test] + entries: + """ + + with self.assertRaises(ParseException): + sections = self.parse(blank_entries) + + def test_invalid_names(self): + with_spaces = """ + [sections:invalid name 1] + entries: + """ + + begins_with_number = """ + [sections:2invalid_name] + entries: + """ + + with_special_character = """ + [sections:invalid_name~] + entries: + """ + + with self.assertRaises(ParseException): + sections = self.parse(with_spaces) + + with self.assertRaises(ParseException): + sections = self.parse(begins_with_number) + + with self.assertRaises(ParseException): + sections = self.parse(with_special_character) + + def test_non_existent_entries(self): + misspelled_entries_field = """ + [sections:test] + entrie: + .section1 + """ + + missing_entries_field = """ + [sections:test] + """ + + with self.assertRaises(ParseException): + sections = self.parse(misspelled_entries_field) + + with self.assertRaises(ParseException): + sections = self.parse(missing_entries_field) + + def test_duplicate_entries(self): + duplicate_entries = """ + [sections:test] + entries: + .section1 + .section3 + .section1 + .section1 + .section2 + .section3 + .section1 + """ + + sections = self.parse(duplicate_entries) + + entries = sections.entries + + expected = { + ".section1", + ".section2", + ".section3", + } + + self.assertEqual(set(entries), expected) + +class SchemeTest(FragmentTest): + + def setUp(self): + self.parser = Scheme.get_fragment_grammar() + + def test_valid_entries(self): + valid_entries = """ + [scheme:test] + entries: + sections1 -> target1 + sections2 -> target2 + """ + + scheme = self.parse(valid_entries) + + entries = scheme.entries + + expected = { + ("sections1", "target1"), + ("sections2", "target2") + } + + self.assertEqual(entries, expected) + + def test_duplicate_same_mapping(self): + duplicate_entries = """ + [scheme:duplicate_same_mapping] + entries: + sections1 -> target1 + sections2 -> target2 + sections1 -> target1 + """ + + scheme = self.parse(duplicate_entries) + + entries = scheme.entries + + expected = { + ("sections1", "target1"), + ("sections2", "target2") + } + + self.assertEqual(len(entries), 2) + self.assertEqual(entries, expected) + + def test_invalid_separator(self): + wrong_character = """ + [scheme:test] + entries: + sections1, target1 + """ + + single_word = """ + [scheme:test] + entries: + sections1 + """ + + with self.assertRaises(ParseException): + scheme = self.parse(wrong_character) + + with self.assertRaises(ParseException): + scheme = self.parse(single_word) + + def test_blank_entries(self): + blank_entries = """ + [scheme:test] + entries: + """ + + with self.assertRaises(ParseException): + sections = self.parse(blank_entries) + + def test_non_existent_entries(self): + misspelled_entries_field = """ + [scheme:test] + entrie: + section -> target + """ + + missing_entries_field = """ + [scheme:test] + """ + + with self.assertRaises(ParseException): + sections = self.parse(misspelled_entries_field) + + with self.assertRaises(ParseException): + sections = self.parse(missing_entries_field) + +class MappingTest(FragmentTest): + + def setUp(self): + self.parser = Mapping.get_fragment_grammar() + + def parse_expression(self, expression): + parser = SDKConfig.get_expression_grammar() + return parser.parseString(expression, parseAll=True) + + def test_valid_grammar(self): + valid_entries = """ + [mapping] + archive: lib.a + entries: + obj:symbol (noflash) + # Comments should not matter + obj (noflash) + # Nor should whitespace + obj : symbol_2 ( noflash ) + obj_2 ( noflash ) + * (noflash) + """ + + mapping = self.parse(valid_entries) + + self.assertEqual("lib.a", mapping.archive) + self.assertEqual("lib_a", mapping.name) + + entries = mapping.entries + + expected = [("default", { + ("obj", "symbol", "noflash"), + ("obj", None, "noflash"), + ("obj", "symbol_2", "noflash"), + ("obj_2", None, "noflash"), + ("*", None, "noflash") + } ) ] + + self.assertEqual(entries, expected) + + def test_invalid_grammar(self): + with_fragment_name = """ + [mapping:name] + archive: lib.a + entries: + obj:symbol (noflash) + """ + + missing_archive = """ + [mapping:name] + entries: + obj:symbol (noflash) + """ + + misspelled_archive = """ + [mapping:name] + archi: lib.a + entries: + obj:symbol (noflash) + """ + + missing_entries = """ + [mapping] + archive: lib.a + """ + + misspelled_entries = """ + [mapping] + archive: lib.a + entrie: + obj:symbol (noflash) + """ + + missing_symbols = """ + [mapping] + archive: lib.a + entries: + obj: (noflash) + """ + + missing_scheme_1 = """ + [mapping] + archive: lib.a + entries: + obj: () + """ + + missing_scheme_2 = """ + [mapping] + archive: lib.a + entries: + obj:symbol + """ + + missing_entity = """ + [mapping] + archive: lib.a + entries: + (noflash) + """ + + wilcard_symbol = """ + [mapping] + archive: lib.a + entries: + obj:* (noflash) + """ + + empty_object_with_symbol = """ + [mapping] + archive: lib.a + entries: + :symbol (noflash) + """ + + wildcard_object_with_symbol = """ + [mapping] + archive: lib.a + entries: + *:symbol (noflash) + """ + + empty_definition = """ + [mapping] + """ + + with self.assertRaises(ParseException): + sections = self.parse(with_fragment_name) + + with self.assertRaises(ParseException): + sections = self.parse(missing_archive) + + with self.assertRaises(ParseException): + sections = self.parse(misspelled_archive) + + with self.assertRaises(ParseException): + sections = self.parse(missing_entries) + + with self.assertRaises(ParseException): + sections = self.parse(misspelled_entries) + + with self.assertRaises(ParseException): + sections = self.parse(missing_symbols) + + with self.assertRaises(ParseException): + sections = self.parse(missing_scheme_1) + + with self.assertRaises(ParseException): + sections = self.parse(missing_scheme_2) + + with self.assertRaises(ParseException): + sections = self.parse(missing_entity) + + with self.assertRaises(ParseException): + sections = self.parse(wilcard_symbol) + + with self.assertRaises(ParseException): + sections = self.parse(empty_object_with_symbol) + + with self.assertRaises(ParseException): + sections = self.parse(wildcard_object_with_symbol) + + with self.assertRaises(ParseException): + sections = self.parse(empty_definition) + + def test_explicit_blank_default_w_others(self): + expl_blnk_w_oth = """ + [mapping] + archive: lib.a + entries: + : CONFIG_A = y + obj_a (noflash) + : default + """ + + mapping = self.parse(expl_blnk_w_oth) + + entries = mapping.entries + + expected = [ ( entries[0][0] , { + ("obj_a", None, "noflash"), + } ), + ("default", set() ) ] + + self.assertEqual(entries, expected) + + + def test_implicit_blank_default_w_others(self): + impl_blnk_w_oth = """ + [mapping] + archive: lib.a + entries: + : CONFIG_A = y + obj_a (noflash) + """ + + mapping = self.parse(impl_blnk_w_oth) + + entries = mapping.entries + + expected = [ ( entries[0][0] , { + ("obj_a", None, "noflash"), + } ), + ("default", set() ) ] + + self.assertEqual(entries, expected) + + def test_explicit_blank_default(self): + expl_blnk_def = """ + [mapping] + archive: lib.a + entries: + : default + """ + mapping = self.parse(expl_blnk_def) + entries = mapping.entries + expected = [ ("default", set() ) ] + + self.assertEqual(entries, expected) + + def test_implicit_blank_default(self): + impl_blnk_def = """ + [mapping] + archive: lib.a + entries: + : default + """ + mapping = self.parse(impl_blnk_def) + entries = mapping.entries + expected = [ ("default", set() ) ] + + self.assertEqual(entries, expected) + + def test_multiple_entries(self): + multiple_entries = """ + [mapping] + archive: lib.a + entries: + : CONFIG_A = y + obj_a1 (noflash) + obj_a2 (noflash) + : CONFIG_B = y + obj_b1 (noflash) + obj_b2 (noflash) + obj_b3 (noflash) + : CONFIG_C = y + obj_c1 (noflash) + """ + + mapping = self.parse(multiple_entries) + + entries = mapping.entries + + expected = [ ( entries[0][0] , { + ("obj_a1", None, "noflash"), + ("obj_a2", None, "noflash"), + } ), + ( entries[1][0] , { + ("obj_b1", None, "noflash"), + ("obj_b2", None, "noflash"), + ("obj_b3", None, "noflash"), + } ), + ( entries[2][0] , { + ("obj_c1", None, "noflash"), + } ), + ("default", set() ) ] + + self.assertEqual(entries, expected) + + def test_blank_entries(self): + blank_entries = """ + [mapping] + archive: lib.a + entries: + : CONFIG_A = y + obj_a (noflash) + : CONFIG_B = y + : CONFIG_C = y + obj_c (noflash) + : CONFIG_D = y + : CONFIG_E = y + : default + obj (noflash) + """ + + mapping = self.parse(blank_entries) + + entries = mapping.entries + + expected = [ ( entries[0][0] , { + ("obj_a", None, "noflash") + } ), + ( entries[1][0] , set()), + ( entries[2][0] , { + ("obj_c", None, "noflash") + } ), + ( entries[3][0] , set()), + ( entries[4][0] , set()), + ( "default" , { + ("obj", None, "noflash") + } ) ] + + self.assertEqual(entries, expected) + + def test_blank_first_condition(self): + blank_first_condition = """ + [mapping] + archive: lib.a + entries: + obj_a (noflash) + : CONFIG_B = y + obj_b (noflash) + """ + + with self.assertRaises(ParseException): + mapping = self.parse(blank_first_condition) + + + def test_nonlast_default(self): + nonlast_default_1 = """ + [mapping] + archive: lib.a + entries: + : default + obj_a (noflash) + : CONFIG_A = y + obj_A (noflash) + """ + + nonlast_default_2 = """ + [mapping] + archive: lib.a + entries: + : CONFIG_A = y + obj_A (noflash) + : default + obj_a (noflash) + : CONFIG_B = y + obj_B (noflash) + """ + + nonlast_default_3 = """ + [mapping] + archive: lib.a + entries: + : CONFIG_A = y + obj_A (noflash) + : + obj_a (noflash) + : CONFIG_B = y + obj_B (noflash) + """ + + with self.assertRaises(ParseException): + mapping = self.parse(nonlast_default_1) + + with self.assertRaises(ParseException): + mapping = self.parse(nonlast_default_2) + + with self.assertRaises(ParseException): + mapping = self.parse(nonlast_default_3) + + def test_duplicate_default(self): + duplicate_default_1 = """ + archive: lib.a + entries: + : CONFIG_A = y + obj_A (noflash) + : default + obj_a (noflash) + : CONFIG_B = y + obj_B (noflash) + : default + obj_a (noflash) + """ + + duplicate_default_2 = """ + archive: lib.a + entries: + : CONFIG_A = y + obj_A (noflash) + : CONFIG_B = y + obj_a (noflash) + : default + obj_B (noflash) + : + obj_a (noflash) + """ + + with self.assertRaises(ParseException): + mapping = self.parse(duplicate_default_1) + + with self.assertRaises(ParseException): + mapping = self.parse(duplicate_default_2) + +if __name__ =="__main__": + unittest.main() diff --git a/tools/ldgen/test/test_generation.py b/tools/ldgen/test/test_generation.py new file mode 100755 index 0000000000..3f64ce7096 --- /dev/null +++ b/tools/ldgen/test/test_generation.py @@ -0,0 +1,1099 @@ +#!/usr/bin/env python +# +# Copyright 2018-2019 Espressif Systems (Shanghai) PTE LTD +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import unittest +import sys +import os + +sys.path.append('../') +from generation import * +from pyparsing import * + +class GenerationModelTest(unittest.TestCase): + + def setUp(self): + self.model = GenerationModel() + self.sdkconfig = None + self.sections_info = None + self.script_model = None + + with open("data/Kconfig") as kconfig_file_obj: + with open("data/sdkconfig") as sdkconfig_file_obj: + self.sdkconfig = SDKConfig(kconfig_file_obj, sdkconfig_file_obj) + + with open("data/sample.lf") as fragment_file_obj: + fragment_file = FragmentFileModel(fragment_file_obj) + self.model.add_fragments_from_file(fragment_file) + + self.sections_info = SectionsInfo() + + with open("data/sections.info") as sections_info_file_obj: + self.sections_info.add_sections_info(sections_info_file_obj) + + with open("data/template.ld") as template_file_obj: + self.script_model = TemplateModel(template_file_obj) + + def _add_mapping(self, text): + parser = Mapping.get_fragment_grammar() + fragment = parser.parseString(text, parseAll=True) + self.model.mappings[fragment[0].name] = fragment[0] + + def _add_sections(self, text): + parser = Sections.get_fragment_grammar() + fragment = parser.parseString(text, parseAll=True) + self.model.sections[fragment[0].name] = fragment[0] + + def _add_scheme(self, text): + parser = Scheme.get_fragment_grammar() + fragment = parser.parseString(text, parseAll=True) + self.model.schemes[fragment[0].name] = fragment[0] + + def _write(self, expected, actual): + self.script_model.fill(expected, self.sdkconfig) + self.script_model.write(open("expected.ld", "w")) + + self.script_model.fill(actual, self.sdkconfig) + self.script_model.write(open("actual.ld", "w")) + + def _generate_default_rules(self): + rules = dict() + + # flash_text + placement_rules = list() + rule = PlacementRule(None, None, None, self.model.sections["text"].entries, "flash_text") + placement_rules.append(rule) + rules["flash_text"] = placement_rules + + # flash_rodata + placement_rules = list() + rule = PlacementRule(None, None, None, self.model.sections["rodata"].entries, "flash_rodata") + placement_rules.append(rule) + rules["flash_rodata"] = placement_rules + + # dram0_data + placement_rules = list() + rule = PlacementRule(None, None, None, self.model.sections["data"].entries + self.model.sections["dram"].entries, "dram0_data") + placement_rules.append(rule) + rules["dram0_data"] = placement_rules + + # dram0_bss + placement_rules = list() + rule = PlacementRule(None, None, None, self.model.sections["bss"].entries + self.model.sections["common"].entries, "dram0_bss") + placement_rules.append(rule) + rules["dram0_bss"] = placement_rules + + # iram0_text + placement_rules = list() + rule = PlacementRule(None, None, None, self.model.sections["iram"].entries, "iram0_text") + placement_rules.append(rule) + rules["iram0_text"] = placement_rules + + # rtc_text + placement_rules = list() + rule = PlacementRule(None, None, None, self.model.sections["rtc_text"].entries, "rtc_text") + placement_rules.append(rule) + rules["rtc_text"] = placement_rules + + # rtc_data + placement_rules = list() + rule = PlacementRule(None, None, None, self.model.sections["rtc_data"].entries + self.model.sections["rtc_rodata"].entries, "rtc_data") + placement_rules.append(rule) + rules["rtc_data"] = placement_rules + + # rtc_bss + placement_rules = list() + rule = PlacementRule(None, None, None, self.model.sections["rtc_bss"].entries, "rtc_bss") + placement_rules.append(rule) + rules["rtc_bss"] = placement_rules + + return rules + + def _compare_rules(self, expected, actual): + self.assertEqual(set(expected.keys()), set(actual.keys())) + + for (target, rules) in actual.items(): + + message = "target: " + target + + actual_target_rules = rules + expected_target_rules = expected[target] + + self.assertEqual(len(actual_target_rules), len(expected_target_rules)) + + for actual_target_rule in actual_target_rules: + self.assertTrue(actual_target_rule in expected_target_rules, message + str(actual_target_rule)) + + for expected_target_rule in expected_target_rules: + self.assertTrue(expected_target_rule in actual_target_rules, message + str(expected_target_rule)) + + def _get_default(self, target, rules): + return rules[target][0] + + def test_rule_generation_blank(self): + normal = """ + [mapping] + archive: libfreertos.a + entries: + """ + + self._add_mapping(normal) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + expected = self._generate_default_rules() + + self.assertEqual(expected, actual) + + def test_rule_generation_nominal_1(self): + normal = """ + [mapping] + archive: libfreertos.a + entries: + * (noflash) + """ + self._add_mapping(normal) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + + iram0_text_E1 = PlacementRule("libfreertos.a", "*", None, self.model.sections["text"].entries, "iram0_text") + dram0_data_E1 = PlacementRule("libfreertos.a", "*", None, self.model.sections["rodata"].entries, "dram0_data") + + # Add the exclusions + flash_text_default.add_exclusion(iram0_text_E1) + flash_rodata_default.add_exclusion(dram0_data_E1) + + # Add to the placement rules list + expected["iram0_text"].append(iram0_text_E1) + expected["dram0_data"].append(dram0_data_E1) + + self._compare_rules(expected, actual) + + def test_rule_generation_nominal_2(self): + normal = """ + [mapping] + archive: libfreertos.a + entries: + timers (rtc) + """ + + self._add_mapping(normal) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + dram0_data_default = self._get_default("dram0_data", expected) + dram0_bss_default = self._get_default("dram0_bss", expected) + + rtc_text_E1 = PlacementRule("libfreertos.a", "timers", None, self.model.sections["text"].entries, "rtc_text") + rtc_data_E1 = PlacementRule("libfreertos.a", "timers", None, self.model.sections["data"].entries + self.model.sections["rodata"].entries, "rtc_data") + rtc_bss_E1 = PlacementRule("libfreertos.a", "timers", None, self.model.sections["bss"].entries + self.model.sections["common"].entries, "rtc_bss") + + # Add the exclusions + flash_text_default.add_exclusion(rtc_text_E1) + flash_rodata_default.add_exclusion(rtc_data_E1) + dram0_data_default.add_exclusion(rtc_data_E1) + dram0_bss_default.add_exclusion(rtc_bss_E1) + + # Add the rules + expected["rtc_text"].append(rtc_text_E1) + expected["rtc_data"].append(rtc_data_E1) + expected["rtc_bss"].append(rtc_bss_E1) + + self._compare_rules(expected, actual) + + def test_rule_generation_nominal_3(self): + normal = """ + [mapping] + archive: libfreertos.a + entries: + timers (rtc) + * (noflash) + """ + + self._add_mapping(normal) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + dram0_data_default = self._get_default("dram0_data", expected) + dram0_bss_default = self._get_default("dram0_bss", expected) + + rtc_text_E1 = PlacementRule("libfreertos.a", "timers", None, self.model.sections["text"].entries, "rtc_text") + rtc_data_E1 = PlacementRule("libfreertos.a", "timers", None, self.model.sections["data"].entries + self.model.sections["rodata"].entries, "rtc_data") + rtc_bss_E1 = PlacementRule("libfreertos.a", "timers", None, self.model.sections["bss"].entries + self.model.sections["common"].entries, "rtc_bss") + + iram0_text_E2 = PlacementRule("libfreertos.a", "*", None, self.model.sections["text"].entries, "iram0_text") + dram0_data_E2 = PlacementRule("libfreertos.a", "*", None, self.model.sections["rodata"].entries, "dram0_data") + + # Add the exclusions + flash_text_default.add_exclusion(iram0_text_E2) + flash_rodata_default.add_exclusion(dram0_data_E2) + + dram0_data_default.add_exclusion(rtc_data_E1) + dram0_bss_default.add_exclusion(rtc_bss_E1) + + iram0_text_E2.add_exclusion(rtc_text_E1) + dram0_data_E2.add_exclusion(rtc_data_E1) + + # Add the rules + expected["iram0_text"].append(iram0_text_E2) + expected["dram0_data"].append(dram0_data_E2) + + expected["rtc_text"].append(rtc_text_E1) + expected["rtc_data"].append(rtc_data_E1) + expected["rtc_bss"].append(rtc_bss_E1) + + self._compare_rules(expected, actual) + + + def test_rule_generation_nominal_4(self): + normal = """ + [mapping] + archive: libfreertos.a + entries: + croutine (rtc) + event_groups (noflash) + timers (rtc) + """ + + self._add_mapping(normal) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + dram0_data_default = self._get_default("dram0_data", expected) + dram0_bss_default = self._get_default("dram0_bss", expected) + + rtc_text_E1 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["text"].entries, "rtc_text") + rtc_data_E1 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["data"].entries + self.model.sections["rodata"].entries, "rtc_data") + rtc_bss_E1 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["bss"].entries + self.model.sections["common"].entries, "rtc_bss") + + iram0_text_E2 = PlacementRule("libfreertos.a", "event_groups", None, self.model.sections["text"].entries, "iram0_text") + dram0_data_E2 = PlacementRule("libfreertos.a", "event_groups", None, self.model.sections["rodata"].entries, "dram0_data") + + rtc_text_E3 = PlacementRule("libfreertos.a", "timers", None, self.model.sections["text"].entries, "rtc_text") + rtc_data_E3 = PlacementRule("libfreertos.a", "timers", None, self.model.sections["data"].entries + self.model.sections["rodata"].entries, "rtc_data") + rtc_bss_E3 = PlacementRule("libfreertos.a", "timers", None, self.model.sections["bss"].entries + self.model.sections["common"].entries, "rtc_bss") + + # Add the exclusions + flash_text_default.add_exclusion(rtc_text_E3) + flash_rodata_default.add_exclusion(rtc_data_E3) + dram0_data_default.add_exclusion(rtc_data_E3) + dram0_bss_default.add_exclusion(rtc_bss_E3) + + flash_text_default.add_exclusion(iram0_text_E2) + flash_rodata_default.add_exclusion(dram0_data_E2) + + flash_text_default.add_exclusion(rtc_text_E1) + flash_rodata_default.add_exclusion(rtc_data_E1) + dram0_data_default.add_exclusion(rtc_data_E1) + dram0_bss_default.add_exclusion(rtc_bss_E1) + + # Add the rules + expected["rtc_text"].append(rtc_text_E3) + expected["rtc_data"].append(rtc_data_E3) + expected["rtc_bss"].append(rtc_bss_E3) + + expected["iram0_text"].append(iram0_text_E2) + expected["dram0_data"].append(dram0_data_E2) + + expected["rtc_text"].append(rtc_text_E1) + expected["rtc_data"].append(rtc_data_E1) + expected["rtc_bss"].append(rtc_bss_E1) + + self._compare_rules(expected, actual) + + def test_rule_generation_nominal_5(self): + normal = """ + [mapping] + archive: libfreertos.a + entries: + croutine (rtc) + event_groups (noflash) + timers (rtc) + * (noflash) + """ + + self._add_mapping(normal) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + dram0_data_default = self._get_default("dram0_data", expected) + dram0_bss_default = self._get_default("dram0_bss", expected) + + rtc_text_E1 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["text"].entries, "rtc_text") + rtc_data_E1 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["data"].entries + self.model.sections["rodata"].entries, "rtc_data") + rtc_bss_E1 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["bss"].entries + self.model.sections["common"].entries, "rtc_bss") + + iram0_text_E2 = PlacementRule("libfreertos.a", "event_groups", None, self.model.sections["text"].entries, "iram0_text") + dram0_data_E2 = PlacementRule("libfreertos.a", "event_groups", None, self.model.sections["rodata"].entries, "dram0_data") + + rtc_text_E3 = PlacementRule("libfreertos.a", "timers", None, self.model.sections["text"].entries, "rtc_text") + rtc_data_E3 = PlacementRule("libfreertos.a", "timers", None, self.model.sections["data"].entries + self.model.sections["rodata"].entries, "rtc_data") + rtc_bss_E3 = PlacementRule("libfreertos.a", "timers", None, self.model.sections["bss"].entries + self.model.sections["common"].entries, "rtc_bss") + + iram0_text_E4 = PlacementRule("libfreertos.a", "*", None, self.model.sections["text"].entries, "iram0_text") + dram0_data_E4 = PlacementRule("libfreertos.a", "*", None, self.model.sections["rodata"].entries, "dram0_data") + + # Add the exclusions + flash_text_default.add_exclusion(iram0_text_E4) + flash_rodata_default.add_exclusion(dram0_data_E4) + + iram0_text_E4.add_exclusion(rtc_text_E3) + dram0_data_E4.add_exclusion(rtc_data_E3) + dram0_data_default.add_exclusion(rtc_data_E3) + dram0_bss_default.add_exclusion(rtc_bss_E3) + + iram0_text_E4.add_exclusion(iram0_text_E2) + dram0_data_E4.add_exclusion(dram0_data_E2) + + iram0_text_E4.add_exclusion(rtc_text_E1) + dram0_data_E4.add_exclusion(rtc_data_E1) + dram0_data_default.add_exclusion(rtc_data_E1) + dram0_bss_default.add_exclusion(rtc_bss_E1) + + # Add the rules + expected["iram0_text"].append(iram0_text_E4) + expected["dram0_data"].append(dram0_data_E4) + + expected["rtc_text"].append(rtc_text_E3) + expected["rtc_data"].append(rtc_data_E3) + expected["rtc_bss"].append(rtc_bss_E3) + + expected["iram0_text"].append(iram0_text_E2) + expected["dram0_data"].append(dram0_data_E2) + + expected["rtc_text"].append(rtc_text_E1) + expected["rtc_data"].append(rtc_data_E1) + expected["rtc_bss"].append(rtc_bss_E1) + + self._compare_rules(expected, actual) + + def test_rule_generation_nominal_6(self): + normal = """ + [mapping] + archive: libfreertos.a + entries: + croutine:prvCheckPendingReadyList (noflash) + """ + + self._add_mapping(normal) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + + iram0_text_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckPendingReadyList", self.model.sections["text"].entries, "iram0_text") + dram0_data_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckPendingReadyList", self.model.sections["rodata"].entries, "dram0_data") + + iram0_text_E1_extra = PlacementRule("libfreertos.a", "croutine", None, [".text.*", ".literal.*"], "flash_text") + dram0_data_E1_extra = PlacementRule("libfreertos.a", "croutine", None, [".rodata.*"], "flash_rodata") + + # Add the exclusions + flash_text_default.add_exclusion(iram0_text_E1_extra, self.sections_info) + flash_rodata_default.add_exclusion(dram0_data_E1_extra, self.sections_info) + + iram0_text_E1_extra.add_exclusion(iram0_text_E1, self.sections_info) + dram0_data_E1_extra.add_exclusion(dram0_data_E1, self.sections_info) + + # Add the rules + expected["flash_text"].append(iram0_text_E1_extra) + expected["flash_rodata"].append(dram0_data_E1_extra) + + expected["iram0_text"].append(iram0_text_E1) + expected["dram0_data"].append(dram0_data_E1) + + self._compare_rules(expected, actual) + + def test_rule_generation_nominal_7(self): + normal = """ + [mapping] + archive: libfreertos.a + entries: + croutine:prvCheckPendingReadyList (noflash) + croutine:prvCheckDelayedList (noflash) + croutine:xCoRoutineCreate (noflash) + """ + + self._add_mapping(normal) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + + iram0_text_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckPendingReadyList", self.model.sections["text"].entries, "iram0_text") + dram0_data_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckPendingReadyList", self.model.sections["rodata"].entries, "dram0_data") + + iram0_text_E2 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["text"].entries, "iram0_text") + dram0_data_E2 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["rodata"].entries, "dram0_data") + + iram0_text_E3 = PlacementRule("libfreertos.a", "croutine", "xCoRoutineCreate", self.model.sections["text"].entries, "iram0_text") + dram0_data_E3 = PlacementRule("libfreertos.a", "croutine", "xCoRoutineCreate", self.model.sections["rodata"].entries, "dram0_data") + + flash_text_extra = PlacementRule("libfreertos.a", "croutine", None, [".text.*", ".literal.*"], "flash_text") + flash_rodata_extra = PlacementRule("libfreertos.a", "croutine", None, [".rodata.*"], "flash_rodata") + + # Add the exclusions + flash_text_default.add_exclusion(flash_text_extra, self.sections_info) + flash_rodata_default.add_exclusion(flash_rodata_extra, self.sections_info) + + flash_text_extra.add_exclusion(iram0_text_E1, self.sections_info) + flash_rodata_extra.add_exclusion(dram0_data_E1, self.sections_info) + + flash_text_extra.add_exclusion(iram0_text_E2, self.sections_info) + flash_rodata_extra.add_exclusion(dram0_data_E2, self.sections_info) + + flash_text_extra.add_exclusion(iram0_text_E3, self.sections_info) + flash_rodata_extra.add_exclusion(dram0_data_E3, self.sections_info) + + # Add the rules + expected["flash_text"].append(flash_text_extra) + expected["flash_rodata"].append(flash_rodata_extra) + + expected["iram0_text"].append(iram0_text_E1) + expected["dram0_data"].append(dram0_data_E1) + + expected["iram0_text"].append(iram0_text_E2) + expected["dram0_data"].append(dram0_data_E2) + + expected["iram0_text"].append(iram0_text_E3) + expected["dram0_data"].append(dram0_data_E3) + + self._compare_rules(expected, actual) + + def test_rule_generation_nominal_8(self): + normal = """ + [mapping] + archive: libfreertos.a + entries: + croutine:prvCheckPendingReadyList (noflash) + croutine:prvCheckDelayedList (rtc) + croutine:xCoRoutineCreate (noflash) + """ + + self._add_mapping(normal) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + dram0_data_default = self._get_default("dram0_data", expected) + dram0_bss_default = self._get_default("dram0_bss", expected) + + iram0_text_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckPendingReadyList", self.model.sections["text"].entries, "iram0_text") + dram0_data_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckPendingReadyList", self.model.sections["rodata"].entries, "dram0_data") + + rtc_text_E2 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["text"].entries, "rtc_text") + rtc_data_E2 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["data"].entries + self.model.sections["rodata"].entries, "rtc_data") + rtc_bss_E2 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["bss"].entries + self.model.sections["common"].entries, "rtc_bss") + + iram0_text_E3 = PlacementRule("libfreertos.a", "croutine", "xCoRoutineCreate", self.model.sections["text"].entries, "iram0_text") + dram0_data_E3 = PlacementRule("libfreertos.a", "croutine", "xCoRoutineCreate", self.model.sections["rodata"].entries, "dram0_data") + + flash_text_extra = PlacementRule("libfreertos.a", "croutine", None, [".text.*", ".literal.*"], "flash_text") + flash_rodata_extra = PlacementRule("libfreertos.a", "croutine", None, [".rodata.*"], "flash_rodata") + dram0_data_extra = PlacementRule("libfreertos.a", "croutine", None, [".data.*"], "dram0_data") + dram0_bss_extra = PlacementRule("libfreertos.a", "croutine", None, [".bss.*"], "dram0_bss") + + # Add the exclusions + flash_text_default.add_exclusion(flash_text_extra, self.sections_info) + flash_rodata_default.add_exclusion(flash_rodata_extra, self.sections_info) + dram0_data_default.add_exclusion(dram0_data_extra, self.sections_info) + dram0_bss_default.add_exclusion(dram0_bss_extra, self.sections_info) + + flash_text_extra.add_exclusion(iram0_text_E1, self.sections_info) + flash_rodata_extra.add_exclusion(dram0_data_E1, self.sections_info) + + flash_text_extra.add_exclusion(rtc_text_E2, self.sections_info) + dram0_data_extra.add_exclusion(rtc_data_E2, self.sections_info) + flash_rodata_extra.add_exclusion(rtc_data_E2, self.sections_info) + dram0_bss_extra.add_exclusion(rtc_bss_E2, self.sections_info) + + flash_text_extra.add_exclusion(iram0_text_E3, self.sections_info) + flash_rodata_extra.add_exclusion(dram0_data_E3, self.sections_info) + + # Add the rules + expected["flash_text"].append(flash_text_extra) + expected["flash_rodata"].append(flash_rodata_extra) + expected["dram0_data"].append(dram0_data_extra) + expected["dram0_bss"].append(dram0_bss_extra) + + expected["iram0_text"].append(iram0_text_E1) + expected["dram0_data"].append(dram0_data_E1) + + expected["rtc_text"].append(rtc_text_E2) + expected["rtc_data"].append(rtc_data_E2) + expected["rtc_bss"].append(rtc_bss_E2) + + expected["iram0_text"].append(iram0_text_E3) + expected["dram0_data"].append(dram0_data_E3) + + self._compare_rules(expected, actual) + + def test_rule_generation_nominal_9(self): + normal = """ + [mapping] + archive: libfreertos.a + entries: + croutine:prvCheckDelayedList (rtc) + croutine (noflash) + """ + + self._add_mapping(normal) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + dram0_data_default = self._get_default("dram0_data", expected) + dram0_bss_default = self._get_default("dram0_bss", expected) + + rtc_text_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["text"].entries, "rtc_text") + rtc_data_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["data"].entries + self.model.sections["rodata"].entries, "rtc_data") + rtc_bss_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["bss"].entries + self.model.sections["common"].entries, "rtc_bss") + + iram0_text_E2 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["text"].entries, "iram0_text") + dram0_data_E2 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["rodata"].entries, "dram0_data") + + dram0_data_extra = PlacementRule("libfreertos.a", "croutine", None, [".data.*"], "dram0_data") + dram0_bss_extra = PlacementRule("libfreertos.a", "croutine", None, [".bss.*"], "dram0_bss") + + # Add the exclusions + flash_text_default.add_exclusion(iram0_text_E2, self.sections_info) + flash_rodata_default.add_exclusion(dram0_data_E2, self.sections_info) + + dram0_data_default.add_exclusion(dram0_data_extra, self.sections_info) + dram0_bss_default.add_exclusion(dram0_bss_extra, self.sections_info) + + dram0_data_extra.add_exclusion(rtc_data_E1, self.sections_info) + dram0_bss_extra.add_exclusion(rtc_bss_E1, self.sections_info) + + iram0_text_E2.add_exclusion(rtc_text_E1, self.sections_info) + dram0_data_E2.add_exclusion(rtc_data_E1, self.sections_info) + + # Add the rules + expected["dram0_data"].append(dram0_data_extra) + expected["dram0_bss"].append(dram0_bss_extra) + + expected["iram0_text"].append(iram0_text_E2) + expected["dram0_data"].append(dram0_data_E2) + + expected["rtc_text"].append(rtc_text_E1) + expected["rtc_data"].append(rtc_data_E1) + expected["rtc_bss"].append(rtc_bss_E1) + + self._compare_rules(expected, actual) + + def test_rule_generation_nominal_10(self): + normal = """ + [mapping] + archive: libfreertos.a + entries: + croutine:prvCheckDelayedList (rtc) + * (noflash) + """ + + self._add_mapping(normal) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + iram0_text_default = self._get_default("iram0_text", expected) + dram0_data_default = self._get_default("dram0_data", expected) + dram0_bss_default = self._get_default("dram0_bss", expected) + + rtc_text_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["text"].entries, "rtc_text") + rtc_data_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["data"].entries + self.model.sections["rodata"].entries, "rtc_data") + rtc_bss_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["bss"].entries + self.model.sections["common"].entries, "rtc_bss") + + iram0_text_E2 = PlacementRule("libfreertos.a", None, None, self.model.sections["text"].entries, "iram0_text") + dram0_data_E2 = PlacementRule("libfreertos.a", None, None, self.model.sections["rodata"].entries, "dram0_data") + + iram0_text_extra = PlacementRule("libfreertos.a", "croutine", None, [".text.*", ".literal.*"], "iram0_text") + dram0_data_extra = PlacementRule("libfreertos.a", "croutine", None, [".data.*", ".rodata.*"], "dram0_data") + dram0_bss_extra = PlacementRule("libfreertos.a", "croutine", None, [".bss.*"], "dram0_bss") + + # Add the exclusions + flash_text_default.add_exclusion(iram0_text_E2, self.sections_info) + flash_rodata_default.add_exclusion(dram0_data_E2, self.sections_info) + + iram0_text_default.add_exclusion(iram0_text_extra, self.sections_info) + dram0_data_default.add_exclusion(dram0_data_extra, self.sections_info) + dram0_bss_default.add_exclusion(dram0_bss_extra, self.sections_info) + + iram0_text_E2.add_exclusion(iram0_text_extra, self.sections_info) + dram0_data_E2.add_exclusion(dram0_data_extra, self.sections_info) + + iram0_text_extra.add_exclusion(rtc_text_E1, self.sections_info) + dram0_data_extra.add_exclusion(rtc_data_E1, self.sections_info) + dram0_bss_extra.add_exclusion(rtc_bss_E1, self.sections_info) + + # Add the rules + expected["iram0_text"].append(iram0_text_extra) + expected["dram0_data"].append(dram0_data_extra) + expected["dram0_bss"].append(dram0_bss_extra) + + expected["iram0_text"].append(iram0_text_E2) + expected["dram0_data"].append(dram0_data_E2) + + expected["rtc_text"].append(rtc_text_E1) + expected["rtc_data"].append(rtc_data_E1) + expected["rtc_bss"].append(rtc_bss_E1) + + self._compare_rules(expected, actual) + + def test_rule_generation_nominal_11(self): + normal = """ + [mapping] + archive: libfreertos.a + entries: + croutine:prvCheckDelayedList (noflash) + croutine (rtc) + * (noflash) + """ + + self._add_mapping(normal) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + iram0_text_default = self._get_default("iram0_text", expected) + dram0_data_default = self._get_default("dram0_data", expected) + dram0_bss_default = self._get_default("dram0_bss", expected) + + iram0_text_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["text"].entries, "iram0_text") + dram0_data_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["rodata"].entries, "dram0_data") + + rtc_text_E2 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["text"].entries, "rtc_text") + rtc_data_E2 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["data"].entries + self.model.sections["rodata"].entries, "rtc_data") + rtc_bss_E2 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["bss"].entries + self.model.sections["common"].entries, "rtc_bss") + + iram0_text_E3 = PlacementRule("libfreertos.a", None, None, self.model.sections["text"].entries, "iram0_text") + dram0_data_E3 = PlacementRule("libfreertos.a", None, None, self.model.sections["rodata"].entries, "dram0_data") + + # Add the exclusions + flash_text_default.add_exclusion(iram0_text_E3, self.sections_info) + flash_rodata_default.add_exclusion(dram0_data_E3, self.sections_info) + iram0_text_default.add_exclusion(rtc_text_E2, self.sections_info) + dram0_data_default.add_exclusion(rtc_data_E2, self.sections_info) + dram0_bss_default.add_exclusion(rtc_bss_E2, self.sections_info) + + iram0_text_E3.add_exclusion(rtc_text_E2, self.sections_info) + dram0_data_E3.add_exclusion(rtc_data_E2, self.sections_info) + + rtc_text_E2.add_exclusion(iram0_text_E1, self.sections_info) + rtc_data_E2.add_exclusion(dram0_data_E1, self.sections_info) + + # Add the rules + expected["iram0_text"].append(iram0_text_E1) + expected["dram0_data"].append(dram0_data_E1) + + expected["rtc_text"].append(rtc_text_E2) + expected["rtc_data"].append(rtc_data_E2) + expected["rtc_bss"].append(rtc_bss_E2) + + expected["iram0_text"].append(iram0_text_E3) + expected["dram0_data"].append(dram0_data_E3) + + self._compare_rules(expected, actual) + + def test_rule_generation_nominal_12(self): + normal = """ + [mapping] + archive: libfreertos.a + entries: + croutine:prvCheckDelayedList (rtc) + croutine (noflash) + * (rtc) + """ + + self._add_mapping(normal) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + dram0_data_default = self._get_default("dram0_data", expected) + dram0_bss_default = self._get_default("dram0_bss", expected) + + rtc_text_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["text"].entries, "rtc_text") + rtc_data_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["data"].entries + self.model.sections["rodata"].entries, "rtc_data") + rtc_bss_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["bss"].entries + self.model.sections["common"].entries, "rtc_bss") + + iram0_text_E2 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["text"].entries, "iram0_text") + dram0_data_E2 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["rodata"].entries, "dram0_data") + + rtc_text_E3 = PlacementRule("libfreertos.a", None, None, self.model.sections["text"].entries, "rtc_text") + rtc_data_E3 = PlacementRule("libfreertos.a", None, None, self.model.sections["data"].entries + self.model.sections["rodata"].entries, "rtc_data") + rtc_bss_E3 = PlacementRule("libfreertos.a", None, None, self.model.sections["bss"].entries + self.model.sections["common"].entries, "rtc_bss") + + rtc_data_extra = PlacementRule("libfreertos.a", "croutine", None, [".data.*"], "rtc_data") + rtc_bss_extra = PlacementRule("libfreertos.a", "croutine", None, [".bss.*"], "rtc_bss") + + # Add the exclusions + flash_text_default.add_exclusion(rtc_text_E3, self.sections_info) + flash_rodata_default.add_exclusion(rtc_data_E3, self.sections_info) + dram0_data_default.add_exclusion(rtc_data_E3, self.sections_info) + dram0_bss_default.add_exclusion(rtc_bss_E3, self.sections_info) + + rtc_text_E3.add_exclusion(iram0_text_E2, self.sections_info) + rtc_data_E3.add_exclusion(dram0_data_E2, self.sections_info) + rtc_data_E3.add_exclusion(rtc_data_extra, self.sections_info) + rtc_bss_E3.add_exclusion(rtc_bss_extra, self.sections_info) + + rtc_data_extra.add_exclusion(rtc_data_E1, self.sections_info) + rtc_bss_extra.add_exclusion(rtc_bss_E1, self.sections_info) + iram0_text_E2.add_exclusion(rtc_text_E1, self.sections_info) + dram0_data_E2.add_exclusion(rtc_data_E1, self.sections_info) + + # Add the rules + expected["rtc_data"].append(rtc_data_extra) + expected["rtc_bss"].append(rtc_bss_extra) + + expected["rtc_text"].append(rtc_text_E1) + expected["rtc_data"].append(rtc_data_E1) + expected["rtc_bss"].append(rtc_bss_E1) + + expected["iram0_text"].append(iram0_text_E2) + expected["dram0_data"].append(dram0_data_E2) + + expected["rtc_text"].append(rtc_text_E3) + expected["rtc_data"].append(rtc_data_E3) + expected["rtc_bss"].append(rtc_bss_E3) + + self._compare_rules(expected, actual) + + def test_rule_generation_nominal_13(self): + normal = """ + [mapping] + archive: libfreertos.a + entries: + croutine:prvCheckDelayedList (noflash) + event_groups:xEventGroupCreate (noflash) + croutine (rtc) + event_groups (rtc) + * (noflash) + """ + + self._add_mapping(normal) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + dram0_data_default = self._get_default("dram0_data", expected) + dram0_bss_default = self._get_default("dram0_bss", expected) + + iram0_text_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["text"].entries, "iram0_text") + dram0_data_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["rodata"].entries, "dram0_data") + + iram0_text_E2 = PlacementRule("libfreertos.a", "event_groups", "xEventGroupCreate", self.model.sections["text"].entries, "iram0_text") + dram0_data_E2 = PlacementRule("libfreertos.a", "event_groups", "xEventGroupCreate", self.model.sections["rodata"].entries, "dram0_data") + + rtc_text_E3 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["text"].entries, "rtc_text") + rtc_data_E3 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["data"].entries + self.model.sections["rodata"].entries, "rtc_data") + rtc_bss_E3 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["bss"].entries + self.model.sections["common"].entries, "rtc_bss") + + rtc_text_E4 = PlacementRule("libfreertos.a", "event_groups", None, self.model.sections["text"].entries, "rtc_text") + rtc_data_E4 = PlacementRule("libfreertos.a", "event_groups", None, self.model.sections["data"].entries + self.model.sections["rodata"].entries, "rtc_data") + rtc_bss_E4 = PlacementRule("libfreertos.a", "event_groups", None, self.model.sections["bss"].entries + self.model.sections["common"].entries, "rtc_bss") + + iram0_text_E5 = PlacementRule("libfreertos.a", None, None, self.model.sections["text"].entries, "iram0_text") + dram0_data_E5 = PlacementRule("libfreertos.a", None, None, self.model.sections["rodata"].entries, "dram0_data") + + # Add the exclusions + flash_text_default.add_exclusion(iram0_text_E5, self.sections_info) + flash_rodata_default.add_exclusion(dram0_data_E5, self.sections_info) + dram0_bss_default.add_exclusion(rtc_bss_E3, self.sections_info) + dram0_data_default.add_exclusion(rtc_data_E3, self.sections_info) + dram0_bss_default.add_exclusion(rtc_bss_E4, self.sections_info) + dram0_data_default.add_exclusion(rtc_data_E4, self.sections_info) + + iram0_text_E5.add_exclusion(rtc_text_E3, self.sections_info) + dram0_data_E5.add_exclusion(rtc_data_E3, self.sections_info) + iram0_text_E5.add_exclusion(rtc_text_E4, self.sections_info) + dram0_data_E5.add_exclusion(rtc_data_E4, self.sections_info) + + rtc_text_E4.add_exclusion(iram0_text_E2, self.sections_info) + rtc_data_E4.add_exclusion(dram0_data_E2, self.sections_info) + + rtc_text_E3.add_exclusion(iram0_text_E1, self.sections_info) + rtc_data_E3.add_exclusion(dram0_data_E1, self.sections_info) + + # Add the rules + expected["iram0_text"].append(iram0_text_E1) + expected["dram0_data"].append(dram0_data_E1) + + expected["iram0_text"].append(iram0_text_E2) + expected["dram0_data"].append(dram0_data_E2) + + expected["rtc_text"].append(rtc_text_E3) + expected["rtc_data"].append(rtc_data_E3) + expected["rtc_bss"].append(rtc_bss_E3) + + expected["rtc_text"].append(rtc_text_E4) + expected["rtc_data"].append(rtc_data_E4) + expected["rtc_bss"].append(rtc_bss_E4) + + expected["iram0_text"].append(iram0_text_E5) + expected["dram0_data"].append(dram0_data_E5) + + self._compare_rules(expected, actual) + + def test_rule_generation_nominal_14(self): + normal = """ + [mapping] + archive: libfreertos.a + entries: + croutine:prvCheckDelayedList (noflash) + event_groups:xEventGroupCreate (rtc) + croutine (rtc) + event_groups (noflash) + """ + + self._add_mapping(normal) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + dram0_data_default = self._get_default("dram0_data", expected) + dram0_bss_default = self._get_default("dram0_bss", expected) + + iram0_text_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["text"].entries, "iram0_text") + dram0_data_E1 = PlacementRule("libfreertos.a", "croutine", "prvCheckDelayedList", self.model.sections["rodata"].entries, "dram0_data") + + rtc_text_E2 = PlacementRule("libfreertos.a", "event_groups", "xEventGroupCreate", self.model.sections["text"].entries, "rtc_text") + rtc_data_E2 = PlacementRule("libfreertos.a", "event_groups", "xEventGroupCreate", self.model.sections["data"].entries + self.model.sections["rodata"].entries, "rtc_data") + rtc_bss_E2 = PlacementRule("libfreertos.a", "event_groups", "xEventGroupCreate", self.model.sections["bss"].entries + self.model.sections["common"].entries, "rtc_bss") + + rtc_text_E3 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["text"].entries, "rtc_text") + rtc_data_E3 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["data"].entries + self.model.sections["rodata"].entries, "rtc_data") + rtc_bss_E3 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["bss"].entries + self.model.sections["common"].entries, "rtc_bss") + + iram0_text_E4 = PlacementRule("libfreertos.a", "event_groups", None, self.model.sections["text"].entries, "iram0_text") + dram0_data_E4 = PlacementRule("libfreertos.a", "event_groups", None, self.model.sections["rodata"].entries, "dram0_data") + + dram0_data_extra = PlacementRule("libfreertos.a", "event_groups", None, [".data.*"], "dram0_data") + dram0_bss_extra = PlacementRule("libfreertos.a", "event_groups", None, [".bss.*"], "dram0_bss") + + # Add the exclusions + flash_text_default.add_exclusion(iram0_text_E4, self.sections_info) + flash_rodata_default.add_exclusion(dram0_data_E4, self.sections_info) + dram0_data_default.add_exclusion(dram0_data_extra, self.sections_info) + dram0_bss_default.add_exclusion(dram0_bss_extra, self.sections_info) + + flash_text_default.add_exclusion(rtc_text_E3, self.sections_info) + flash_rodata_default.add_exclusion(rtc_data_E3, self.sections_info) + dram0_data_default.add_exclusion(rtc_data_E3, self.sections_info) + dram0_bss_default.add_exclusion(rtc_bss_E3, self.sections_info) + + iram0_text_E4.add_exclusion(rtc_text_E2, self.sections_info) + dram0_data_E4.add_exclusion(rtc_data_E2, self.sections_info) + dram0_data_extra.add_exclusion(rtc_data_E2, self.sections_info) + dram0_bss_extra.add_exclusion(rtc_bss_E2, self.sections_info) + + rtc_text_E3.add_exclusion(iram0_text_E1, self.sections_info) + rtc_data_E3.add_exclusion(dram0_data_E1, self.sections_info) + + # Add the rules + expected["iram0_text"].append(iram0_text_E1) + expected["dram0_data"].append(dram0_data_E1) + + expected["rtc_text"].append(rtc_text_E2) + expected["rtc_data"].append(rtc_data_E2) + expected["rtc_bss"].append(rtc_bss_E2) + + expected["rtc_text"].append(rtc_text_E3) + expected["rtc_data"].append(rtc_data_E3) + expected["rtc_bss"].append(rtc_bss_E3) + + expected["iram0_text"].append(iram0_text_E4) + expected["dram0_data"].append(dram0_data_E4) + + expected["dram0_data"].append(dram0_data_extra) + expected["dram0_bss"].append(dram0_bss_extra) + + self._compare_rules(expected, actual) + + def test_rule_generation_nominal_15(self): + normal = """ + [mapping] + archive: libfreertos.a + entries: + croutine (noflash_data) + croutine (noflash_text) + """ + + self._add_mapping(normal) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + + iram0_text_E1 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["text"].entries, "iram0_text") + dram0_data_E1 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["rodata"].entries, "dram0_data") + + # Add the exclusions + flash_text_default.add_exclusion(iram0_text_E1) + flash_rodata_default.add_exclusion(dram0_data_E1) + + # Add the rules + expected["iram0_text"].append(iram0_text_E1) + expected["dram0_data"].append(dram0_data_E1) + + self._compare_rules(expected, actual) + + def test_rule_generation_nominal_16(self): + normal = """ + [mapping] + archive: libfreertos.a + entries: + croutine (noflash_data) + croutine (noflash) + """ + + self._add_mapping(normal) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + + iram0_text_E1 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["text"].entries, "iram0_text") + dram0_data_E1 = PlacementRule("libfreertos.a", "croutine", None, self.model.sections["rodata"].entries, "dram0_data") + + # Add the exclusions + flash_text_default.add_exclusion(iram0_text_E1) + flash_rodata_default.add_exclusion(dram0_data_E1) + + # Add the rules + expected["iram0_text"].append(iram0_text_E1) + expected["dram0_data"].append(dram0_data_E1) + + self._compare_rules(expected, actual) + + def test_rule_generation_conflict(self): + conflict_mapping = """ + [mapping] + archive: libfreertos.a + entries: + croutine (conflict) + croutine (noflash) + """ + + conflict_scheme = """ + [scheme:conflict] + entries: + rodata -> dram0_data + bss -> dram0_data + """ + + self._add_scheme(conflict_scheme) + self._add_mapping(conflict_mapping) + + with self.assertRaises(GenerationException): + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + + def test_rule_generation_condition (self): + generation_with_condition = """ + [mapping] + archive: lib.a + entries: + : PERFORMANCE_LEVEL = 0 + : PERFORMANCE_LEVEL = 1 + obj1 (noflash) + : PERFORMANCE_LEVEL = 2 + obj1 (noflash) + obj2 (noflash) + : PERFORMANCE_LEVEL = 3 + obj1 (noflash) + obj2 (noflash) + obj3 (noflash) + """ + + self._add_mapping(generation_with_condition) + + for perf_level in range(0, 4): + self.sdkconfig.config.syms["PERFORMANCE_LEVEL"].set_value(str(perf_level)) + + actual = self.model.generate_rules(self.sdkconfig, self.sections_info) + expected = self._generate_default_rules() + + flash_text_default = self._get_default("flash_text", expected) + flash_rodata_default = self._get_default("flash_rodata", expected) + + if perf_level < 4: + for append_no in range (1, perf_level + 1): + iram_rule = PlacementRule("lib.a", "obj" + str(append_no), None, self.model.sections["text"].entries, "iram0_text") + dram_rule = PlacementRule("lib.a", "obj" + str(append_no), None, self.model.sections["rodata"].entries, "dram0_data") + + flash_text_default.add_exclusion(iram_rule) + flash_rodata_default.add_exclusion(dram_rule) + + expected["iram0_text"].append(iram_rule) + expected["dram0_data"].append(dram_rule) + + self._compare_rules(expected, actual) + +if __name__ =="__main__": + unittest.main() \ No newline at end of file