얼마 전에 아래 패치를 봤어요. 이게 뭐지? 잘 이해가 안 가더라구요.
배열을 초기화하는 것 같기도 한데.
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
index ce7cd96..fb252ec 100644
--- a/drivers/usb/dwc3/debugfs.c
+++ b/drivers/usb/dwc3/debugfs.c
@@ -402,7 +402,7 @@ static ssize_t dwc3_mode_write(struct file *file,
struct dwc3 *dwc = s->private;
unsigned long flags;
u32 mode = 0;
- char buf[32];
+ char buf[32] = {0};
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
@@ -482,7 +482,7 @@ static ssize_t dwc3_testmode_write(struct file *file,
struct dwc3 *dwc = s->private;
unsigned long flags;
u32 testmode = 0;
- char buf[32];
+ char buf[32] = {0};
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
@@ -589,7 +589,7 @@ static ssize_t dwc3_link_state_write(struct file *file,
struct dwc3 *dwc = s->private;
unsigned long flags;
enum dwc3_link_state state = 0;
- char buf[32];
+ char buf[32] = {0};
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
return -EFAULT;
@@ -630,12 +630,10 @@ static ssize_t dwc3_store_ep_num(struct file *file, const char __user *ubuf,
{
struct seq_file *s = file->private_data;
struct dwc3 *dwc = s->private;
- char kbuf[10];
+ char kbuf[10] = {0};
unsigned int num, dir, temp;
unsigned long flags;
- memset(kbuf, 0, 10);
-
if (copy_from_user(kbuf, ubuf, count > 10 ? 10 : count))
return -EFAULT;
|
한 가지 이해가 안 간건. 위 코드에서 왜? memset이란 API를 뺐을까요?
커널 패치를 컴파일 한 다음에, 위 패치 반영 전과 후를 비교해보았어요.
아래 ARM instruction은 패치 적용 전 코드인데요, c0629e08 주소에서 __copy_from_user() 함수를
Branch 명령어로 이동하는 Instruction 이외에 특이 코드는 없네요.
static ssize_t dwc3_mode_write(struct file *file,
const char __user *ubuf, size_t count, loff_t *ppos)
{
c0629d9c: e1a0c00d mov ip, sp
c0629da0: e92ddbf0
{r4, r5, r6, r7, r8, r9, fp, ip, lr, pc}
c0629da4: e24cb004 sub fp, ip, #4
c0629da8: e24dd028 sub sp, sp, #40 ; 0x28
c0629dac: e52de004 push {lr} ; (str lr, [sp, #-4]!)
c0629db0: ebe7958c bl c000f3e8 <__gnu_mcount_nc>
c0629db4: e1a05002 mov r5, r2
c0629db8: e59f2118 ldr r2, [pc, #280] ; c0629ed8 <dwc3_mode_write+0x13c>
c0629dbc: e5923000 ldr r3, [r2]
c0629dc0: e1a08002 mov r8, r2
c0629dc4: e50b3028 str r3, [fp, #-40] ; 0xffffffd8
c0629dc8: e59030bc ldr r3, [r0, #188] ; 0xbc
c0629dcc: e1a0000d mov r0, sp
c0629dd0: e3c0cd7f bic ip, r0, #8128 ; 0x1fc0
c0629dd4: e3ccc03f bic ip, ip, #63 ; 0x3f
c0629dd8: e5936060 ldr r6, [r3, #96] ; 0x60
c0629ddc: e355001f cmp r5, #31
c0629de0: 31a03005 movcc r3, r5
c0629de4: 23a0301f movcs r3, #31
c0629de8: e59cc008 ldr ip, [ip, #8]
c0629dec: e0910003 adds r0, r1, r3
c0629df0: 30d0000c sbcscc r0, r0, ip
c0629df4: 33a0c000 movcc ip, #0
c0629df8: e35c0000 cmp ip, #0
c0629dfc: 1a000005 bne c0629e18 <dwc3_mode_write+0x7c>
c0629e00: e24b0048 sub r0, fp, #72 ; 0x48
c0629e04: e1a02003 mov r2, r3
c0629e08: ebf2e301 bl c02e2a14 <__copy_from_user> //<<--
c0629e0c: e3500000 cmp r0, #0
자자, 이제 패치 적용 후 컴파일을해본 후 어셈블 코드 좀 확인해 보았어요.
근데 ARM GCC 컴파일가 다른 코드를 생성한 것 같아요. 좀 살펴보면,
[1]: R1에 0x0을 이동시킴.
[2]: R2에 32를 이동시킴
[3]: R0을 현재 스택 주소에서 0x48 떨어진 곳에 위치시킴(스택 공간을 주는 거죠)
[4]: 아래 포멧으로 memset 호출
memset(R0: buf, R1: 0x0, R2: 32)
static ssize_t dwc3_mode_write(struct file *file,
const char __user *ubuf, size_t count, loff_t *ppos)
{
c0629d9c: e1a0c00d mov ip, sp
c0629da0: e92ddbf0 push {r4, r5, r6, r7, r8, r9, fp, ip, lr, pc}
c0629da4: e24cb004 sub fp, ip, #4
c0629da8: e24dd028 sub sp, sp, #40 ; 0x28
c0629dac: e52de004 push {lr} ; (str lr, [sp, #-4]!)
c0629db0: ebe7958c bl c000f3e8 <__gnu_mcount_nc>
c0629db4: e59f7130 ldr r7, [pc, #304] ; c0629eec <dwc3_mode_write+0x150>
c0629db8: e1a04001 mov r4, r1
c0629dbc: e1a05002 mov r5, r2
c0629dc0: e3a01000 mov r1, #0 //<<--[1]
c0629dc4: e3a02020 mov r2, #32 //<<--[2]
c0629dc8: e5973000 ldr r3, [r7]
c0629dcc: e50b3028 str r3, [fp, #-40] ; 0xffffffd8
c0629dd0: e59030bc ldr r3, [r0, #188] ; 0xbc
c0629dd4: e24b0048 sub r0, fp, #72 ; 0x48 //<<--[3]
c0629dd8: e5936060 ldr r6, [r3, #96] ; 0x60
c0629ddc: ebf2ec6f bl c02e4fa0 <memset> //<<--[4]
c0629de0: e1a0200d mov r2, sp
c0629de4: e3c21d7f bic r1, r2, #8128 ; 0x1fc0
c0629de8: e3c1103f bic r1, r1, #63 ; 0x3f
c0629dec: e355001f cmp r5, #31
c0629df0: 31a03005 movcc r3, r5
c0629df4: 23a0301f movcs r3, #31
c0629df8: e591c008 ldr ip, [r1, #8]
c0629dfc: e0942003 adds r2, r4, r3
c0629e00: 30d2200c sbcscc r2, r2, ip
c0629e04: 33a0c000 movcc ip, #0
c0629e08: e35c0000 cmp ip, #0
c0629e0c: 1a000006 bne c0629e2c <dwc3_mode_write+0x90>
c0629e10: e24b0048 sub r0, fp, #72 ; 0x48
c0629e14: e1a01004 mov r1, r4
c0629e18: e1a02003 mov r2, r3
c0629e1c: ebf2e2fc bl c02e2a14 <__copy_from_user>
우아...
char buf[32] = {0}; 와 같이 선언하니 ARM GCC compiler가 친절하게도 memset을 붙혀서
0x0으로 초기화 시켜주네요. char buf[32] = {0}; 구문을 자주 쓰도록 합시다. 그리고 C 코드가 어셈블 코드로 어떻게 변환되는 지도 종종 확인해야 할 것 같아요.
그리고, 위 패치를 작성하신 분은 이미 이 원리를 알고 있었던 것 같아요.
'[Debugging] Tips' 카테고리의 다른 글
[Linux][Kernel] T32 - Linked List 디버깅 cmm Script (0) | 2023.05.04 |
---|---|
[리눅스커널][디버깅] Red Hat Crash-Utility(크래시 유틸리티) 설치 (0) | 2023.05.04 |
[Linux][Kernel] ftrace: stack tracer (0) | 2023.05.04 |
tombstone 시(시스템 크래시) - 커널 패닉 유발 (0) | 2023.05.04 |
특정 CPU를 끄는 패치(특정 CPU에서 커널 크래시) (0) | 2023.05.04 |