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>
|
#include <mach-o/dyld.h>
|
||||||
|
|
||||||
#define _SECTION_ATTR_IMPL_GENERIC(SECTION, COUNTER) \
|
#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__)
|
#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) */
|
#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) \
|
#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__)
|
#define PLACE_IN_SECTION(SECTION) _SECTION_ATTR_IMPL_GENERIC(SECTION, __COUNTER__)
|
||||||
|
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
* Linker script for the section macros test on Linux host builds.
|
* 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
|
SECTIONS
|
||||||
@@ -15,5 +16,12 @@ SECTIONS
|
|||||||
KEEP(*(SORT(.test_data_table*)))
|
KEEP(*(SORT(.test_data_table*)))
|
||||||
PROVIDE(_test_data_table_end = .);
|
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;
|
INSERT AFTER .data;
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
|
#include "test_ptr_entry.h"
|
||||||
#include <stdint.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_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_a2 PLACE_IN_SECTION("test_data_table") = 0xCAFEBABE;
|
||||||
static const uint32_t entry_a3 PLACE_IN_SECTION("test_data_table") = 0x12345678;
|
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 "esp_attr.h"
|
||||||
|
#include "test_ptr_entry.h"
|
||||||
#include <stdint.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_b1 PLACE_IN_SECTION("test_data_table") = 0xAAAAAAAA;
|
||||||
static const uint32_t entry_b2 PLACE_IN_SECTION("test_data_table") = 0x55555555;
|
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 <stdio.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
#include "esp_attr.h"
|
#include "esp_attr.h"
|
||||||
|
#include "test_ptr_entry.h"
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Test for the portable link-time section macros defined in esp_attr.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(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 */
|
/* Expected values — order is linker-determined, so we check membership */
|
||||||
static const uint32_t expected_values[] = {
|
static const uint32_t expected_values[] = {
|
||||||
@@ -78,4 +81,54 @@ void app_main(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
printf("SUCCESS: All %zu section entries verified.\n", count);
|
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'])
|
@idf_parametrize('target', ['linux'], indirect=['target'])
|
||||||
def test_section_macros(dut: Dut) -> None:
|
def test_section_macros(dut: Dut) -> None:
|
||||||
dut.expect('SUCCESS: All 5 section entries verified.')
|
dut.expect('SUCCESS: All 5 section entries verified.')
|
||||||
|
dut.expect('SUCCESS: All 3 pointer section entries verified.')
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.host_test
|
@pytest.mark.host_test
|
||||||
@@ -17,3 +18,4 @@ def test_section_macros(dut: Dut) -> None:
|
|||||||
@idf_parametrize('target', ['linux'], indirect=['target'])
|
@idf_parametrize('target', ['linux'], indirect=['target'])
|
||||||
def test_section_macros_macos(dut: Dut) -> None:
|
def test_section_macros_macos(dut: Dut) -> None:
|
||||||
dut.expect('SUCCESS: All 5 section entries verified.')
|
dut.expect('SUCCESS: All 5 section entries verified.')
|
||||||
|
dut.expect('SUCCESS: All 3 pointer section entries verified.')
|
||||||
|
|||||||
Reference in New Issue
Block a user