Commit Graph

6794 Commits

Author SHA1 Message Date
Simon Glass
bf6a5e80cf malloc: Refactor malloc_dump() to use output callback
Replace direct printf calls in malloc_dump() with an output callback
function. This introduces dump_out_fn type and dump_to_console() helper,
with malloc_dump_impl() taking the callback and context pointer.

This allows the same implementation logic to be reused for different
output destinations such as writing to a file.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2026-01-03 12:40:43 -07:00
Simon Glass
c0dfcc8123 malloc: Fix malloc_usable_size() to handle mcheck headers
When mcheck is enabled, malloc_usable_size() returns incorrect results
because mem2chunk() is called on the offset user pointer rather than the
actual chunk.

The pointer returned to the user is offset by the mcheck header, but
malloc_usable_size() is unaware of this. Add a wrapper that returns the
user-requested size stored in the mcheck header. This fixes test
failures when CONFIG_MCHECK_CALLER_LEN is set to larger values.

Also add a wrapper for the case where MALLOC_DEBUG is enabled without
MCHECK_HEAP_PROTECTION, since MALLOC_DEBUG makes
dlmalloc_usable_size_impl() static but no public dlmalloc_usable_size
exists outside the mcheck block.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2026-01-03 12:39:14 -07:00
Simon Glass
b4f6fdbcd2 sandbox: Add -M option to disable mcheck at runtime
Add a command-line option (-M or --no_mcheck) to disable mcheck heap
protection at runtime. When mcheck is disabled, the wrapper functions
pass through directly to the underlying allocator without adding
headers or checking for corruption.

This is useful for debugging when mcheck interferes with test results,
such as when memory-leak detection reports false positives due to
accumulated allocations from other tests.

Changes:
- Add disable_mcheck flag to sandbox_state
- Add mcheck_set_disabled() function to mcheck API
- Modify dlmalloc wrappers to bypass mcheck when disabled
- Add stub for when MCHECK_HEAP_PROTECTION is not enabled
- Document the new option in sandbox.rst

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2026-01-03 12:39:14 -07:00
Simon Glass
b8b8a65133 mcheck: Skip mcheck overhead for pre-relocation allocations
When mcheck heap-protection is enabled, each allocation adds quite a
bit of overhead for headers and canaries. While this is needed for the
full allocator, it serves no purpose for pre-relocation allocations,
since:

1. Simple malloc is a bump allocator that cannot free memory
3. Mcheck's corruption-detection provides no benefit for non-freeable
   memory

Since the pre-relocation heap space is limited (typically <16KB), this
overhead can exhaust the heap, causing boot failures.

Fix this by bypassing mcheck hooks in dlmalloc(), dlfree(),
dlmemalign() and dlcalloc() when called before relocation, directly
calling the simple malloc functions instead.

Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2026-01-01 14:27:30 -07:00
Simon Glass
6f810962d1 mcheck: Add Kconfig option for caller string length
The mcheck heap protection stores a caller string in each allocation
header for debugging purposes. The length is hard-coded to 48 bytes in
mcheck_core.inc.h

Add a CONFIG_MCHECK_CALLER_LEN Kconfig option to make this configurable,
allowing users to adjust the trade-off between the amount of debugging
context and the memory overhead per allocation.

Co-developed-by: Claude Opus 4.5 <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2026-01-01 14:27:30 -07:00
Heinrich Schuchardt
e1a1046c61 bloblist: adjust default bloblist size after reloc
If neither CONFIG_BLOBLIST_FIXED NOR CONFIG_BLOBLIST_ALLOC is set,
currently CONFIG_BLOBLIST_SIZE_RELOC defaults to 0 except if
* CONFIG_ARM=y && CONFIG_EFI_LOADER=y && GENERATE_ACPI_TABLE=y.

A size of zero never makes sense for a bloblist.

When using QFW we need more than 64 KiB to host the ACPI table.
In this case CONFIG_BLOBLIST_ALLOC is used.

Set a reasonable default.

Remove the CONFIG_BLOBLIST_SIZE_RELOC in ARM QEMU defconfigs which are
not compatible with ACPI tables passed from QEMU.

Reported-by: Emil Renner Berthing <emil.renner.berthing@canonical.com>
Fixes: 6f9b015c13 ("common: Enable BLOBLIST_TABLES on arm")
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
Acked-by: Ilias Apalodimas <ilias.apalodimas@linaro.org>
(cherry picked from commit 559f11e66c)
2025-12-26 19:58:15 -07:00
Evgeny Bachinin
94e9d64ffc fdtdec: encapsulate dtb_dt_embedded() within
Patch keeps the access to dtb_dt_embedded() within fdtdec API,
by means of new API function introduction. This new function is a
common place for updating appropriate global_data fields for
OF_EMBED case.

  Also, the consequence of the patch is movement of '___dtb_dt_*begin'
symbols' declaration from header file, because nobody used symbols
outside the lib/fdtdec.c.

Signed-off-by: Evgeny Bachinin <EABachinin@salutedevices.com>
Suggested-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
(cherry picked from commit 623f5cf517)
2025-12-24 05:17:05 -07:00
Randolph
790b611c89 riscv: spl: add FIT name for RISC-V Falcon mode
The FIT name in RISC-V Falcon mode should be different from that in
normal boot mode; it is called linux.itb. If the setting is missing
in common/spl, the normal boot file name will be used.

Signed-off-by: Randolph <randolph@andestech.com>
(cherry picked from commit e59241f8b1)
2025-12-24 05:17:01 -07:00
Simon Glass
b64009e9a6 common: Move autoprobe out to board init
Rather than doing autoprobe within the driver model code, move it out to
the board-init code. This makes it clear that it is a separate step from
binding devices.

For now this is always done twice, before and after relocation, but we
should discuss whether it might be possible to drop the post-relocation
probe.

For boards with SPL, the autoprobe is still done there as well.

Note that with this change, autoprobe happens after the
EVT_DM_POST_INIT_R/F events are sent, rather than before.

Link: https://lore.kernel.org/u-boot/20240626235717.272219-1-marex@denx.de/

Signed-off-by: Simon Glass <sjg@chromium.org>
(cherry picked from commit 6995f2c8be)
2025-12-21 06:01:44 -07:00
Simon Glass
e010443b06 common: Drop check for DM in initf_dm()
This is enabled by all boards, so drop the condition.

Signed-off-by: Simon Glass <sjg@chromium.org>
Reviewed-by: Tom Rini <trini@konsulko.com>
(cherry picked from commit 70c79dc88f)
2025-12-21 05:46:50 -07:00
Venkatesh Yadav Abbarapu
64049bd24e common: memtop: Fix the return type for find_ram_top
As the return type is "int" for find_ram_top() function and
returning the "base" which is of phys_addr_t is breaking when the
"base" address is 64-bit. So fix this by updating the return type as
phys_addr_t.

Signed-off-by: Venkatesh Yadav Abbarapu <venkatesh.abbarapu@amd.com>
Reviewed-by: Michal Simek <michal.simek@amd.com>
Acked-by: Sughosh Ganu <sughosh.ganu@linaro.org>
Link: https://lore.kernel.org/r/20241220030742.1745984-1-venkatesh.abbarapu@amd.com
Signed-off-by: Michal Simek <michal.simek@amd.com>
(cherry picked from commit 1b70b6c9cc)
2025-12-19 09:40:29 -07:00
Venkatesh Yadav Abbarapu
90eeb8ab55 usb: onboard-hub: Update the bind function based on peer-hub property
As the "peer-hub" property is optional, don't error out just
skip the bind function.

Fixes: 57e30b09fc ("usb: onboard-hub: Bail out if peer hub is already probed")
Signed-off-by: Venkatesh Yadav Abbarapu <venkatesh.abbarapu@amd.com>
Acked-by: Michal Simek <michal.simek@amd.com>
Reviewed-by: Patrice Chotard <patrice.chotard@foss.st.com>
Tested-by: Patrice Chotard <patrice.chotard@foss.st.com>
(cherry picked from commit 0e24474cc3)
2025-12-17 16:36:32 -07:00
Evgeny Bachinin
a0d3466f32 common: relocate fdt_blob in global_data for FDTSRC_EMBED case
Patch resolves two kind of bugs, one of which is vulnerability related
to KASLR.

=== Issue briefly ===

  Working with FDT (via non-relocated gd::fdt_blob) from inside bootm
command may lead to the reading the garbage instead of FDT nodes. And
this can result in various side-effects depending on DTS nodes, being
parsed during bootm.

  But below is my specific story how I faced with this issue due to
MESON_RNG probing failure.

=== Bugs description ===

1) Bug is revealed on:
* configuration below
* U-boot 2024.10 - f919c3a889 ("Prepare v2024.10")

  It seems, the following patch is a trigger:
ea955eea4f ("fdt: automatically add /chosen/kaslr-seed if DM_RNG is enabled")

  Generally, CONFIG_OF_EMBED=y & CONFIG_RNG_MESON=y are the most
valuable ones for reproducing the issue.
```
  CONFIG_ARCH_FIXUP_FDT_MEMORY=y
  CONFIG_CMD_FDT=y
  CONFIG_DEFAULT_FDT_FILE=""
  CONFIG_FDT_64BIT=y
  CONFIG_OF_BOARD_SETUP=y
  CONFIG_OF_CONTROL=y
  CONFIG_OF_EMBED=y
  CONFIG_OF_LIBFDT_ASSUME_MASK=0x0
  CONFIG_OF_LIBFDT_OVERLAY=y
  CONFIG_OF_LIBFDT=y
  CONFIG_OF_LIST="meson-axg-our-device-name"
  CONFIG_OF_REAL=y
  CONFIG_OF_TRANSLATE=y
  CONFIG_SUPPORT_OF_CONTROL=y
  CONFIG_SYS_FDT_PAD=0x3000
  CONFIG_TOOLS_OF_LIBFDT=y

  CONFIG_DM_RNG=y
  CONFIG_RNG_MESON=y
```

2) Due to CONFIG_OF_EMBED, the DTS is embedded into U-boot ELF and
accessible via __dtb_dt_begin symbol.

  On early boot stage (board_f.c) the fdtdec_setup() is called only
once before U-boot's relocation into top of RAM. fdtdec_setup()
initializes gd::fdt_blob for FDTSRC_EMBED case:
```
  gd->fdt_blob = dtb_dt_embedded();
  gd->fdt_src = FDTSRC_EMBED;
```

3) Then reloc_fdt() is called in board_f.c

  But due to CONFIG_OF_EMBED=y the reloc_fdt() does not update
gd::fdt_blob value (strictly speaking, it is impossible for
CONFIG_OF_EMBED=y, because U-boot ELF has not been relocated yet
at this moment).

  As a result after relocation we get fdt_blob, pointing to DTS address
before relocation:
```
   # bdinfo
  <...>
  relocaddr = 0x000000000fedf000
  reloc off = 0x000000000eedf000
  <...>
  fdt_blob = 0x010ce6c0 << points to __dtb_dt_begin before relocation
  new_fdt = 0x0000000000000000  << empty erroneously
  fdt_size = 0x0000000000000000 << zero erroneously
```

4) During bootm command (according to our ITS-config file) the Linux
is loaded into 0x01080000 (which is very close to fdt_blob addr
0x010ce6c0).
```
  ## Loading kernel from FIT Image at 04000000 ...
     Trying 'kernel' kernel subimage
       <...>
       Load Address: 0x01080000
```

  So Linux image overwrites the gd::fdt_blob memory location
in RAM (0x010ce6c0).

5) Issue:

  Hence any manipulation with DTS (say, via FDT API) inside
implementation of bootm command leads to accessing the fdt_blob area
with garbage, that can lead to two situations:

5.1) Abort.

  Call to fdt_off_dt_struct() from fdt_next_tag() :: fdt_offset_ptr()::
fdt_offset_ptr_() returns with garbage, that leads to tagp value
being out of RAM top addr (256 Mb in our board), causing the abort:
```
  Boot cmd: bootm 0x4000000#boot_evt1
  bootm_run_states()
  <...>
  image_setup_libfdt()
   fdt_chosen()
    fdt_kaslrseed()
     uclass_get_device()
      uclass_get_device_tail()
       device_probe()
        device_of_to_plat()
        meson_rng_of_to_plat()
         clk_get_by_name_optional()
          clk_get_by_name()
           clk_get_by_name_nodev()
            ofnode_stringlist_search()
             fdt_stringlist_search()
              fdt_getprop()
               fdt_get_property_namelen_()
                fdt_first_property_offset()
                 fdt_check_node_offset_()
                  fdt_next_tag():
                    ```
                      tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
                    ```
                  fdt_next_tag() tagp:0x22890766
                  fdt_next_tag() ram_top:0x10000000 (tagp OUT of RAM)
  "Synchronous Abort" handler, esr 0x96000010, far 0x22890766
  elr: 000000000108be24 lr : 000000000108be24 (reloc)
  elr: 000000000ff6fe24 lr : 000000000ff6fe24
  x0 : 0000000000000041 x1 : 0000000000000000
  x2 : 000000000ff3b57c x3 : 0000000000000012
  x4 : 000000000ded2ad5 x5 : 0000000000000020
  x6 : 00000000ffffffe8 x7 : 000000000ded2f40
  x8 : 00000000ffffffd8 x9 : 000000000000000d
  x10: 0000000000000006 x11: 000000000001869f
  x12: 000000000fffffff x13: 000000000fffffff
  x14: 0000000000000000 x15: 000000000ded2abb
  x16: 000000000ff3b080 x17: 0000000000000001
  x18: 000000000ded3dc0 x19: 0000000022890766
  x20: 00000000010cb0f0 x21: 00000000000015e4
  x22: 000000000ff8f4d8 x23: 000000000000000b
  x24: 000000000ded2fbc x25: 000000000ffe2000
  x22: 000000000ff8f4d8 x23: 000000000000000b
  x24: 000000000ded2fbc x25: 000000000ffe2000
  x26: 000000000ffe2000 x27: 000000000000000b
  x28: 000000000ff9cf2d x29: 000000000ded2f40

  Code: aa1603e1 91197484 52801742 94004de8 (b9400276)
```

5.2) Vulnerability situation "KASLR is disabled".

Almost the same as in (5.1), but 2 situations happen (depending on
the value of garbage):
  * call to fdt_offset_ptr_() :: fdt_off_dt_struct(fdt)
    returns not so big garbage, leading to tagp, being inside RAM.
  * or calculations of absoffset inside fdt_offset_ptr() leads to
    failure of the one of if() conditions with NULL as retval.

  Result is fdt_next_tag() interprets the tagp as FDT_END. And we are
returning from our callstack via functions' error paths, leading to
"No RNG device" and "KASLR disabled due to lack of seed":
```
  fdt_kaslrseed()
   uclass_get_device()
   <...>
    device_probe()
     device_of_to_plat()
      meson_rng_of_to_plat()
       clk_get_by_name()
        clk_get_by_name_nodev()
        <...>
         fdt_stringlist_search()
          fdt_getprop()
           fdt_get_property_namelen_()
            fdt_first_property_offset()
             fdt_check_node_offset_()
              fdt_next_tag():
                ```
                  tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE);
                ```
              fdt_next_tag() tagp:0000000001890677
              fdt_next_tag() ram_top:0x10000000 (tagp is inside RAM)
      uclass_get_device_tail():486 device_probe() ret:-22
  No RNG device
 Starting kernel ...

  [ 0.000000] Linux version 6.9.12
  [ 0.000000] KASLR disabled due to lack of seed
```

Signed-off-by: Evgeny Bachinin <EABachinin@salutedevices.com>
(cherry picked from commit acab6e78ac)
2025-12-17 02:30:38 +00:00
Heinrich Schuchardt
5b9d59d3eb configs: raise SPL_SYS_MALLOC_SIZE to 8 MiB on RISC-V
On several RISC-V boards we have seen that 1 MiB is a insufficient value
for CONFIG_SPL_SYS_MALLOC_SIZE.

For instance qemu-riscv32_spl_defconfig fails booting because u-boot.itb
exceeds 1 MiB.

8 MiB is a reasonable value that allows adding FPGA blobs or splash images
to main U-boot.

Reported-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt@canonical.com>
Reviewed-by: Leo Yu-Chi Liang <ycliang@andestech.com>
(cherry picked from commit 8b410cab51)
Dropped modifications to all files except common/spl/Kconfig:
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-13 16:28:36 -07:00
Simon Glass
4739e7a89a malloc: Print mcheck registry-overflow message only once
Use a static bool flag to ensure the overflow warning is printed only
once, avoiding repeated messages when the registry is full.

Make sure to set the flag before calling printf(), which can itself do
allocations with sandbox / Truetype.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
9998ff5c87 malloc: Show caller info for freed chunks in malloc_dump
When CONFIG_MCHECK_HEAP_PROTECTION is enabled, show the original
caller info for freed chunks. This helps identify what code allocated
memory that is now free.

The mcheck header's canary and caller fields survive after free since
dlmalloc only overwrites the first 16 bytes (size, aln_skip) with its
free list pointers (fd, bk). We detect freed headers by looking for
the MAGICFREE canary pattern.

For small chunks or coalesced chunks where the header is not preserved,
the caller info is simply omitted.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
a527909208 malloc: Skip backtrace when stack is corrupted
When the stack is corrupted (e.g., by the stack protector test),
collecting a backtrace during malloc causes a crash because the
backtrace code walks the invalid stack frames.

Update __stack_chk_fail() to set the flag before calling panic()

Also update stackprot_test() to set the flag before intentionally
corrupting the stack. This is needed because of the printf() in the
test: on sandbox printf() results in truetype allocations due to the
console output.

These fixes allow the stack protector test to pass with mcheck enabled.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
754a755e4a malloc: Record caller backtrace for each allocation
When CONFIG_MCHECK_HEAP_PROTECTION is enabled, use backtrace_str() to
capture the caller information for each malloc/calloc/realloc/memalign
call. This information is stored in the mcheck header and can be viewed
with 'malloc dump'.

Add a flag to disable the backtrace when the stack is corrupted, since
the backtrace code tries to walks the invalid stack frames and will
crash.

Note: A few allocations made during libbacktrace initialisation may
not have caller info since they occur during the first backtrace call.

Example output showing caller info:
    18a1d010   90  used  log_init:453 <-board_init_r:774
    18a1d0a0 6060  used  membuf_new:420 <-console_record
    18a3b840   90  used  of_alias_scan:911 <-board_init_

Fix up the backtrace test to avoid recursion.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
36118a9e18 malloc: Fix malloc_dump to find mcheck headers in memalign chunks
For memalign allocations, the mcheck header is placed at an offset from
the chunk start to maintain alignment. The current assumption is that
the header is always at the start of the chunk, but this is not true for
memalign allocations.

Add find_mcheck_hdr_in_chunk() which looks up the header in the mcheck
registry and validates:
- The header falls within the chunk's memory range
- The aln_skip field is consistent with the header position
- The canary is MAGICWORD (active), not MAGICFREE (freed)

This ensures malloc_dump correctly displays caller info for all
allocations including those made via memalign.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
ee8e9bf104 malloc: Add malloc dump command to walk the heap
Add a new 'malloc dump' command that walks the dlmalloc heap from start
to end, printing each chunk's address, size (in hex), and status
(used/free/top). This is useful for debugging memory allocation issues.

When CONFIG_MCHECK_HEAP_PROTECTION is enabled, the caller string is
also shown if available.

Example output:
    Heap dump: 18a1d000 - 1ea1f000
         Address        Size  Status
    ----------------------------------
        18a1d000          10  (chunk header)
        18a1d010          90  used
        18adfc30          60  <free>
        18adff90     5f3f030  top
        1ea1f000              end
    ----------------------------------
    Used: c2ef0 bytes in 931 chunks
    Free: 5f3f0c0 bytes in 2 chunks + top

Expand the console-record size to handle this command.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
e2ccfa9c23 malloc: Add a caller-info parameter to dlmalloc_impl()
When CONFIG_MALLOC_DEBUG is enabled, add an optional caller string
parameter to dlmalloc_impl(). This allows tracking where allocations
originate from when debugging memory issues.

The CALLER_PARAM, CALLER_ARG, and CALLER_NULL macros hide the parameter
when MALLOC_DEBUG is not enabled, keeping the non-debug code path clean.

When MALLOC_DEBUG is enabled (with or without MCHECK), the _impl
functions must be separate from the public API functions since they
have different signatures. Add simple pass-through wrappers for this
case.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
834e83ffc1 malloc: Support storing caller information
Add a field to store the caller for each allocation, using the backtrace
information. This can be useful when debugging heap corruption.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
69257bf5a9 malloc: Remove warning messages during relocation
Pre-relocation heap allocations are expected to be discarded during
relocation - this is normal behavior, not a warning condition.
Remove the verbose messages that were printed for each chunk.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
afddd1b731 malloc: Increase the mcheck registry size
The mcheck registry tracks concurrent allocations for pedantic checking.
The current size of 6608 entries is insufficient when running the full
pytest suite, causing registry overflow warnings.

Increase REGISTRY_SZ to 12000 to handle the full test suite.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
87c2c087ea malloc: Update the valloc functions to use mcheck wrappers
Fix dlposix_memalign(), dlvalloc(), and dlpvalloc() to call dlmemalign()
instead of dlmemalign_impl() or internal_memalign() directly. This
ensures these functions go through the mcheck wrappers when
CONFIG_MCHECK_HEAP_PROTECTION is enabled.

Without this fix, internal_memalign is undefined when mcheck is enabled,
causing a build error.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
f96cb92d4c malloc: Fix internal calls and memalign for mcheck
With mcheck enabled, internal_malloc and internal_free go through mcheck
wrappers which expect user pointers (after mcheck header), not raw
allocator pointers. Also, dlmemalign_impl() needs a properly aligned base
pointer for mcheck to place its header correctly.

Use _impl functions directly for internal_malloc/internal_free. Call
internal_memalign() for alignments greater than MALLOC_ALIGNMENT.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
22c435d21b malloc: Move mcheck block after includes
Move the CONFIG_MCHECK_HEAP_PROTECTION block after the standard
includes so that size_t and string functions are available for
the inline MALLOC_ZERO and MALLOC_COPY functions.

Add the <string.h> and <linux/types.h> includes needed for mcheck.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
331063acd0 malloc: Add a Kconfig option for heap protection
Add CONFIG_MCHECK_HEAP_PROTECTION option to enable mcheck heap
protection. Convert all uses of MCHECK_HEAP_PROTECTION to use the
CONFIG_ -prefixed version to work with Kconfig.

Disable this option when tracing is enabled, since the mcheck hooks (mcheck_pedantic_prehook(), etc.) interfere with function tracing.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
d8b19014d7 malloc: Add call counters for malloc, free, realloc
Add counters to track the number of calls to malloc(), free(), and
realloc(). These are displayed by the 'malloc info' command and
accessible via malloc_get_info().

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
bd0f9a753c malloc: Enable stats if UNIT_TEST or MALLOC_DEBUG
When debugging or running unit tests it is helpful to have information
available from the malloc subsystem. Enable these features in those
cases.

Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
c3fb5f4018 malloc: Add a Kconfig option for debugging malloc()
Add a new CONFIG_MALLOC_DEBUG option to control malloc() debugging
features. This replaces the direct UNIT_TEST check and allows enabling
malloc debugging independently of whether UNIT_TEST is enabled.

The option defaults to y when UNIT_TEST is enabled, preserving existing
behaviour. Disable for RISC-V since it seems to have a size limitation.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
bd73f8182a malloc: Add malloc_get_info() to retrieve memory statistics
Add struct malloc_info and malloc_get_info() function to
programmatically access the memory-allocation stats that malloc_stats()
prints.

The struct contains the size of the malloc() poll and the number of
bytes in use.

Add a static inline stub to return an error when DEBUG is not defined.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
a91d1a5541 malloc: Fix unused internal_memalign warning with mcheck
When CONFIG_MCHECK_HEAP_PROTECTION is enabled, dlmemalign_impl() calls
dlmalloc_impl() directly since the mcheck wrapper handles alignment.
This leaves internal_memalign() unused, causing a compiler warning.

Guard internal_memalign() with a preprocessor check so it's only
compiled when needed (mcheck disabled or MSPACES enabled).

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
95f10a6302 malloc: Make mcheck respect REALLOC_ZERO_BYTES_FREES
The mcheck wrapper for realloc() unconditionally frees memory and
returns NULL when size is 0. This differs from dlmalloc's default
behaviour which returns a minimum-sized allocation unless
REALLOC_ZERO_BYTES_FREES is defined.

Make the mcheck wrapper respect the same REALLOC_ZERO_BYTES_FREES
setting for consistent behavior with or without mcheck enabled.

Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
f22cc09203 malloc: Use mcheck.h header instead of local declaration
Include <mcheck.h> and remove the local declaration of
mcheck_on_ramrelocation() to use the proper header file.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
c17d68b0fb test: Show the required size when console-record overflows
When the console-record buffer overflows, show both the current buffer
size and the size needed. This helps the user know what value to set
for CONFIG_CONSOLE_RECORD_OUT_SIZE.

Add a console_out_ovf field to global_data to track the number of bytes
that could not be written due to overflow.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-10 05:53:03 -07:00
Simon Glass
4096d43361 doc: Add malloc documentation
Add doc/develop/malloc.rst documenting U-Boot's dynamic memory
allocation implementation:

- Overview of pre/post-relocation malloc phases
- dlmalloc 2.8.6 version and features
- Data structure sizes (~500 bytes vs 1032 bytes in 2.6.6)
- Configuration options for code-size optimization
- Debugging features (mcheck, valgrind, malloc testing)
- API reference

Also add an introductory comment to dlmalloc.c summarising the
U-Boot configuration.

Series-to: concept
Series-cc: heinrich
Cover-letter:
malloc: Import dlmalloc 2.8.6
This series imports dlmalloc 2.8.6 from Doug Lea, replacing the old
version 2.6.6 that U-Boot has been using since 2002.

The new version provides:
- Better memory efficiency with improved binning algorithms
- More robust overflow checking via MAX_REQUEST
- Somewhat cleaner codebase

All U-Boot-specific modifications from the historical commits have been
ported to the new implementation, including:
- Pre-relocation malloc via malloc_simple
- Valgrind annotations
- Malloc testing infrastructure
- mcheck heap protection support
- Sandbox USE_DL_PREFIX support

The approach here is to leave the upstream code unchanged, so much as
possible, clearly marking U-Boot-specific changes with an #ifdef

Unfortunately the code size is not great out-of-the-box, so the final
part of the series includes some options to remove in-place realloc(),
provide a simplified init, remove the tree stucture for large blocks
and a few other things.

With these adjustments the new version is about 1K less code on Thumb2
(firefly-rk3288).

The new free() algorithm is more sophisticated but also larger. If
needed we might be able to shrink by a few hundred bytes. Of course SPL
doesn't normally use free() so the benefit might be minimal.

Another point worth mentioning is that the pre-inited av_[] array has
been replaced replaced with a BSS _sm_ struct which reduces the image
size by about 1.5K. One patch adjusts some imx8mp boards to deal with
the larger BSS.

Some code-size stats:

  $ buildman -b mala imx8mp_venice firefly-rk3288 firefly-rk3399 -sS --step 0
  Summary of 2 commits for 3 boards (3 threads, 11 jobs per thread)
  01: backtrace: Strip the source tree prefix from filenames
     aarch64:  w+   imx8mp_venice firefly-rk3399
  40: doc: Add malloc documentation
     aarch64: (for 2/2 boards) all -3904.0 bss +864.0 data -2076.0
       spl/u-boot-spl:all -654.0 spl/u-boot-spl:bss +316.0
       spl/u-boot-spl:data -1034.0 spl/u-boot-spl:text +64.0 text -2692.0
     arm: (for 1/1 boards) all -1436.0 data -1040.0 text -396.0

For the new malloc.h I have avoided including string.h so have added
that to various places that need it.

The existing common/dlmalloc.src file is left alone.

In order to bring this in without losing functionality, I went through
the patches applied to the original implementation over time. Where
these commits were added, they are added as a cherry-pick, with the
original commit hash.

Here is a list of what was done with each U-Boot commit on top of the
new common/dlmalloc.c and include/malloc.h:

 1. 217c9dad82 2002-10-25 Initial revision
    - Ignored

 2. 5b1d713721 2002-11-03 Initial revision
    - Ignored

 3. 8bde7f776c 2003-06-27 * Code cleanup:
    - Ignored as we don't really want to change the style

 4. d87080b721 2006-03-31 GCC-4.x fixes: clean up global data pointer initialization for all boards.
    - Global data is not needed at this point

 5. 81673e9ae1 2008-05-13 Make sure common.h is the first include.
    - common.h has been removed

 6. f2302d4430 2008-08-06 Fix merge problems
    - no merge problems to fix with the new code

 7. 60a3f404ac 2009-06-13 malloc.h: protect it against multiple include
    - Already covered: new malloc.h has MALLOC_280_H include guards

 8. 5e93bd1c9a 2009-08-21 Consolidate arch-specific sbrk() implementations
    - Already covered: sbrk() and mem_malloc_init() in separate commit

 9. d4e8ada0f6 2009-08-21 Consolidate arch-specific mem_malloc_init() implementations
    - Already covered: mem_malloc_init() in separate commit

10. 521af04d85 2009-09-21 Conditionally perform common relocation fixups
    - Not needed: Manual relocation removed in 4babaa0c28

11. b4feeb4e8a 2009-11-24 i386: Fix malloc initialization
    - Already covered: mem_malloc_init() is common, no arch-specific guards

12. 2740544881 2010-01-15 malloc: return NULL if not initialized yet
    - Done: Add check in dlmalloc() to return NULL if not initialized

13. ae30b8c200 2010-04-06 malloc: sbrk() should return MORECORE_FAILURE instead of NULL on failure
    - Already covered: sbrk() returns MFAIL on failure

14. ea882baf9c 2010-06-20 New implementation for internal handling of environment variables.
    - Not needed: Just changes #if 0 to #ifdef DEBUG for old stats code

15. 1ba91ba233 2010-10-14 dlmalloc.c: Fix gcc alias warning
    - Not needed: New dlmalloc has no strict-aliasing warnings

16. 2e5167ccad 2010-10-28 Replace CONFIG_RELOC_FIXUP_WORKS by CONFIG_NEEDS_MANUAL_RELOC
    - Not needed: Manual relocation removed in 4babaa0c28

17. 6163f5b4c8 2010-11-15 malloc: Fix issue with calloc memory possibly being non-zero
    - Already covered: sbrk() clears memory on negative increment

18. 21726a7afc 2011-06-29 Add assert() for debug assertions
    - Not needed: New dlmalloc uses U-Boot's global assert()

19. ea95cb7331 2011-09-10 utx8245: fix build breakage due to assert()
    - Not needed: New dlmalloc has different debug check functions

20. 213adf6dff 2012-03-29 Malloc: Fix -Wundef warnings
    - Not needed: New malloc.h doesn't have these #if issues

21. 93691842e8 2012-09-04 Fix strict-aliasing warning in dlmalloc
    - Not needed: New dlmalloc has no malloc_bin_reloc()

22. 00d0d2ad4e 2012-06-03 malloc: remove extern declarations of malloc_bin_reloc() in board.c files
    - Not needed: New dlmalloc has no malloc_bin_reloc()

23. 199adb601f 2012-10-29 common/misc: sparse fixes
    - Not needed: New dlmalloc uses proper NULL

24. 7b395232da 2013-01-21 malloc: make malloc_bin_reloc static
    - Not needed: New dlmalloc has no malloc_bin_reloc()

25. 472d546054 2013-04-01 Consolidate bool type
    - Not needed: Just a comment change (True -> true)

26. d93041a4ca 2014-07-10 Remove form-feeds from dlmalloc.c
    - Not needed: New dlmalloc doesn't have form-feeds

27. d59476b644 2014-07-10 Add a simple malloc() implementation for pre-relocation
    - Done (updated): Redirect to malloc_simple before GD_FLG_FULL_MALLOC_INIT

28. 6d7601e744 2014-07-10 sandbox: Always enable malloc debug
    - Done (updated): Combined with #64, use 'DEBUG 1' for new dlmalloc

29. 854d2b9753 2014-10-29 dlmalloc: ensure gd is set for early alloc
    - Not needed: Reverted by #38

30. 868de51dde 2014-08-26 malloc: Output region when debugging
    - Already covered: debug() message in mem_malloc_init()

31. c9356be307 2014-11-10 dm: Split the simple malloc() implementation into its own file
    - Already covered: Redirect to malloc_simple.c via GD_FLG_FULL_MALLOC_INIT

32. 0aa8a4ad99 2015-03-04 dlmalloc: do memset in malloc init as new default config
    - Already covered: SYS_MALLOC_CLEAR_ON_INIT at line 6396

33. fb5cf7f16b 2015-02-27 Move initf_malloc() to a common place
    - Already covered: initf_malloc() at line 6357

34. 1eb0c03c21 2015-09-13 malloc_simple: Add Kconfig option for using only malloc_simple in the SPL
    - Not needed: Changes to Kconfig/malloc_simple.c, not dlmalloc.c

35. 4f144a4164 2016-01-25 malloc: work around some memalign fragmentation issues
    - Done (updated): Ported to internal_memalign() at line 4955

36. ee05fedc6c 2016-02-04 malloc: solve dead code issue in memalign()
    - Not needed: New dlmalloc 2.8.6 has rewritten internal_memalign()

37. 2f0bcd4de1 2016-03-05 malloc: use hidden visibility
    - Done (updated): Use DLMALLOC_EXPORT at line 546

38. deff6fb3a7 2016-03-05 malloc: remove !gd handling
    - Not needed: Reverts #29, we don't add gd check

39. 4eece2602b 2016-04-21 common/dlmalloc.c: Delete content that was moved to malloc.h
    - Not needed: New dlmalloc doesn't have #if 0 code

40. 034eda867f 2016-04-25 malloc: improve memalign fragmentation fix
    - Done (updated): Combined with #35 in memalign workaround port

41. 4e33316f65 2017-05-25 malloc: Turn on DEBUG when enabling unit tests
    - Already covered: Combined with #28, #63 at line 555

42. f1896c45cb 2017-07-24 spl: make SPL and normal u-boot stage use independent SYS_MALLOC_F_LEN
    - Already covered: Use CONFIG_IS_ENABLED and CONFIG_VAL at line 6410

43. a874cac3b4 2017-11-10 malloc: don't compare pointers to 0
    - Not needed: New dlmalloc uses proper NULL comparisons

44. ee038c58d5 2018-05-18 malloc: Use malloc simple before malloc is fully initialized in memalign()
    - Already covered: memalign_simple redirect at line 5367

45. 7cbd2d2e32 2018-11-18 malloc_simple: Add logging of allocations
    - Not needed: Changes to malloc_simple.c, not dlmalloc.c

46. 4c6be01c27 2019-03-27 malloc: Fix memalign not honoring alignment prior to full malloc init
    - Already covered: Uses memalign_simple at line 5367

47. bb71a2d9dc 2019-10-25 dlmalloc: calloc: fix zeroing early allocations
    - Done (updated): Port to dlcalloc() at line 4857

48. cfda60f99a 2020-02-03 sandbox: Use a prefix for all allocation functions
    - Done: USE_DL_PREFIX and reverse mappings in malloc.h

49. be621c11b9 2020-04-15 dlmalloc: remove unit test support in SPL
    - Already covered: CONFIG_IS_ENABLED(UNIT_TEST) at line 554

50. 9297e366d6 2020-04-29 malloc: dlmalloc: add an ability for the malloc to be re-init/init multiple times
    - Not needed: No boards use CONFIG_SYS_MALLOC_DEFAULT_TO_INIT

51. f7ae49fc4f 2020-05-10 common: Drop log.h from common header
    - Already covered: Includes log.h at line 559

52. 401d1c4f5d 2020-10-30 common: Drop asm/global_data.h from common header
    - Already covered: Includes asm/global_data.h at line 557

53. c6bf4f3898 2021-02-10 malloc: adjust memcpy() and memset() definitions.
    - Not needed: New malloc.h doesn't declare memset/memcpy

54. c197f6e279 2021-03-15 malloc: Export malloc_simple_info()
    - Not needed: Only changes malloc.h, not dlmalloc.c

55. 5ad9220bf7 2021-05-29 malloc: add SPDX license identifiers
    - Not needed: New dlmalloc has MIT-0 license from upstream

56. bdaeea1b68 2022-03-23 malloc: Annotate allocator for valgrind
    - Done (updated): Valgrind annotations in dlmalloc(), dlfree(), dlrealloc()

57. 62d638386c 2022-09-06 test: Support testing malloc() failures
    - Done: malloc_testing/malloc_max_allocs in dlmalloc()

58. f88d48cc74 2023-02-27 dlmalloc: Fix a warning with clang-15
    - Done: Add (void) to dlmalloc_stats() function definition

59. c9db9a2ef5 2023-08-25 dlmalloc: Add support for SPL_SYS_MALLOC_CLEAR_ON_INIT
    - Already covered: Uses CONFIG_IS_ENABLED() in mem_malloc_init() from #32

60. 6a595c2f67 2023-09-06 common: malloc: Remove unused NEEDS_MANUAL_RELOC code bits
    - Not needed: NEEDS_MANUAL_RELOC has been removed

61. ac897385bb 2023-10-02 Merge branch 'next'
    - Not needed: Merge commit, no dlmalloc changes

62. 3d6d507514 2023-09-26 spl: Use SYS_MALLOC_F instead of SYS_MALLOC_F_LEN
    - Already covered: Uses CONFIG_IS_ENABLED(SYS_MALLOC_F) throughout

63. 1786861415 2023-10-07 malloc: Enable assertions if UNIT_TEST is enabled
    - Done (updated): Combined with #28, use 'DEBUG 1' for new dlmalloc

64. c82ff48115 2024-03-31 mcheck: prepare +1 tier for mcheck-wrappers, in dl-*alloc commands
    - Done (updated): Added STATIC_IF_MCHECK and *_impl macros for dlmalloc 2.8.6

65. dfba071ddc 2024-03-31 mcheck: Use memset/memcpy instead of MALLOC_ZERO/MALLOC_COPY for mcheck.
    - Done: Undef and redefine MALLOC_ZERO/MALLOC_COPY when mcheck enabled

66. 151493a875 2024-03-31 mcheck: integrate mcheck into dlmalloc.c
    - Done: Added mcheck wrapper functions for dlmalloc, dlfree, dlrealloc, dlmemalign, dlcalloc

67. ae838768d7 2024-03-31 mcheck: support memalign
    - Done: Implemented dlmemalign wrapper with mcheck hooks

68. 18c1bfafe0 2024-03-31 mcheck: add pedantic mode support
    - Done: Added mcheck_pedantic_prehook() calls and mcheck_pedantic()/mcheck_check_all() API

69. a79fc7a79c 2024-04-27 common: Remove <common.h> and add needed includes
    - Not needed: common.h has been removed

70. d678a59d2d 2024-05-18 Revert "Merge patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet""
    - Not needed: common.h has been removed

71. 03de305ec4 2024-05-20 Restore patch series "arm: dts: am62-beagleplay: Fix Beagleplay Ethernet"
    - Not needed: common.h has been removed

72. 910cef3d2f 2024-07-13 common: Remove duplicate newlines
    - Not needed: New dlmalloc has its own formatting from upstream

73. 6627fbba20 2024-07-23 include: Remove duplicate newlines
    - Not needed: New malloc.h has its own formatting from upstream

74. 04894f5ad5 2024-07-30 malloc: Support testing with realloc()
    - Done: Combined with #57, malloc_testing check in dlrealloc()

75. 8642b2178d 2024-08-02 dlmalloc: Fix integer overflow in request2size()
    - Not needed: New dlmalloc 2.8.6 uses MAX_REQUEST for robust overflow checks

76. 0a10b49206 2024-08-02 dlmalloc: Fix integer overflow in sbrk()
    - Already covered: sbrk() checks bounds before memset in U-Boot section

77. 9b9368b5c4 2024-08-02 dlmalloc: Make sure allocation size is within malloc area
    - Not needed: New dlmalloc 2.8.6 uses MAX_REQUEST for robust overflow checks

78. 41fecdc94e 2024-10-21 common: Tidy up how malloc() is inited
    - Already covered: mem_malloc_init() uses map_sysmem in U-Boot section

79. 22f87ef530 2025-08-17 malloc: Avoid defining calloc()
    - Done: Added SYS_MALLOC_SIMPLE section to malloc.h with calloc redirect
END

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-01 17:04:37 +00:00
Simon Glass
7eeb099ae1 malloc: Switch to the new malloc() implementation
Add CONFIG_SYS_MALLOC_LEGACY to select the current allocator and adjust
the header-file and Makefile rule to use the new dlmalloc
implementation.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-01 17:00:23 +00:00
Simon Glass
9c57da7282 malloc: Add SMALLCHUNKS_AS_FUNCS to convert macros to funcs
The insert_small_chunk() and unlink_first_small_chunk() macros are
inlined at multiple places in the code.

Provide an option to convert these to functions, so the compiler can try
to reduce code size.

Add braces to the insert_chunk macro.

This reduces code size imx8mp_venice SPL by about 208 bytes

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-01 17:00:23 +00:00
Simon Glass
3a6c517068 malloc: Add SIMPLE_MEMALIGN to simplify memalign for code size
Add a new SIMPLE_MEMALIGN to remove the fallback-retry logic from
memalign(), to reduce code sizein SPL.

The fallback mechanism attempts multiple allocation strategies:
1. Over-allocate to guarantee finding aligned space
2. If that fails, allocate exact size and check if aligned
3. If not aligned, free and retry with calculated extra space

While this fallback is useful in low-memory situations, SPL typically
has predictable memory usage and sufficient heap space for the initial
over-allocation to succeed. The fallback adds code complexity without
obvious practical benefit.

This reduces code size on imx8mp_venice (for example) SPL by 74 bytes.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-01 17:00:22 +00:00
Simon Glass
c87cac82e4 malloc: Add NO_TREE_BINS option to reduce code size
Add a new NO_TREE_BINS option to disable binary-tree bins for large
allocations (>= 256 bytes). While this is an invasive changes, it saves
about 1.25K of code size on arm64 (as well as 250 bytes of data). When
enabled, all large chunks use a simple doubly-linked list instead of
tree bins, trading O(log n) performance for smaller code size.

The tradeoff here is that large allocations use O(n) search instead of
O(log n) and fragmentation coud also become worse. So performance will
suffer when there are lots of large allocations and frees are done. This
is rare in SPL.

Implementation:
- Add a dedicated mchunkptr largebin field to malloc_state
- Replace treebins[NTREEBINS] array with a single linked-list pointer
- Implement simplified insert/unlink operations using largebin list
- Update allocation functions (tmalloc_small/large) for linear search
- Update heap checking functions (do_check_treebin, bin_find) to handle
  linked list traversal instead of tree traversal

It is enabled by CONFIG_SYS_MALLOC_SMALL, i.e. by default in SPL.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-01 16:59:59 +00:00
Simon Glass
319350496b malloc: Add NO_REALLOC_IN_PLACE option to reduce code size
Add a new NO_REALLOC_IN_PLACE option that disables in-place realloc
optimization. When enabled via CONFIG_SYS_MALLOC_SMALL, realloc() always
allocates new memory, copies data, and frees the old block instead of
trying to extend the existing allocation.

This saves about 500 bytes by eliminating try_realloc_chunk() and
mmap_resize() functions.

When unit tests are enabled, the extra realloc logic is included.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-01 16:57:15 +00:00
Simon Glass
d8c064ab34 malloc: Allow building dlmalloc with SPL_SYS_MALLOC_SIMPLE
When building boards that use CONFIG_SPL_SYS_MALLOC_SIMPLE (like
qemu-x86_64), we need to avoid a conflict between the stub free()
function defined by malloc and the real free() defined by dlmalloc.c

Fix this by define COMPILING_DLMALLOC in dlmalloc.c before including
malloc.h and adding a guard to the latter.

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-01 16:57:15 +00:00
Simon Glass
1088f74ec6 malloc: Set up the malloc() state in mem_malloc_init()
Move the malloc state initialisation from lazy init in sys_alloc() to
explicit init in mem_malloc_init(). This allows is_initialized() to
always return true for U-Boot, eliminating runtime checks.

The initialisation sets up:
- least_addr, seg.base, seg.size, seg.sflags
- magic, release_checks, mflags
- bins (via init_bins)
- top chunk (via init_top)
- footprint tracking

Add a simplified sys_alloc() for small builds. Since the
heap is pre-allocated with fixed size, sys_alloc() only needs to extend
via sbrk() if space remains: no mmap, no multiple segments, no comple
merging. The helper functions mmap_alloc(), mmap_resize(),
prepend_alloc() and add_segment() are thus compiled out for non-sandbox
builds.

This is controlled by a new SIMPLE_SYSALLOC option, which is the
default. Sandbox retains full functionality for testing.

With this, the new dlmalloc is approximately at parity with the old one,
e.g. about 400 bytes less code on Thumb2 (firefly-rk3288).

There is a strange case here with a small number of boards which set up
the full malloc() when CONFIG_SYS_MALLOC_SIMPLE is enabled. This cannot
work.

With CONFIG_SPL_SYS_MALLOC_SIMPLE, all malloc()/free()/realloc() calls
are redirected to simple implementations via macros in thhe malloc.h
header. In this case, mem_malloc_init() doesn't need to init the dlmalloc
state structure (gm) since it will never be used.

Initing _gm_ pulls in the entire malloc_state BSS structure (~472
bytes) plus initialisation code (~128 bytes), adding ~600 bytes to SPL
on boards that use full malloc (K3 platforms with CONFIG_K3_LOAD_SYSFW).

Skip the _gm_ init when SYS_MALLOC_SIMPLE is enabled.

These boards call mem_malloc_init() even though it will have no effect:

   $ ./tools/qconfig.py -f CONFIG_K3_LOAD_SYSFW SPL_SYS_MALLOC_SIMPLE -l
   am62ax_evm_r5
   am62px_evm_r5
   am62x_beagleplay_r5
   am62x_evm_r5
   am62x_evm_r5_ethboot
   am62x_lpsk_r5
   am64x_evm_r5
   am68_sk_r5
   am69_sk_r5
   j721s2_evm_r5
   j722s_evm_r5
   j784s4_evm_r5
   phycore_am62x_r5
   phycore_am62x_r5_usbdfu
   phycore_am64x_r5
   verdin-am62_r5

Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
2025-12-01 16:57:15 +00:00
Simon Glass
e8eb87ea1b mcheck: add pedantic mode support
Add mcheck_pedantic_prehook() calls to dlmalloc, dlrealloc,
dlmemalign, and dlcalloc wrapper functions. Also add the
mcheck_pedantic() and mcheck_check_all() API functions.

The pedantic mode is runtime controlled, so the registry hooks
are called on every allocation operation.

Changes from original commit:
- Uses dl* function names instead of mALLOc style names

Signed-off-by: Eugene Uriev <eugeneuriev@gmail.com>
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
(cherry picked from commit 18c1bfafe0)
2025-12-01 16:57:15 +00:00
Simon Glass
e29c8176f4 mcheck: support memalign
Implement the dlmemalign wrapper function for mcheck heap protection.
Uses mcheck_memalign_prehook() and mcheck_memalign_posthook() to
properly handle aligned allocations.

Changes from original commit:
- Uses dlmemalign/dlmemalign_impl instead of mEMALIGn/mEMALIGn_impl

Signed-off-by: Eugene Uriev <eugeneuriev@gmail.com>
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
(cherry picked from commit ae838768d7)
2025-12-01 16:57:15 +00:00
Simon Glass
8bf36da37c mcheck: integrate mcheck into dlmalloc.c
Add mcheck wrapper functions for dlmalloc, dlfree, dlrealloc,
dlmemalign, and dlcalloc. When MCHECK_HEAP_PROTECTION is enabled,
these wrappers call the mcheck hooks around the internal *_impl
functions to provide heap corruption detection.

Also add the mcheck() and mprobe() API functions.

Changes from original commit:
- Adapted for dlmalloc 2.8.6 function names (dl* instead of mALLOc)
- Updated function signatures (void* instead of Void_t*)

Signed-off-by: Eugene Uriev <eugeneuriev@gmail.com>
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
(cherry picked from commit 151493a875)
2025-12-01 16:57:15 +00:00
Simon Glass
2bc5cc784a mcheck: Use memset/memcpy instead of MALLOC_ZERO/MALLOC_COPY for mcheck.
These fast helpers sometimes breach mem-chunk boundaries.
Thus they trigger mcheck alarm. Standard ones are accurate though.

When MCHECK_HEAP_PROTECTION is enabled, redefine MALLOC_ZERO and
MALLOC_COPY to use standard memset/memcpy instead of the optimized
versions that may access memory outside allocated chunks.

Signed-off-by: Eugene Uriev <eugeneuriev@gmail.com>
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
(cherry picked from commit dfba071ddc)
2025-12-01 16:57:15 +00:00
Simon Glass
2cb547df96 mcheck: prepare +1 tier for mcheck-wrappers, in dl-*alloc commands
Add STATIC_IF_MCHECK macro and rename the main allocation functions
to *_impl versions (dlmalloc_impl, dlfree_impl, dlrealloc_impl,
dlmemalign_impl, dlcalloc_impl) to prepare for mcheck wrappers.

When MCHECK_HEAP_PROTECTION is not defined, the *_impl macros map
directly to the original function names, so behavior is unchanged.

Changes from original commit:
- Adapted to new dlmalloc 2.8.6 function names (dl* vs mALLOc, etc.)
- Updated all internal calls to use *_impl versions

Signed-off-by: Eugene Uriev <eugeneuriev@gmail.com>
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
(cherry picked from commit c82ff48115)
2025-12-01 16:57:15 +00:00
Simon Glass
371eceab7d dlmalloc: Fix a warning with clang-15
Add (void) to dlmalloc_stats() function definition to match its
declaration and avoid the clang-15 warning about function declarations
without prototypes.

Signed-off-by: Tom Rini <trini@konsulko.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
Co-developed-by: Claude <noreply@anthropic.com>
Signed-off-by: Simon Glass <simon.glass@canonical.com>
(cherry picked from commit f88d48cc74)
2025-12-01 16:57:15 +00:00