fix(esp_common): Remove alignement in ojects placced in specific sections

Let the compiler use variabel natural alignment
This commit is contained in:
Guillaume Souchere
2026-03-12 13:26:31 +01:00
parent dde91039fc
commit 51d2cc2245
7 changed files with 116 additions and 3 deletions
+6 -2
View File
@@ -252,7 +252,7 @@ FORCE_INLINE_ATTR TYPE& operator<<=(TYPE& a, int b) { a = a << b; return a; }
#include <mach-o/dyld.h>
#define _SECTION_ATTR_IMPL_GENERIC(SECTION, COUNTER) \
__attribute__((used, aligned(4), section("__DATA," SECTION)))
__attribute__((used, section("__DATA," SECTION)))
#define PLACE_IN_SECTION(SECTION) _SECTION_ATTR_IMPL_GENERIC(SECTION, __COUNTER__)
@@ -278,8 +278,12 @@ FORCE_INLINE_ATTR TYPE& operator<<=(TYPE& a, int b) { a = a << b; return a; }
#else /* ELF targets (Linux and embedded) */
/* Use the variable's own natural alignment so that pointer arithmetic over
* the section (end - start) gives the correct entry count with no padding gaps.
* On 32-bit embedded targets uint32_t aligns to 4; on 64-bit hosts a struct
* with a pointer member aligns to 8 — both correct without an explicit override. */
#define _SECTION_ATTR_IMPL_GENERIC(SECTION, COUNTER) \
__attribute__((used, aligned(4), section("." SECTION "." _COUNTER_STRINGIFY(COUNTER))))
__attribute__((used, section("." SECTION "." _COUNTER_STRINGIFY(COUNTER))))
#define PLACE_IN_SECTION(SECTION) _SECTION_ATTR_IMPL_GENERIC(SECTION, __COUNTER__)
@@ -4,7 +4,8 @@
* SPDX-License-Identifier: Apache-2.0
*
* Linker script for the section macros test on Linux host builds.
* Collects all uint32_t entries placed in the .test_data_table section.
* Collects all uint32_t entries placed in the .test_data_table section,
* and all test_ptr_entry_t entries placed in the .test_ptr_table section.
*/
SECTIONS
@@ -15,5 +16,12 @@ SECTIONS
KEEP(*(SORT(.test_data_table*)))
PROVIDE(_test_data_table_end = .);
}
.test_ptr_table :
{
PROVIDE(_test_ptr_table_start = .);
KEEP(*(SORT(.test_ptr_table*)))
PROVIDE(_test_ptr_table_end = .);
}
}
INSERT AFTER .data;
@@ -5,6 +5,7 @@
*/
#include "esp_attr.h"
#include "test_ptr_entry.h"
#include <stdint.h>
/*
@@ -14,3 +15,14 @@
static const uint32_t entry_a1 PLACE_IN_SECTION("test_data_table") = 0xDEADBEEF;
static const uint32_t entry_a2 PLACE_IN_SECTION("test_data_table") = 0xCAFEBABE;
static const uint32_t entry_a3 PLACE_IN_SECTION("test_data_table") = 0x12345678;
/*
* Two pointer-containing struct entries from translation unit A.
* Fields cover every data type size: pointer, u64, u32, u16, u8.
*/
static const test_ptr_entry_t ptr_a1 PLACE_IN_SECTION("test_ptr_table") = {
.name = "ptr_a1", .u32 = 0xA1A2A3A4, .u16 = 0xA5A6, .u8 = 0xA7
};
static const test_ptr_entry_t ptr_a2 PLACE_IN_SECTION("test_ptr_table") = {
.name = "ptr_a2", .u32 = 0xB1B2B3B4, .u16 = 0xB5B6, .u8 = 0xB7
};
@@ -5,6 +5,7 @@
*/
#include "esp_attr.h"
#include "test_ptr_entry.h"
#include <stdint.h>
/*
@@ -14,3 +15,10 @@
*/
static const uint32_t entry_b1 PLACE_IN_SECTION("test_data_table") = 0xAAAAAAAA;
static const uint32_t entry_b2 PLACE_IN_SECTION("test_data_table") = 0x55555555;
/*
* One pointer-containing struct entry from translation unit B.
*/
static const test_ptr_entry_t ptr_b1 PLACE_IN_SECTION("test_ptr_table") = {
.name = "ptr_b1", .u32 = 0xC1C2C3C4, .u16 = 0xC5C6, .u8 = 0xC7
};
@@ -0,0 +1,26 @@
/*
* SPDX-FileCopyrightText: 2026 Espressif Systems (Shanghai) CO LTD
*
* SPDX-License-Identifier: Apache-2.0
*/
#pragma once
#include <stdint.h>
/**
* A struct covering every fundamental data type size, used to verify that
* PLACE_IN_SECTION() correctly places and aligns section entries on both
* 32-bit embedded targets and 64-bit host builds (Linux/macOS).
*
* Layout (no padding on any platform when members are in descending size order):
* ptr : pointer — 8 bytes on 64-bit, 4 bytes on 32-bit
* u32 : uint32_t — 4 bytes
* u16 : uint16_t — 2 bytes
* u8 : uint8_t — 1 byte
*/
typedef struct {
const char *name; /* pointer — drives struct alignment on 64-bit */
uint32_t u32;
uint16_t u16;
uint8_t u8;
} test_ptr_entry_t;
@@ -7,7 +7,9 @@
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include "esp_attr.h"
#include "test_ptr_entry.h"
/*
* Test for the portable link-time section macros defined in esp_attr.h.
@@ -21,6 +23,7 @@
*/
_SECTION_ATTR_SYMBOL_DECL_GENERIC(uint32_t, test_data_table)
_SECTION_ATTR_SYMBOL_DECL_GENERIC(test_ptr_entry_t, test_ptr_table)
/* Expected values — order is linker-determined, so we check membership */
static const uint32_t expected_values[] = {
@@ -78,4 +81,54 @@ void app_main(void)
}
printf("SUCCESS: All %zu section entries verified.\n", count);
/* ------------------------------------------------------------------ */
/* Part 2: pointer-containing struct section */
/* ------------------------------------------------------------------ */
/* expected entries — all fields checked to ensure no data corruption */
static const test_ptr_entry_t expected_ptr[] = {
{ .name = "ptr_a1", .u32 = 0xA1A2A3A4, .u16 = 0xA5A6, .u8 = 0xA7 },
{ .name = "ptr_a2", .u32 = 0xB1B2B3B4, .u16 = 0xB5B6, .u8 = 0xB7 },
{ .name = "ptr_b1", .u32 = 0xC1C2C3C4, .u16 = 0xC5C6, .u8 = 0xC7 },
};
#define EXPECTED_PTR_COUNT (sizeof(expected_ptr) / sizeof(expected_ptr[0]))
const test_ptr_entry_t *pstart = _SECTION_START(test_ptr_table);
const test_ptr_entry_t *pend = _SECTION_END(test_ptr_table);
size_t pcount = (size_t)(pend - pstart);
printf("Pointer section entry count: %zu (expected %zu)\n",
pcount, (size_t)EXPECTED_PTR_COUNT);
if (pcount != EXPECTED_PTR_COUNT) {
printf("FAIL: pointer section entry count mismatch\n");
exit(1);
}
/* Check each expected entry is present and pointer is valid */
for (size_t i = 0; i < EXPECTED_PTR_COUNT; i++) {
int found = 0;
for (size_t j = 0; j < pcount; j++) {
/* Verify the pointer is non-NULL and dereferenceable */
if (pstart[j].name == NULL) {
printf("FAIL: entry %zu has NULL name pointer (alignment issue?)\n", j);
exit(1);
}
if (strcmp(pstart[j].name, expected_ptr[i].name) == 0 &&
pstart[j].u32 == expected_ptr[i].u32 &&
pstart[j].u16 == expected_ptr[i].u16 &&
pstart[j].u8 == expected_ptr[i].u8) {
found = 1;
break;
}
}
if (!found) {
printf("FAIL: expected pointer entry {%s} not found or fields corrupted\n",
expected_ptr[i].name);
exit(1);
}
}
printf("SUCCESS: All %zu pointer section entries verified.\n", pcount);
}
@@ -10,6 +10,7 @@ from pytest_embedded_idf.utils import idf_parametrize
@idf_parametrize('target', ['linux'], indirect=['target'])
def test_section_macros(dut: Dut) -> None:
dut.expect('SUCCESS: All 5 section entries verified.')
dut.expect('SUCCESS: All 3 pointer section entries verified.')
@pytest.mark.host_test
@@ -17,3 +18,4 @@ def test_section_macros(dut: Dut) -> None:
@idf_parametrize('target', ['linux'], indirect=['target'])
def test_section_macros_macos(dut: Dut) -> None:
dut.expect('SUCCESS: All 5 section entries verified.')
dut.expect('SUCCESS: All 3 pointer section entries verified.')