ARM Linux Crash Analysis-Application Segmentation fault Analysis

Posted by dadamssg on Wed, 08 May 2019 22:09:07 +0200

I. Test Code

The test code is as follows:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>


void getmemory(char *p)
{
	p=(char *)malloc(100);
	strcpy(p,"helloworld");
	return;
}
void test1_printf()
{
	printf("aefawfaeeaa  /n");
	return;
}


void test1_printf2()
{
	int bbb  = 0x5555;
	
	printf("test = %d  /n",bbb);
	return;
}


void test1_printf3()
{
	printf("aefawfaeeaa  /n");
	return;
}


void test1_printf4()
{
	int bbb  = 0x5555;
	
	printf("test = %d  /n",bbb);
	return;
}



void teswtaaaaa(void )
{
		char*str=NULL;
	getmemory(str);
	*str = 12;
	printf("%s /n",str);
	return;
}




int main(int argc,char *argv[])
{
	test1_printf();

	test1_printf2();
	

	teswtaaaaa();


	test1_printf3();


	test1_printf4();

	
	
#if 0
	char strss[10] = {0};
	strss[11] = 6;
	
	printf("%s /n",strss);
	
#endif


	return 0;
}

Compilation takes Hisi3559A as an example:
Generation.o: aarch64-himix100-linux-g C C-C test.c-Wall-Werror-g
Generate executable file: aarch64-himix100-linux-gcc-o test.o-Wall-Werror-g

Explain:
- Wall: The option opens all of the most commonly used compilation warnings, strongly recommended, to catch many of the most common errors in C programming.
- Werror: Treat warnings as errors
- g:. Create a symbol table that contains a list of variable names used in the program.
Close all optimization mechanisms so that the original C code is strictly followed during program execution

II. Test Running

Put it on board and execute:
There was a mistake.
The error message is as follows:

test[1775]: unhandled level 2 translation fault (11) at 0x00000000, esr 0x92000046
pgd = ffffffc020807000
[00000000] *pgd=00000000617ac003, *pud=00000000617ac003
, *pmd=0000000000000000

CPU: 1 PID: 1775 Comm: test Tainted: P           O    4.9.37 #1
Hardware name: Hisilicon HI3559AV100 DEMO Board (DT)
task: ffffffc021f53000 task.stack: ffffffc02100c000
PC is at 0x4006d8
LR is at 0x4006d0
pc : [<00000000004006d8>] lr : [<00000000004006d0>] pstate: 60000000
sp : 0000007ffbbcae20
x29: 0000007ffbbcae20 x28: 0000000000000000 
x27: 0000000000000000 x26: 0000000000000000 
x25: 0000000000000000 x24: 0000000000000000 
x23: 0000000000000000 x22: 0000000000000000 
x21: 0000000000400490 x20: 0000000000000000 
x19: 0000000000400728 x18: 0000000000000000 
x17: 0000000000411000 x16: 0000007fabc52780 
x15: 0000000000000482 x14: 0000000000000005 
x13: 0000000000000000 x12: 0000000000000000 
x11: 0000000000000018 x10: 0101010101010101 
x9 : ffffff80ffffffc8 x8 : 0000000000000003 
x7 : 000000000000007b x6 : 000000006e2f2020 
x5 : 0000000000000071 x4 : 0000000000413020 
x3 : 0000000000000071 x2 : 726f776f6c6c6568 
x1 : 000000000000000c x0 : 0000000000000000 

3. Error Analysis

3.1 ARM PC Register

PC stands for program counter, pipeline uses three stages, so instructions are divided into three stages: 1. finger fetching (loading an instruction from memory); 2. decoding (identifying the instructions to be executed); 3. execution (processing instructions and writing the results back to the register). And R15 (PC) always points to "taking" instructions, not "executing" instructions or "decoding" instructions.

3.2 ARM LR registers:

The occurrence of exceptions will lead to the interruption of the normal operation of the program, and transfer the control flow to the corresponding exception handling (exception response). After some exceptions (fiq, irq) are processed, the system also hopes to return to the source program breakpoint where the original exceptions were interrupted and continue to complete the execution of the source program (exception return). This requires a solution for recording the source process. The breakpoint position of the order so that the correct exception returns.
Similarly, there are subroutine calls and returns. When calling a subroutine in the main program (by calling instructions through subroutines), it is also necessary to record the location of the call point in the main program for the return of future subroutines.
In ARM processors, R14 is used to record breakpoints and call points, even though R14 is used as a return connection register (LR). On hardware and instruction execution, the CPU automatically completes the recording of the corresponding return point. In ARM assembly language programming, R14 and LR are universal.
When the ARM processor is abnormal, it will automatically save the current PC to the LR register.

When an error occurs, the two registers have the following values:

PC is at 0x4006d8
LR is at 0x4006d0

3.4 nm command

3.4 nm command is used to display symbol table of binary object file

aarch64-himix100-linux-nm test

It is shown as follows:

         U abort@@GLIBC_2.17
0000000000411040 B __bss_end__
0000000000411040 B _bss_end__
0000000000411038 B __bss_start
0000000000411038 B __bss_start__
00000000004004d8 t call_weak_fn
0000000000411038 b completed.7391
0000000000411028 D __data_start
0000000000411028 W data_start
00000000004004f0 t deregister_tm_clones
0000000000400570 t __do_global_dtors_aux
0000000000410df8 t __do_global_dtors_aux_fini_array_entry
0000000000411030 D __dso_handle
0000000000410e08 d _DYNAMIC
0000000000411038 D _edata
0000000000411040 B _end
0000000000411040 B __end__
00000000004007a4 T _fini
00000000004005a0 t frame_dummy
0000000000410df0 t __frame_dummy_init_array_entry
00000000004007f8 r __FRAME_END__
00000000004005e0 T getmemory
0000000000410fd8 d _GLOBAL_OFFSET_TABLE_
                 w __gmon_start__
0000000000400408 T _init
0000000000410df8 t __init_array_end
0000000000410df0 t __init_array_start
00000000004007b8 R _IO_stdin_used
0000000000410e00 d __JCR_END__
0000000000410e00 d __JCR_LIST__
00000000004007a0 T __libc_csu_fini
0000000000400728 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.17
00000000004006f8 T main
                 U malloc@@GLIBC_2.17
                 U printf@@GLIBC_2.17
0000000000400530 t register_tm_clones
0000000000400490 T _start
0000000000400624 T test1_printf
0000000000400644 T test1_printf2
0000000000400670 T test1_printf3
0000000000400690 T test1_printf4
00000000004006bc T teswtaaaaa
0000000000411038 D __TMC_END__

3.5 objdump command

The objdump command is a command for disassembling object files or executable files under Linux. It allows you to learn more about the additional information that binary files may carry in a readable format.

 aarch64-himix100-linux-objdump -x -s -d test

Intercept part of the content:

00000000004006bc <teswtaaaaa>:
  4006bc:	a9be7bfd 	stp	x29, x30, [sp, #-32]!
  4006c0:	910003fd 	mov	x29, sp
  4006c4:	f9000fbf 	str	xzr, [x29, #24]
  4006c8:	f9400fa0 	ldr	x0, [x29, #24]
  4006cc:	97ffffc5 	bl	4005e0 <getmemory>
  4006d0:	f9400fa0 	ldr	x0, [x29, #24]
  4006d4:	52800181 	mov	w1, #0xc                   	// #12
  4006d8:	39000001 	strb	w1, [x0]
  4006dc:	90000000 	adrp	x0, 400000 <_init-0x408>
  4006e0:	911fc000 	add	x0, x0, #0x7f0
  4006e4:	f9400fa1 	ldr	x1, [x29, #24]
  4006e8:	97ffff66 	bl	400480 <printf@plt>
  4006ec:	d503201f 	nop
  4006f0:	a8c27bfd 	ldp	x29, x30, [sp], #32
  4006f4:	d65f03c0 	ret

You can see a specified error in the function teswtaaaaa

3.6 addr2line tool

Using the addr2line tool, sometimes you can use this tool directly to locate the number of rows in the application:

 addr2line  0x4006d8   -e test -f

Print as follows:

$ addr2line  0x4006d8   -e test -f
teswtaaaaa
/home/lie/code_test/test.c:49

End!

Topics: Linux Programming Assembly Language