ARM Cortex-M7 Function Address Mismatch Between Map File and Runtime

When working with ARM Cortex-M7 processors, a common issue that developers encounter is a discrepancy between the function address specified in the map file and the address observed during runtime. This issue can be particularly perplexing when debugging or verifying the memory layout of an embedded application. In this post, we will delve into the reasons behind this discrepancy, explore the underlying causes, and provide detailed troubleshooting steps to resolve the issue.

Thumb-2 Instruction Set and Function Address Alignment

The ARM Cortex-M7 processor utilizes the Thumb-2 instruction set, which is a blend of 16-bit and 32-bit instructions designed to improve code density and performance. One of the key characteristics of the Thumb-2 instruction set is that function addresses are often aligned with the least significant bit (LSB) set to 1. This is because the Thumb-2 instruction set uses this bit to indicate that the code is in Thumb state, as opposed to ARM state, which is not used in Cortex-M series processors.

In the context of the provided issue, the function VhicDebugUartInit has an address of 0x00473dbc in the map file, but when printed during runtime, the address is 0x00473DCB. The difference between these two addresses is more than just the LSB being set. The map file address 0x00473dbc is the base address of the function, while the runtime address 0x00473DCB includes additional offsets due to the Thumb-2 instruction set and potential alignment requirements.

The Thumb-2 instruction set requires that function addresses be aligned to 2 bytes, and the LSB of the address is used to indicate the Thumb state. When the function address is printed during runtime, the LSB is set to 1, indicating that the function is in Thumb state. However, the map file typically lists the base address without this bit set, leading to the observed discrepancy.

Memory Layout and Section Alignment in Map Files

The map file generated by the linker provides a detailed view of the memory layout of the application, including the addresses of functions, variables, and sections. The map file address 0x00473dbc corresponds to the base address of the function VhicDebugUartInit within the .text section. However, the runtime address 0x00473DCB includes additional offsets due to section alignment and the Thumb-2 instruction set.

In the provided example, the .ARM.exidx section is associated with the function VhicDebugUartInit. The .ARM.exidx section contains exception handling information and is typically placed immediately after the function code. The size of the .ARM.exidx section for VhicDebugUartInit is 0x10 bytes, as indicated in the map file. This section alignment can cause the runtime address of the function to differ from the map file address.

Additionally, the map file may not account for certain runtime adjustments made by the compiler or linker, such as the insertion of padding bytes for alignment or the inclusion of exception handling information. These adjustments can lead to differences between the map file address and the runtime address.

Debugging and Verifying Function Addresses in Cortex-M7

To resolve the discrepancy between the map file address and the runtime address, it is essential to understand how the compiler, linker, and runtime environment interact. The following steps provide a detailed approach to debugging and verifying function addresses in an ARM Cortex-M7 application:

  1. Verify the Map File Address: The first step is to confirm the address of the function VhicDebugUartInit in the map file. The map file should list the base address of the function within the .text section. In this case, the map file address is 0x00473dbc.

  2. Inspect the Runtime Address: When printing the address of the function during runtime, ensure that the correct format specifier is used. In C, the %p format specifier should be used to print pointers, as it correctly handles pointer sizes and formatting. The runtime address 0x00473DCB should be printed using printf("VhicDebugUartInit at %p", VhicDebugUartInit);.

  3. Check the Thumb-2 Instruction Set: Verify that the function is compiled using the Thumb-2 instruction set. The LSB of the runtime address should be set to 1, indicating that the function is in Thumb state. The difference between the map file address 0x00473dbc and the runtime address 0x00473DCB is due to the Thumb-2 instruction set and section alignment.

  4. Examine Section Alignment: Review the memory layout in the map file to understand how sections are aligned. The .ARM.exidx section, which contains exception handling information, is placed immediately after the function code. The size of this section is 0x10 bytes, which can cause the runtime address to differ from the map file address.

  5. Use a Debugger to Inspect Addresses: Load the application into a debugger and inspect the address of the function VhicDebugUartInit. The debugger should display the runtime address, which should match the address printed during runtime. This step helps confirm that the discrepancy is not due to a printing error.

  6. Review Compiler and Linker Settings: Ensure that the compiler and linker settings are consistent with the requirements of the ARM Cortex-M7 processor. The compiler should be configured to generate Thumb-2 code, and the linker should align sections according to the processor’s memory model.

  7. Check for Padding and Alignment: The compiler may insert padding bytes to align functions or sections. Review the map file and the generated binary to identify any padding bytes that may affect the function address.

  8. Validate Exception Handling Information: The .ARM.exidx section contains exception handling information that may affect the function address. Ensure that this section is correctly aligned and that its size is accounted for in the map file.

By following these steps, developers can identify and resolve discrepancies between the map file address and the runtime address of functions in an ARM Cortex-M7 application. Understanding the interaction between the Thumb-2 instruction set, section alignment, and runtime adjustments is crucial for accurate memory layout verification and debugging.

Implementing Correct Pointer Formatting and Debugging Techniques

To ensure accurate address printing and debugging, it is essential to use the correct pointer formatting and debugging techniques. The following guidelines provide a detailed approach to implementing these techniques:

  1. Use the Correct Format Specifier: When printing pointers in C, always use the %p format specifier. This specifier correctly handles pointer sizes and formatting, ensuring that the address is printed accurately. For example, use printf("VhicDebugUartInit at %p", VhicDebugUartInit); to print the address of the function VhicDebugUintInit.

  2. Inspect the Map File: The map file provides a detailed view of the memory layout, including the addresses of functions, variables, and sections. Review the map file to understand the base address of the function and the alignment of sections. The map file address 0x00473dbc should be used as a reference when comparing with the runtime address.

  3. Verify Thumb-2 Code Generation: Ensure that the compiler is configured to generate Thumb-2 code. The Thumb-2 instruction set requires that function addresses have the LSB set to 1, indicating Thumb state. The runtime address 0x00473DCB should have the LSB set to 1, confirming that the function is in Thumb state.

  4. Check Section Alignment in the Map File: The map file should indicate the alignment of sections, including the .text and .ARM.exidx sections. The .ARM.exidx section, which contains exception handling information, is typically placed immediately after the function code. The size of this section is 0x10 bytes, which can cause the runtime address to differ from the map file address.

  5. Use a Debugger to Inspect Addresses: Load the application into a debugger and inspect the address of the function VhicDebugUartInit. The debugger should display the runtime address, which should match the address printed during runtime. This step helps confirm that the discrepancy is not due to a printing error.

  6. Review Compiler and Linker Settings: Ensure that the compiler and linker settings are consistent with the requirements of the ARM Cortex-M7 processor. The compiler should be configured to generate Thumb-2 code, and the linker should align sections according to the processor’s memory model.

  7. Check for Padding and Alignment: The compiler may insert padding bytes to align functions or sections. Review the map file and the generated binary to identify any padding bytes that may affect the function address.

  8. Validate Exception Handling Information: The .ARM.exidx section contains exception handling information that may affect the function address. Ensure that this section is correctly aligned and that its size is accounted for in the map file.

By following these guidelines, developers can ensure accurate address printing and debugging, reducing the likelihood of discrepancies between the map file address and the runtime address. Understanding the interaction between the Thumb-2 instruction set, section alignment, and runtime adjustments is crucial for accurate memory layout verification and debugging.

Conclusion

The discrepancy between the map file address and the runtime address of a function in an ARM Cortex-M7 application is a common issue that can be resolved by understanding the Thumb-2 instruction set, section alignment, and runtime adjustments. By following the detailed troubleshooting steps outlined in this post, developers can identify and resolve these discrepancies, ensuring accurate memory layout verification and debugging. Proper use of pointer formatting, map file inspection, and debugging techniques is essential for maintaining the integrity of the application’s memory layout and ensuring reliable system implementations.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *