-
-
Save claudiajkang/04b95dfa84f3a936a3b4549327f4bcb5 to your computer and use it in GitHub Desktop.
물 흘러가듯이 치는 것 부터!
-
[add / commit / push] - [tutorial v2]
-
[rebase / blame] - [tutorial v3]
-
branch : 같은 폴더 다른 세상인 것처럼 운영이 되는 개념이 중요
-
rebase interactive
-
pull -> 바로 merge -> conflict 가능성 있음.
-
fetch -> 바로 merge 안하고, .git에 저장
-
fetch -> rebase -> rewind : rebase시, undo 공간.
- Git 상태확인 명령어
$ git shortlog
$ git diff
$ git commit -sm "commit meesage" # s옵션은 서명 포함
$ git commit --amend # 가 장 위에 있는 commit 을 수정
$ git reset # reset 으로 add 한거 취소
$ git merge test # 현재 브랜치랑 test 브랜치랑 합치기
$ git rebase -i --root # commit 최초 기록부터 리베이스
$ git rebase --continue # rebase 계속
$ git blame report_card.c # 어떤 가 파일이든 누 어느라인을 수정했는지 파악
2. uftrace
1) 실습
install
시, tip.make -j
옵션 사용.compile
시,pg
옵션 필수 !!- g : binary에 debug information 추가
- pg : 모든 function 첫 시작 부분에 mcount를 호출하도록. (mocunt는 libc에 존재 -> mcount를 후킹애서 사용)
- uftrace/wiki/tutorial
- OSS-tutorial : uftrace.data.printf_kern에 들어가서
$ uftrace replay # -D 옵션으로 depth 조정 가능
or$ uftrace info
or$ uftrace report # -s 옵션 : 해당 func가 실제 소비한 시간
or$ uftrace graph # call count 확인 가능
해보기. - kern / xen 이 서로 다름.
- [--auto-args 옵션]
$ gcc print.c -o print -pg -O0 -g
->$ uftrace --auto-args print_var
- O0 : compiler optimization
- [graph 옵션] : 동일하게 실행되는 함수를 묶어서 보여줌.
- [tui 옵션] : configure에서 확인한 lib에서 TUI 관련 lib 설치 필요
$ sudo yum install ncurses-devel # fedora
- run test :
$ uftrace/test/.runtest.py <args>
- coredump :
$ gdb <coredump 파일>
|$ uftrace <coredump??>
: crash point 확인 가능.
2) 사용사례
- 코드 실행 시간 확인
- 함수 동작원리 없이 어떻게 동작하는지 분석하고 싶을 때
- git pull vs git fetch
- uftrace 내부동작 원리 관련 PDF : 소스코드로 정리되어 있음
- uftrace Tutorial (OSSEU17) : 그림. 여기 뒷 부분 참고
## 3. 간략한 uftrace 내부원리 이해와 소스 중간중간 prinf() 찍어보기 (-vvv 활용법)
## 4. 내가 집중할(기여할) 영역 찾아보기, 기여할 idea 고민/토론 1
- #1 터미널 : 잘써야됨.
- git patch
$ git commit --amend
$ git apply ~/where/to/*.patch # git apply 는 "모두 적용, 아니면 모두 취소" 모델을 사용
$ git format-patch -1 -o /where/you/want # 패치 파일 생성시
$ git send-email --annotate --cover-letter --to climbbb.kim@gmail.com *.patch
$ git send-email --to-cmd ./scripts/get_maintainer.pl /where/to/*.patch
관심 있는 분야에 대한 메일링 리스트 보기
-
git am
-
commit message : 해당 파일에 대한
history
참고 -
RFC : Request For Comment
이 부분을 커밋 했는데 확신이 안설 때.. PR? 패치? 보낼 때 내용 추가
-
리눅스 커널 패치하기 (이거 찾아보면 됨)
-
git commit -s : signed-off-by 옵션이 바로 붙음
-
coding rule 확인 필요.
ex) 커널의 경우 if(1) -> if (1)
-
소스 패치는 해당 서브 메일링 리스트에다가 보냄. (주로 커널에 보내지 않음)
-
udev
같은 system programming 하고kernel
로 오는걸 추천.초심자를 위한
staging
폴더 존재. -
kernel
소스를 분석할 때길을 잃지 말 것
# 해당 함수가 무엇이든 그냥 일단 스킵하고 전체 뼈대 이해 먼저 -
insmod
/rmmod
insmod
사용 시 파라미터 값을 넘겨줄 수 있음 파라미터 값은 /sys/module/<module명> ... 여기로 가면 파라미터 값 확인 가능 -
debugfs
: 디버깅 시 사용 -
jazzguitar81/koss 실습 시, debug fs 옵션 on 필요.
난이도 : simple < workerqueue < usbchecker < yavta
-
시스템 프로그래밍 + uftrace 를 통해 커널 일부의 구조 파악 가능
-
uftrace
- userspace
- kernel
- library
-
uftrace tracing 실습
#include <stdio.h>
int main()
{
printf("hello\n");
flush(stdout);
}
$ touch a
$ sudo uftrace record --force -K 20 rm -f a
$ sudo uftrace replay
- 함수 시작 시 기록.
- 함수 엔트리 증가.
- 함수 종료시 엔트리 삭제.
- 함수 종료.
-> 파이썬을 통해서 uftrace 진행
import sys
count = 0
def uftrace_begin(args):
print "begin"
print sys.platform
def uftrace_entry(args):
global count
count += 1
def uftrace_exit(args):
pass
def uftrace_End():
print("{} called ".format(count))
// fibonacci
#include <stdio.h>
int main()
{
int n = 20;
long i, a=0, b=1;
for ( i=1; i < n; i++) {
a+=b;
b=a-b;
}
printf("%lu\n", a);
}
// fibonacci_recursive
#include <stdio.h>
int fibonacci(int);
int main()
{
int n = 20 i, result;
for ( i=1; i < n; i++) {
result=fibonacci(i)
}
printf("%lu\n", result);
return 0;
}
int fibonacci(int n)
{
if(n == 0 || n == 1)
return n;
else
return fibonacci(n-1) + fibonacci(n-2);
}
- 컴파일 방법
$gcc p1.c -o p1 -pg -g
man uftrace script
참고
- 예제 :
uftrace/scripts/*.py
$ uftrace record --auto-args p1
$ uftrace record -S scripts/count.py --auto-args p1
- fitler 기능 사용
1. uftrace
함수 호출 규약
uftrace
파일을 실행한 이후 misc/debug.sh
의 내부 실행 주소를 바꾼 후 실행하면 실제 gdb
로 디버깅할때와는 달리 함수 호출 부분에 uftrace
로 함수 호출 순서가 바뀌는 것을 볼 수 있음.
uftrace/arch/x86_64/mount.S
에서 함수 리턴 주소를 스택에 쌓고 새로운 리턴 주소로 바꾼 후, 함수 실행 : 리턴 값 파싱 + 복구 역할 -> 리턴이 될 때(mcount_return
)uftrace
가 알아차릴 수 있음.
-> uftrace는 아래에서 설명하는 예제에서 두 번째 함수 호출시 원래 함수로 가야하는 주소를 GOT에서 이미 알고 있는데도 불구하고 uftrace
내의 로직에서 첫 번째 함수 호출 시에 실행했던 linking 과정의 값으로 복구해놈.
-> plt_hooker 사용.
--> uftrace가 두 번재 함수의 경우에도 linking을 다시하도록 복구함!
-
PLT(Procedure Linking Table) / GOT(Global Offset Table) / Dynamic Linking / lazy binding
-
GOT : 프로세스가 가지고 있는 지도 or 이정표
-
lazy binding은 운영체제마다 실행되는 함수나 과정이 다름!
-
ex)
getpid
debugging (assembler code) -> 리눅스의 경우 lazy binding(binary를 실행할 때 모든 바이너리를 linking해줌). but windows는 그렇지 않음.
// 예제 소스
void main()
{
getpid();
getpid();
}
// 디버깅 시에는 첫 getpid 랑 두번째 getpid가 불리는 과정이 다른 것을 확실히 알아야됨.
// plt -> 아래 세 가지의 라인으로 구성. (링킹 되기 전과 후가 다름)
(gdb) disas getpid
Dump of assembler code for function getpid@plt:
0x00000000004004b0 <+0>: jmpq *0x200b62(%rip) # 0x601018(got주소) # plt+0의 경우 뭐가 됬든 실행 -> 601018에 있는 값으로 실행하라. (처음과 두번째에서 0x601018의 값이 다를것!!!!!)
0x00000000004004b6 <+6>: pushq $0x0 # 처음에는 무조건 plt+0가 plt+6으로 점프함. 왜냐면 #0x601018이라는 값에 plt+6의 주소가 들어가 있음.
0x00000000004004bb <+11>: jmpq 0x4004a0 # -> 링킹으로 넘어가기 전 과정.
// process 매핑 맵을 가져다 줌.
(gdb) info proc mapping
원래 함수 어드레스가 libc-2.27.so의 주소에 매핑되어있는 것을 확인할 수 있음.
// 최종
(gdb) disass main
Dump of assembler code for function main:
0x0000000000400652 <+0>: push %rbp
0x0000000000400653 <+1>: mov %rsp,%rbp
0x0000000000400656 <+4>: sub $0x10,%rsp
0x000000000040065a <+8>: callq 0x4004d0 <mcount@plt>
0x000000000040065f <+13>: movl $0x0,-0x4(%rbp)
0x0000000000400666 <+20>: mov $0x0,%eax
=> 0x000000000040066b <+25>: callq 0x4004b0 <getpid@plt>
0x0000000000400670 <+30>: mov $0x0,%eax
0x0000000000400675 <+35>: callq 0x4004b0 <getpid@plt>
0x000000000040067a <+40>: mov $0x0,%eax
0x000000000040067f <+45>: leaveq
0x0000000000400680 <+46>: retq
End of assembler dump.
(gdb) si
0x00000000004004b0 in getpid@plt ()
(gdb) disas
Dump of assembler code for function getpid@plt:
=> 0x00000000004004b0 <+0>: jmpq *0x200b62(%rip) # 0x601018
0x00000000004004b6 <+6>: pushq $0x0
0x00000000004004bb <+11>: jmpq 0x4004a0
End of assembler dump.
(gdb) x/gx 0x601018
0x601018: 0x00000000004004b6
(gdb) c
Continuing.
Breakpoint 2, 0x0000000000400675 in main ()
(gdb) disas
Dump of assembler code for function main:
0x0000000000400652 <+0>: push %rbp
0x0000000000400653 <+1>: mov %rsp,%rbp
0x0000000000400656 <+4>: sub $0x10,%rsp
0x000000000040065a <+8>: callq 0x4004d0 <mcount@plt>
0x000000000040065f <+13>: movl $0x0,-0x4(%rbp)
0x0000000000400666 <+20>: mov $0x0,%eax
0x000000000040066b <+25>: callq 0x4004b0 <getpid@plt>
0x0000000000400670 <+30>: mov $0x0,%eax
=> 0x0000000000400675 <+35>: callq 0x4004b0 <getpid@plt>
0x000000000040067a <+40>: mov $0x0,%eax
0x000000000040067f <+45>: leaveq
0x0000000000400680 <+46>: retq
End of assembler dump.
(gdb) x/gx 0x601018
0x601018: 0x00007ffff7ade720
Q. 왜 0x601018일까?
(gdb) si
0x00000000004004b0 in getpid@plt ()
(gdb) disass
Dump of assembler code for function getpid@plt:
=> 0x00000000004004b0 <+0>: jmpq *0x200b62(%rip) # 0x601018
0x00000000004004b6 <+6>: pushq $0x0
0x00000000004004bb <+11>: jmpq 0x4004a0
End of assembler dump.
(gdb) info reg $rip
rip 0x4004b0 0x4004b0 <getpid@plt>
(gdb) x/gx $rip+0x200b62
0x601012: 0x04b600007ffff7de
(gdb) x/gx $rip+0x200b62+6
0x601018: 0x00000000004004b6
엑셀에 미리 적어놓고 하기! -> 각자 보물캐기 하듯이 하기 [ wants | needs ] patch needs > wants 패치하기
-
컨트리뷰션 종류: test, doc(예제, 설명 추가), bugfix, refactoring, 이슈, 이슈 댓글, PR, PR 댓글 등
-
집중할 작업 종류
- dwarf 기능 : debug format 기능 | 불안정 | 채워넣어야 될 부분 많음 2) TUI 기능
- script 기능 : ex) malloc, free
1) ~ 3) : 추가 된지 얼마 안됨. 핫한 기능. 보안 여지 필요.
- dump, info 기능
- recv 기능
- report 기능
- replay 기능
- graph 기능
- event 관련
- trigger, filter (count, at return, 등)
A.
$ uftrace replay -A fib@n tests/t-fibonacci 5
-> 이 경우는 gcc -g
옵션으로 디버깅 옵션으로 빌드하기
-> value filter 시 적용 가능할듯.
B.Dwarf
어디서부터 시작해야할지? -> Compiler 별로 포맷도 다르고 형태도 다름.
dwarfview를 바탕으로.
dwarf: 컴파일된 소스를 저장
-> uftrace 는 function을 중점으로 생각...
-> dwarf 표준 문서 참고 : dwarf 2 표준 문서 추천
-> concept 이해 -> 문서보기
-> example 기준으로 확인해보기.
C. Libelf
구현이 달라졌을 때 동일한 인터페이스를 쓸 수 있게.
elf 코드 쓰는 쪽/ elf코드 안 쓰는 쪽
endian / machine 크기 변경 시 발생하는 문제................고민 필요.
D. Code coverage
code coverage 확인 필요......
F. Dynamic Linking
plt[0] : loader의 주소가 있음
pg opt 없이 시작 -> mcount option 을 메모리의 다른 영역에 저장 ->
got table의 0번에 링커 대신 uftrace libmcount.so 주소로 강제 변경 -> libmcount.so로 가서 plthook이 가능하게...
opcode / operand 차이 유지가 필요
-
gcc 는 함수 호출 규약을 깨는 경우가 많음..................
-
규약을 깬다? callee caller 부분의 로직을 강제로 깸
-
gcc 는 컴파일을 3번 컴파일............... <*>
-
instruction decoding 필요
-
- 컴파일러가 지원이 없어도 NOP으로 바꿔서 하는 방안
-
- 컴파일 옵션 없이 코드 삽입 후 mcount 부를 수 있게
-
- attach를 해서 붙어서 확인 (attach를 제대로 쓰려면 dynamic tracing 필요)
-> 컴파일 작업 없이 tracing이 가능
-> decoding -> 캡스톤 ? 을 사용할 예정.......
2. Details of uftrace's TODO
wiki's TODO filter는 record / runtime 모두 사용 가능
커널 기능에서 좋은 걸 user에서 쓸 수 있었으면 좋겠다 -> uftrace 개발 시작 (C/C++지원, 차차 python 진행 예정)
- cleanup task management
- more trigger action
- trigger filtering (ignore, count, at return, ...)
- improve documentation
- report w/ multi-thread
- config file support
- filter by argument value
- filter by function size
- filter by source location
- filter by caller(?)
- SDT argument support
- LTT-ng event (tracepoint) support
- symbol file compression
- reading/watching external data (global variable, cpu, ...)
- show kernel function argument and return value (with kprobes)
- different clock support (TSC on x86, ...)
- generic field support for report
- field and sort support for TUI
- filtering on TUI
- replay on TUI
- python 3 support
- python function tracing
- write useful script examples
- dynamic tracing support
- attach to existing process
- signal trigger support (for daemons)
- process and display multiple data together
- graph diff support
- full demangling support
-
Cleanup task management :
struct uftrace_task
(open_data_file) /struct ftrace_task_handle
(file 데이터 관련) - Finding session에 필요 => 두 개 data 구조체를 하나로 만드려고 함 (내부 구현 작업 필요) -
More trigger actions : Read/Watch/Counting/Ignoring(trigger를 동작하게 되면 영원이 동작하게 되는데 일시적으로 다운 가능하게)/.. 구현 O -> 더 좋은 것이 있는지 고민 필요...
-
Improve documentation, github.io랑 wiki
-
Report with multi-thread : 쭉 파싱해서 통계 내는 Report 기능을 multi-thread로 동작하면 빨리 처리할 수 있지 않을까
-
Value filter : 값에 따른 필터 ->
$ uftrace -V 'foo@arg1>0' foobar
->$ uftrace -V 'foo@arag1/s=="XXX"' foobar
-
Size filter :
$ uftrace -Z 16 foobar
-
Location filter : 특정 dir 내의 파일만 필터, 무시 -
$ uftrace -O src/foo foobar
or$ uftrace -O !^tests/ foobar
-
Caller filter -> 구현 완료 : 특정 function 호출 과정에 대한 필터
$ uftrace -C malloc foobar
소스코드만 보고 호출 로직이 이해가 안될 때 이걸 사용하면 좋음. -
SDT argument support : 커널 SDTv3 allows argument가 필요.
ubuntu 기준 project는 SDTv3가 적용되어 있다.
-
LTT-ng event support : 시스템 전체 트레이스를 할 수 있는 LTT-ng 프로젝트를 적용 하는 것
-
Symbol file compression : symbol 파일을 text로 저장하는데 압축하면 조금 이득이 되지 않을까. 현재는 function에 대해서만 symbol table 저장 중.
-
Watch point -> 구현 완료 : 값이 바뀔때 보여줄 수 있도록. 현재는 cpu만 가능.
-
Kernel function argument : Kernel function은 argument가 저장 x => kprobe로 사용하면 될듯...... kprobe가 저장이 되고 function 내용이 저장이 되어야 하는데, interrupt 발생 시 문제 발생가능성 존재
-
Differenct clock support : clock_gettime(시스템 콜) 사용하면 -> 커널까지 갔다와야하니까 오래 걸릴 가능성 존재함.
- 해결 할려면 x86은 tsc를 사용하면 됨. but 이건 다른 clock이랑 호환이 안됨 => 시간을 정확히 측정할 수 없음
-
Report field
- Total time, self time, call
- Avg total, min total, max total
- Avg self, min self, max self => 원하는대로 골라서 했으면 좋겠다.
- TUI Update
- Filter change
- Field change
- Sort support (for report)
- open/close data
- Replay (with folding) -> 지원 x , folding 구현이 어려움
- Python update : python2/3를 지원할 수 있게. (현재는 dynamic loading이 가능하게)
- Python3 support
- Python function tracing
- Script update : python을 이용해서 uftrace 데이터를 가공
- C언어로 so파일 붙여서 사용할 수 있도록
- lock/unlock state
- 특정 상황을 잘 분석할 수 있는 스크립트
- Attache to process
- 새로운 방식으로 통신 가능한 프로토콜 생성이 필요할 듯..
- Dynamic tracing
- overhead를 줄이기 위해 원하는 몇 가지 function만 tracing 하고 싶..
-
- W/ compiler support
-
- Script to make mcount to NOP
-
- Reverse patch making NOP runtime
-
- Inject mcount call at load-time
-
- Inject mcount call at runtime (w/ attach)
- Signal trigger(#340)
- process가 끝났다는 걸 따로 signal을 보낼 수 있게
- signal로 trace를 tracing할 수 있게.
- Multi-data processing
- uftrace가 1개 이상 process를 tracing할 수 있게..
- 따로 따로 record 시킨 후 볼 때 합쳐서 실행할 수 있게
- Graph diff support
- uftrace graph 를 diff할 수 있게
- 현재는 report로만 확인 가능함
- 터미널 환경에서 표현 상 어려움 필요 (js 필요성..)
- Full demangle support
- C++ symbol을 풀어서 보여줌........
- 현재는 외부 라이브러리 도움 받고 있음 - Without external library
- Flat trace
- 현재는 function trace 를 entry / exit 에서 하고 있는데 return addr 복구 과정에서 문제가 많이 발생...
- 원래 컴파일러가 넣어주는 함수만 tracing하는 걸로 바꾸는게 좋은듯..
- Function entry / exit
Pro user가 되기.
순서대로 따라가면서 확인할 수 있게.
-
--nest-libcall
: deps 내려가서 확인 가능하게 , 생 바이너리도 확인 가능하게 -
graph
는 chrome 에서 확인할 때help
확인 필요.. -
-f +self
: self를 더해서 볼 수 있도록 -
tui
: 직접 써보기 (규모 있는 프로그램에서 사용하는 걸 추천)
--l
: 제일 길게 걸린 함수를 보여줌 - 제일 많이 실행되는 것도 확인할 수 있음 - 아래에 라인 넘버도 확인 O -> source code도 확인 가능함. --u
: 자기의 parent로 감 - partent / child 구분 필요. -
uftrace script
- runtine | recording
- python name filter : 파이썬 스크립트가 해당 name에서 실행하지 않게!!!!
- ctx : context 정보
- 예졔 확인
- args : index로 indexing이 되어 있음
-
dynamic tracing
- compiler support 필요 : NOP instruction을 삽입해야되기 때문
- gcc
mfentry
옵션 - fxray-instrument
-P b
option 적용 필요함! -> 그렇지 않으면 tracing 정보 확인 불가능...
-
uftrace.github.io
---
는 페이지 구분remark
툴 사용- 좋은 example 있으면 contribution해도 좋음..............
commit 은 일단 uftrace.github.io에 하기
-
code coverage : 어디가 실행되고 실행이 안되는지 확인 가능함 + 몇 번까지 확인 가능함. -> 보다 쉽게 이해할 수 있음........!
- 각 소스별로 확인이 가능함.
COVERAGE=1
로 두고 빌드하면 됨!!!
set-trace -> trace
라는 내장 모듈이 있어서 그걸로 하면 됨.
python -m trace
line profileing
-> hooking 지점이 없어서 힘들 가능성이 많음....... -> break
하나씩 걸어야 해서 오버헤드가 클 것.............................................................
-
-E
option ? #185 test -> event 정보 (퍼프 이벤트 정보)
-
- namhyung/uftrace#457
sample
하면 오래걸리지 않게.
- namhyung/uftrace#457
-
- 방향성 ?
속도
,user
관점에서 쉽게 접근 가능xray
- 뭐든지
tool
은 사람이 익숙해야된다는점.............
python - settrace
-C
option 잘 사용하면 좋음
주로 커널쪽은 커밋로그에 많음......
systab
없이 kernel's header file
만 있으면 됨.
build할 때
/.configure -> make -> sudo make install
git log -4 --stat