얼마 전에 아래 패치를 봤어요. 이게 뭐지? 잘 이해가 안 가더라구요.
배열을 초기화하는 것 같기도 한데.
 
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 코드가 어셈블 코드로 어떻게 변환되는 지도 종종 확인해야 할 것 같아요.
 
 
그리고, 위 패치를 작성하신 분은 이미 이 원리를 알고 있었던 것 같아요.

+ Recent posts