디버그 라이브러리

디버그 라이브러리 (The Debug Library)

debug 라이브러리는 루아 프로그램의 디버깅을 위한 함수와 후크(hook)를 제공해요. 이 라이브러리의 함수는 프로그램 실행에 대한 낮은 수준의 정보(호출 스택, 지역 변수, 업밸류, 메타테이블, 레지스트리 등)를 조회하거나 변경할 수 있게 해요. 성능·보안상 이유로, 프로덕션 환경에서는 종종 이 라이브러리를 제거하기도 해요.

디버그 이벤트와 후크

디버그 후크(hook)는 특정 이벤트(호출, 반환, 줄 실행, 카운트)에서 호출되는 함수예요. debug.sethook로 설정하고, 후크는 debug.debug 같이 사용할 수도 있어요.

debug.debug

debug.debug ()

대화형 디버깅을 위한 REPL(라인 단위 인터랙티브 루프) 세션에 들어가요. 사용자가 입력한 루아 코드를 한 줄씩 실행하고, cont(계속) 등으로 실행을 재개할 수 있어요. 어떤 종류의 코드(지역 변수 접근 포함)든 입력할 수 있어요.

debug.gethook

debug.gethook ([thread])

현재 후크 설정을 반환해요. 세 값을 return해요: 후크 함수, 후크 마스크, 후크 카운트. 후크가 없으면 nil들을 반환해요.

debug.getinfo

debug.getinfo ([thread,] f [, what])

함수 f 또는 스택 프레임에 대한 정보를 담은 테이블을 반환해요.

  • f가 함수면 그 함수의 정보를, 숫자면 스택 프레임의 정보를 반환해요.
  • what으로 얻을 필드를 지정할 수 있어요: "n"(이름), "S"(소스·줄), "l"(줄), "u"(업밸류 수), "t"(테이블), "f"(함수) 등. 각 문자는 해당 정보 그룹을 반환해요.
  • 반환 테이블은 source, short_src, linedefined, lastlinedefined, what, currentline, name, namewhat, nups, nparams, isvararg, func, activelines 등의 필드를 가질 수 있어요.
local info = debug.getinfo(1)   -- 현재 호출 스택 프레임
print(info.currentline)

debug.getlocal

debug.getlocal ([thread,] f, local)

스택 프레임 flocal번째 지역 변수 이름과 값을 반환해요. 두 값을 return해요: 이름(문자열)과 값. 변수가 범위 밖이거나 이미 범위가 끝나면 nil을 반환해요.

debug.getmetatable

debug.getmetatable (value)

value의 메타테이블을 반환해요. __metatable 필드가 있어도 무시하고 실제 메타테이블을 반환해요 (일반 getmetatable과 다른 점).

debug.getregistry

debug.getregistry ()

전역 레지스트리(registry) 테이블을 반환해요. 레지스트리는 C API가 전역적으로 보관하는 값들을 담아요. 이 테이블을 조작해서 루아 내부 참조에 접근할 수 있어요.

debug.getupvalue

debug.getupvalue (f, up)

함수 fup번째 업밸류(upvalue)의 이름과 값을 반환해요. 두 값을 return해요. 업밸류가 없으면 nil을 반환해요.

debug.getuservalue

debug.getuservalue (u, n)

userdata un번째 사용자 값(uservalue)을 반환해요. 루아 5.4의 userdata는 여러 사용자 값을 가질 수 있어요. n이 범위 밖이면 nil을 반환해요.

debug.sethook

debug.sethook ([thread,] hook, mask [, count])

디버그 후크를 설정해요.

  • hook은 후크 함수이며, nil이면 후크를 제거해요.
  • mask는 언제 후크를 호출할지 나타내는 문자열이에요.
    • "c" — 루아 함수가 호출될 때마다.
    • "r" — 함수가 반환될 때마다.
    • "l" — 새 줄이 실행될 때마다.
  • count는 양의 정수로, 지정된 명령어(카운트)마다 후크를 호출해요.

후크는 debug.getinfo 등으로 맥락을 조회할 수 있어요.

debug.setlocal

debug.setlocal ([thread,] level, local, value)

스택 프레임 levellocal번째 지역 변수 값을 value로 설정해요. 설정한 변수의 이름을 반환하고, 범위 밖이면 nil을 반환해요.

debug.setmetatable

debug.setmetatable (value, table)

value의 메타테이블을 table로 설정해요 (value는 테이블 또는 userdata). 일반 setmetatable__metatable으로 막는 것을 우회할 수 있어요. value를 반환해요.

debug.setupvalue

debug.setupvalue (f, up, value)

함수 fup번째 업밸류 값을 value로 설정해요. 설정한 업밸류의 이름을 반환하고, 없으면 nil을 반환해요.

debug.setuservalue

debug.setuservalue (udata, value, n)

userdata udatan번째 사용자 값을 value로 설정해요. 성공하면 udata를 반환해요.

debug.traceback

debug.traceback ([thread,] [message [, level]])

오류 메시지 message와 함께 호출 스택 추적(traceback) 문자열을 반환해요. level은 추적 시작 지점을 지정해요. 오류 메시지가 없으면 스택 추적만 돌려줘요. xpcall의 메시지 핸들러로 흔히 쓰여요.

local ok, err = xpcall(risky, debug.traceback)

debug.upvalueid

debug.upvalueid (f, n)

함수 fn번째 업밸류를 식별하는 고유한 값(스레드 또는 userdata)을 반환해요. 두 함수가 같은 업밸류를 공유하는지(upvalueid 동일) 판별할 수 있어요.

debug.upvaluejoin

debug.upvaluejoin (f1, n1, f2, n2)

함수 f1n1번째 업밸류를 함수 f2n2번째 업밸류와 공유하게 만들어요. 즉 f1f2의 그 업밸류를 참조하게 해요. 반환값은 없어요.

성능과 보안

debug 라이브러리는 실행 중인 프로그램의 상태를 조사하고 변경하는 강력한 도구예요. 그만큼 오버헤드와 남용 위험이 커서, 보안이 중요한 환경에서는 로드하지 않는 게 일반적이에요. luaL_openlibs 대신 선택적으로 라이브러리를 열 때 debug를 제외할 수 있어요.

출처: 디버그 라이브러리 (The Debug Library)

본문

스택 프레임 접근

getinfo, getlocal, setlocal, traceback 등은 런타임 호출 스택을 조사해요. 스택 깊이에 따라 성능 부담이 있으므로, 디버깅 시에만 사용하는 게 좋아요.

후크와 프로파일링

sethookgethook로 실행 이벤트(호출/반환/줄/카운트)를 감지해, 간단한 프로파일러나 감시자를 구현할 수 있어요.

업밸류 검사

getupvalue·setupvalue·upvalueid·upvaluejoin로 클로저의 업밸류를 읽고, 쓰고, 공유할 수 있어요.

더 알아보기