Recently I encountered a program crash with an unusual SIGILL. I debugged it.
Core was generated by `/usr/bin/xxxxx'.
Program terminated with signal SIGILL, Illegal instruction
GDB checked and crashed in the free function
(gdb) disassemble
Dump of assembler code for function free:
0xb6f408f0 <+0>: cmp r0, #0
0xb6f408f4 <+4>: bxeq lr
0xb6f408f8 <+8>: ldr r3, [r0, #-4]
0xb6f408fc <+12>: push {r4, r5, r6, r7, r8, r9, r10, r11, lr}
0xb6f40900 <+16>: tst r3, #1
0xb6f40904 <+20>: bic r8, r3, #1
0xb6f40908 <+24>: sub sp, sp, #20
0xb6f4090c <+28>: sub r4, r0, #8
0xb6f40910 <+32>: bne 0xb6f40938 0xb6f40914 <+36>: ldr r3, [r0, #-8] 0xb6f40918 <+40>: sub r0, r4, r3 0xb6f4091c <+44>: tst r3, #1 0xb6f40920 <+48>: add r1, r8, r3 0xb6f40924 <+52>: beq 0xb6f4092c => 0xb6f40928 <+56>: udf #0 0xb6f4092c <+60>: add sp, sp, #20 0xb6f40930 <+64>: pop {r4, r5, r6, r7, r8, r9, r10, r11, lr} 0xb6f40934 <+68>: b 0xb6f5c620 <__munmap> There is indeed a udf instruction in the free function View musk's free function implementation void free(void *p) { struct chunk *self = MEM_TO_CHUNK(p); struct chunk *next; size_t final_size, new_size, size; int reclaim=0; int i; if (!p) return; if (IS_MMAPPED(self)) { size_t extra = self->psize; char *base = (char *)self - extra; size_t len = CHUNK_SIZE(self) + extra; /* Crash on double free */ if (extra & 1) a_crash(); __munmap(base, len); return; } static inline void a_crash() { __asm__ __volatile__( #ifndef __thumb__ ".word 0xe7f000f0" #else ".short 0xdeff" #endif : : : "memory"); } When musl finds that the memory may be double freed, it will actively call a_crash(), that is, insert an arm udf instruction to actively trap the program crash. In fact, if you think about it, this is more scientific, and it can avoid the problem of memory list trashing caused by double free in some allocator implementations. Usually, the double free is fine. The program will crash in a place far away. It is very painful to debug. While Googling this question, I found another interesting problem: the gcc compiler will also actively insert UDF instructions This is a problem encountered by others on the forum question The function written in C language to determine whether to start from nor or nand was not fully compiled during compilation and linking. The disassembly result is as follows (the part in red font). Please help me find out the reason. Thank you! The c function is as follows: int isBootFromNorFlash(void) { volatile int *p = (volatile int *)0; int val; val = *p; *p = 0x12345678; if (*p == 0x12345678) { *p = val; puts("boot from nor.nr"); return 0; } else { puts("boot from nand.nr"); return 1; } } The disassembly results are as follows. In the red font part, only the first few lines of commands are compiled, and the rest are not compiled. 33f80304 33f80304: e3a03000 mov r3, #0 33f80308: e5933000 ldr r3, [r3] 33f8030c: e7f000f0 udf #0 In fact, this is a feature of arm gcc. When undefined behavior is detected, it will actively insert udf instructions to trap the exception. GCC6 and later can detect this error during compilation via -Wnull-dereference. ktkachov 2017-07-27 09:28:26 UTC That inst is the trap instruction that is inserted by the isolate-paths pass because it detects undefined behaviour. While the result of calling data() is unspecified, this is not what the testcase is doing. It's using operator[] which performs an access to the underlying storage directly and is thus out of bounds and undefined
Previous article:Analyze the functions of different working modes of ARM processors and illustrate the switching process with examples
Next article:ARM cortexM4 exception handling(1)
- Popular Resources
- Popular amplifiers
- Learn ARM development(16)
- Learn ARM development(17)
- Learn ARM development(18)
- Embedded system debugging simulation tool
- A small question that has been bothering me recently has finally been solved~~
- Learn ARM development (1)
- Learn ARM development (2)
- Learn ARM development (4)
- Learn ARM development (6)
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- LED chemical incompatibility test to see which chemicals LEDs can be used with
- Application of ARM9 hardware coprocessor on WinCE embedded motherboard
- What are the key points for selecting rotor flowmeter?
- LM317 high power charger circuit
- A brief analysis of Embest's application and development of embedded medical devices
- Single-phase RC protection circuit
- stm32 PVD programmable voltage monitor
- Introduction and measurement of edge trigger and level trigger of 51 single chip microcomputer
- Improved design of Linux system software shell protection technology
- What to do if the ABB robot protection device stops
- ASML predicts that its revenue in 2030 will exceed 457 billion yuan! Gross profit margin 56-60%
- Detailed explanation of intelligent car body perception system
- How to solve the problem that the servo drive is not enabled
- Why does the servo drive not power on?
- What point should I connect to when the servo is turned on?
- How to turn on the internal enable of Panasonic servo drive?
- What is the rigidity setting of Panasonic servo drive?
- How to change the inertia ratio of Panasonic servo drive
- What is the inertia ratio of the servo motor?
- Is it better for the motor to have a large or small moment of inertia?
- 【NUCLEO-L552ZE Review】-2: Stay in TrustZone
- RAM with integrated power backup
- TMS320xF24xx to C2000 Piccolo TMS320F280xx Migration Overview
- What should I do if my phone screen is broken?
- Active Crystal Oscillator - Voltage Controlled Oscillator
- 【TI recommended course】# Hall position sensor application overview#
- 8051 single chip ultrasonic transceiver split ruler (GPS / BDS chip PPS signal as time synchronization, synchronization error is about ten...
- MicroPython officially releases pyb D series development board
- Ask for the direction positioning principle of Bluetooth 5.1
- A few pictures help you easily understand DDR crosstalk