mirror of
https://github.com/espressif/esp-idf.git
synced 2026-04-27 19:13:21 +00:00
fix(esp_common): Remove alignement in ojects placced in specific sections
Let the compiler use variabel natural alignment
This commit is contained in:
@@ -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.')
|
||||
|
||||
Reference in New Issue
Block a user