EPUB는 전자책 포맷입니다. 특징은 가변폭이라 화면의 가로 사이즈가 줄면 그에 맞게 문단의 가로폭도 줄어들어 가로 스크롤을 할 필요가 없습니다. 또한 글꼴이나 글자 크기도 조절할 수 있어 자신에게 맞는 모양으로 글을 읽을 수 있습니다. EPUB 형식으로 제작된 전자책은 EPUB 뷰어(EPUB 리더)로 읽을 수 있습니다. 보통 전자책 판매회사에서 전용 리더를 제공하는데, 만약 EPUB 파일 자체를 받았다면 이를 읽기 위해 리더를 설치해야합니다. PC에 설치해서 EPUB 파일을 볼 수 있는 소프트웨어 5가지를 소개해드립니다.
static int child_pid; void * monitor_pid(void *pVoid) { int status; waitpid(child_pid, &status, 0); /* Child status should never change. */ _exit(0); // Commit seppuku }
void anti_debug() { child_pid = fork(); if (child_pid == 0) { int ppid = getppid(); int status; if (ptrace(PTRACE_ATTACH, ppid, NULL, NULL) == 0) { waitpid(ppid, &status, 0); ptrace(PTRACE_CONT, ppid, NULL, NULL); while (waitpid(ppid, &status, 0)) { if (WIFSTOPPED(status)) { ptrace(PTRACE_CONT, ppid, NULL, NULL); } else { // Process has exited _exit(0); } } }
Amazon EC2의 설정을 자동으로 하기 위해선 인스턴스의 정보를 받아와서 설정할 수 있어야 한다.
예를 들어 특정 태그로 묶인 그룹에게 재가동시 소스코드 갱신과 서버 재가동의 명령어를 init.d에 등록했을 때 인스턴스 정보를 얻어온다면 개별적으로 인스턴스의 역할에 맞는 work load를 할당할 수 있을 것이다.
meta-data 확인하기
Metadata에 대해서 찾아보니 위키백과에 아래와 같이 쓰여 있었다.
메타데이터(metadata)는 데이터(data)에 대한 데이터이다. 이렇게 흔히들 간단히 정의하지만 엄격하게는, Karen Coyle에 의하면 “어떤 목적을 가지고 만들어진 데이터 (Constructed data with a purpose)”라고도 정의한다. 가령 도서관에서 사용하는 서지기술용으로 만든 것이 그 대표적인 예이다. 지금은 온톨로지의 등장과 함께 기계가 읽고 이해할 수 있는 (Machine Actionable)한 형태의 메타데이터가 많이 사용되고 있다.
이 뜻을 인스턴스에 대입해보면, 인스턴스에 대한 데이터라고 생각해볼 수 있다.
여기에는 인스턴스가 가지고 있는 intance-id값과 같이 인스턴스의 특성을 알 수 있는 값들이 있을 것이다.
아래와 같이 예제를 통해 인스턴스의 Meta-data를 받아 본다.
169.254.169.254 라는 IP는 인스턴스의 정보를 받아 볼 수 있는 IP이다. 이 IP를 통해 정보를 받는다.
지금까지 인스턴스의 정보를 받아보았다. 169.254.169.254에 get 요청을 하면 받는 인스턴스 정보를 특정하여 받아볼 수 있는데, 이는 활용하는 사람에 따라 다양하게 적용할 수 있을 것이다.
먼저 Security Group의 정보를 받을 경우에는 인스턴스가 가동할 때 원하는 Security-Group이 할당여부를 확인할 수 있을 것이다. 또한 Role 을 받아오면 인스턴스의 역할을 명확히 알 수 있기 때문에, 인스턴스의 소스코드를 갱신하여 인스턴스가 재시작 될 때마다 동작해야 할 명령어들을 구분지을 수 있다.
다른 활용 방법을 간단하게 구상해보자. 특정 S3에는 스크립트 파일들을 모아두고 role과 파일명을 일치해둔다. 그리고 AMI를 만드는데 내용은 다음과 같다. 가동될 때 meta-data로 role정보를 받아오면 role과 일치하는 S3버킷의 파일을 받아와 shell 또는 python 등 자신이 자신있는 script로 실행한다. script가 실행되면 각 인스턴스의 역할에 맞는 서버가 가동된다.
이런 식으로 설정을 한다면 Scaling Group이 Scale out이 될 때 큰 걱정없이 배포용 코드로 서버들이 가동될 수 있을 것이다.
iOS 개발을 좀 더 잘하기 위해, 편하게 버그를 추적하기 위해 LLDB를 이용한 디버깅 방법을 기록합니다.
Thread의 Stack, Frame
Thread가 생겨날 때, 해당 Thread를 위한Stack이 만들어지며, 해당Stack에는 Frame이 들어갑니다.
Execution Commands
Continue- 정지된 프로그램 실행을 재개함.
(lldb) continue (lldb) c
Step Over- 현재 선택된 Frame에서 소스 수준의 한 단계를 진행.
(lldb) thread step-over (lldb) next (lldb) n
Step Into- 현재 선택된 Frame에서 소스 수준의 한 단계 안으로 들어감.
(lldb) thread step-in (lldb) step (lldb) s
Step Out- 현재 선택된 Frame에서 벗어남.
(lldb) thread step-out (lldb) finish
Instruction Level Step Into- 현재 선택된 Frame에서 명령어 수준의 한 단계 안으로 들어감.
(lldb) thread step-inst (lldb) si
Instruction Level Step Over- 현재 선택된 Frame에서 명령어 수준의 한 단계를 진행.
(lldb) thread step-inst-over (lldb) ni
Examining Variables- 변수 검사
Frame Variable- 메모리에서 변수를 읽어 lldb 형태의 description을 출력함.
/// 현재 frame에 argument와 local 변수 출력하기. (lldb) frame variable (lldb) fr v /// 현재 frame에 local 변수 출력하기 (lldb) frame variable --no-args (lldb) fr v -a /// local 변수 `bar` 내용 출력하기 (lldb) frame variable bar (lldb) fr v bar /// local 변수 `bar`을 hex로 내용 출력하기 (lldb) frame variable --format x bar (lldb) fr v -f x bar /// Object의 Description 출력하기 (lldb) frame variable -O self
Target Variable- global/static 변수를 출력함.
/// global 변수 `baz` 내용 출력하기 (lldb) target variable baz (lldb) ta v baz /// 현재 소스 파일에서 정의된 global/static 변수 출력하기 (lldb) target variable (lldb) ta v
Target Stop-hook / Display- 매번 멈출 때 마다 지정된 명령 실행 / 멈출 때 마다 지정한 변수 내용을 출력
///`frame variable argc argv` stop hook을 등록하기 (lldb) target stop-hook add --one-liner "frame variable argc argv" (lldb) ta st a -o "fr v argc argv" /// 멈출 때 마다 argc, argv 내용을 출력하기 (lldb) display argc (lldb) display argv ///`main` 함수 안에서 멈추면 argc, argv 내용을 출력하기 (lldb) target stop-hook add --name main --one-liner "frame variable argc argv" (lldb) ta st a -n main -o "fr v argc argv" /// C 클래스 이름인 MyClass 안에서 멈추면 *this 변수 내용을 출력하기 (lldb) target stop-hook add --classname MyClass --one-liner "frame variable *this" (lldb) ta st a -c MyClass -o "fr v *this" /// Multiple Line Hook (lldb) target stop-hook add > bt > disassemble --pc > DONE
Examining Thread State- 스레드 상태 검사
Thread List/Change- 현재 스레드 목록을 보여줌 / 다른 스레드로 이동하기
/// 현재 스레드 목록을 보여주기 (lldb) thread list /// Thread 2로 이동하기 (lldb) thread select2
Thread Until/Jump/Return- 특정 줄 전까지 실행 후 멈춤 / 특정 주소/줄로 이동 / 현재 stack frame에서 특정 값을 반환(note: Swift에서는 거의 안됨)
///특정줄까지stepover수행함.(ex:현재줄이10줄이고,20줄이전까지stepover를수행함.)(lldb)threaduntil20//19줄까지stepover,20줄에서멈춤///특정frame의특정소스줄까지수행함.(frame2에서10번째줄전까지수행)(lldb)threaduntil--frame210///명령어수준의특정주소까지수행함(lldb)disassemble--frame(lldb)threaduntil--address0x1023653a0///특정소스라인까지이동함.(lldb)threadjump--line10//10번째줄으로이동(lldb)threadjump--by5//현재줄에서+5번째줄로이동(lldb)threadjump--by-5//현재줄에서-5번째줄로이동///현재frame에서Void를반환하거나특정값을반환(lldb)threadreturn(lldb)threadreturn0(lldb)threadreturn"aa"//OnlyObjcerror: Error returning from frame 0 of thread 1:Weonlysupportsettingsimpleintegerandfloatreturntypesatpresent..
/// Swift (lldb) expr -l swift -- import UIKit (lldb) expr -l swift -- let $vc = unsafeBitCast(0x7fe75a70bb40, to: ViewController.self) (lldb) po $vc /// Objc (lldb) expr -l objc -- @import UIKit (lldb) expr -l objc -- ViewController *$vc = (ViewController *)0x7fe75a70bb40 (lldb) po $vc /// 실행 중에 Pause를 한 후, 특정 메모리 주소의 값을 확인하는 경우 (lldb) expr -l Swift -- Enter expressions, then terminate with an empty line to evaluate: 1let $vc = unsafeBitCast(0x7fe75a70bb40, to: ViewController.self) 2print($vc) 3/// 위 명령들을 축약 (lldb) expr import UIKit (lldb) p import UIKit (lldb) expr let $vc = unsafeBitCast(0x7fe75a70bb40, to: ViewController.self) (lldb) po $vc <SomeProject.ViewController: 0x7fe75a70bb40>
임의의 UIViewController 생성하여 NavigationViewController에 Push하기
frame variable (fr v)- Code를 실행하지 않으며, LLDB formatter를 사용
expression -- (p)- Code를 실행하며, LLDB formatter를 사용
expression -O -- (po)- Code를 실행하며,debugDescription와 같이 개발자가 만든 출력 형태를 사용
BreakPoint 설정된 코드를 실행시 Pause되도록 하기
(lldb)expr--ignore-breakpointsfalse--<Expression>
메소드 및 클래스 선언하기
특정한 메소드 및 클래스를 만들어 사용할 수 있습니다.
(lldb)poEnterexpressions,then terminate with an empty line to evaluate:1class$A{2var$b=03}4(lldb)po$A()<$A:0x600001bc87e0> (lldb) po $A().$b 0
또한, Extension에 함수를 만들어 사용할 수 있습니다.
(lldb) po Enter expressions, then terminate with an empty line to evaluate: 1extensionViewController{ 2func$changeBgColor() { 3self.view.backgroundColor = .red 4 } 5 } 6 (lldb) po self.$changeBgColor()
BreakPoint - BreakPoint 설정하기
/// viewDidLoad 이름인 모든 함수에 breakpoint를 설정하기 - Swift (lldb) breakpoint set --name viewDidLoad (lldb) br s -n viewDidLoad (lldb) b viewDidLoad /// viewDidLoad 이름인 모든 함수에 breakpoint를 설정하기 - Objc (lldb) breakpoint set --name "-[UIViewController viewDidLoad]"/// 특정 파일 특정 줄에 breakpoint 설정하기 (lldb) breakpoint set --file test.c --line 12 (lldb) br s -f test.c -l 12 (lldb) b test.c:12/// 현재 파일의 특정 줄에 breakpoint 설정하기 (lldb) breakpoint set --line 12 (lldb) br s -l 12 (lldb) b 12/// 특정 이름을 가진 Select에 breakpoint 설정하기 (lldb) breakpoint set --selector dealloc /// breakpoint에 global이 5이면 중단되도록 조건 설정 (lldb) b 12 (lldb) breakpoint modify -c"global == 5"/// breakpoint 목록 보기 (lldb) breakpoint list (lldb) br l /// breakpoint 지우기 (lldb) breakpoint delete 1 (lldb) br del 1
Watchpoint - 변수에 값이 기록될 때마다 중단되도록 설정
/// 전역 변수에 watchpoint 설정 (lldb) watchpoint set variable global_var (lldb) wa s v global_var /// 메모리 주소에 watchpoint 설정 (lldb) watchpoint set expression -- my_ptr (lldb) wa s e -- my_ptr /// watchpoint에 global이 5이면 중단되도록 조건 설정 (lldb) watch setvar global (lldb) watchpoint modify -c"global == 5"/// watchpoint 목록 보기 (lldb) watchpoint list (lldb) watch l /// watchpoint 지우기 (lldb) watchpoint delete 1 (lldb) watch del 1
또는 /.lldbinit 파일 내에command script import ~/myCommands.py를 추가함.
기타
/// 특정 키워드의 상세한 설명을 보여줌 (lldb) apropos keyword /// 기본 언어 설정을 바꿈 (lldb) settings set target.language swift /// Alias 설정 (lldb) command alias es expression -l swift --
LLDB 확장 툴
Chisel- python으로 대부분 작성되어 있으며, View Debugging 관련하여 손쉽게 사용할 수 있도록 도와주며,여기에서 많은 명령을 살펴볼 수 있음.
DerekSelander - LLDB- A collection of LLDB aliases/regexes and Python scripts to aid in your debugging sessions