카테고리 보관물: Programming

Jinja2의 UnicodeDecodeError

App engine을 이용하는 project 중에 Jinja2 template 부분에서 다음과 같이 UnicodeDecodeError가 발생하는 문제가 생겼다.

Traceback (most recent call last):
  File "<<APP_ENGINE>>/lib/webapp2-2.5.2/webapp2.py", line 1535, in __call__
    rv = self.handle_exception(request, response, e)
  File "<<APP_ENGINE>>/lib/webapp2-2.5.2/webapp2.py", line 1529, in __call__
    rv = self.router.dispatch(request, response)
  File "<<APP_ENGINE>>/lib/webapp2-2.5.2/webapp2.py", line 1278, in default_dispatcher
    return route.handler_adapter(request, response)J
  File "<<APP_ENGINE>>/lib/webapp2-2.5.2/webapp2.py", line 1102, in __call__
    return handler.dispatch()
  File "<<APP_ENGINE>>/lib/webapp2-2.5.2/webapp2.py", line 572, in dispatch
    return self.handle_exception(e, self.app.debug)
  File "<<APP_ENGINE>>/lib/webapp2-2.5.2/webapp2.py", line 570, in dispatch
    return method(*args, **kwargs)
  File "<<PROJECT_TOP>>/main.py", line 141, in get
    r = t.render(events)
  File "<<APP_ENGINE>>/lib/jinja2-2.6/jinja2/environment.py", line 894, in render
    return self.environment.handle_exception(exc_info, True)
  File "<<PROJECT_TOP>>/templates/parser.html", line 21, in top-level template code
    <td>{{titles[loop.index0]}}</td>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xa1 in position 9: ordinal not in range(128)

Jinja2 web page의 설명문서에 따르면, Jinja2는 내부적으로 Unicode를 사용하기 때문에 template에는 unicode object를 넘겨주어야 한다고 설명하고 있는데, 내가 project에서 사용하는 web page는  cp949 encoding을 사용하기 때문에 문제가 발생한다.

따라서 이것은 Jinja2 template으로 data를 넘기기 전에 unicode()를 이용해서 cpc949를 uinicode로 변환한 값을 넘겨주면 해결할 수 있다. 다음은 실제로 수정된 code로 cp949로 encoding된 문자열을  unicode로 변환해서 추가하는 것이다.

titles.append(sch.mTitle) -> titles.append(unicode(sch.mTitle, 'cp949'))

[BinaryHack#11] 실행 파일에 데이터 삽입하기 (64bits)

‘Binary Hacks’의 hack #11에는 objcopy를 이용해서 실행파일에 binary를 추가하는 방법이 나온다. 이것을 따라 64 bits machine에서 build하면 i386:x86-64 출력물과 i386 출력물이 incompatible 해서 link할 수 없다는 오류가 발생한다.

$> objcopy -I binary -O elf32-i386 -B i386 binary.bmp binary.o
$> gcc -c main.c
$> gcc -o program main.o binary.o
/usr/bin/ld: i386 architecture of input file 'binary.o' is incompatible with i386:x86-64 output
collect2: error: ld returned 1 exit status

gcc로 만들어진 main.o는 ELF-64 format인데 objcopy로 생성한 ELF-32 format이어서 함께 link할 수 없다는 것이다. 이 문제는 동일한 ELF format이 되도록 하면 해결된다. 즉, gcc로 compile한 결과물이 objcopy의 결과물인 ELF-32와 동일하게 되도록 하거나 objcopy의 결과 물이 main.o와 동일한 ELF-64가 되도록 해야한다.

첫번째 방법 – ELF-32 format으로 object를 compile
gcc에 -m32 option을 추가하면 ELF32로 compile된 object file을 얻을 수 있다. 이것을 objcopy의 결과 물과 link한다.

$> objcopy -I binary -O elf32-i386 -B i386 binary.bmp binary.o
$> gcc -m32 -c main.c
$> gcc -m32 -o program main.o binary.o

두번째 방법 – ELF-64 format으로 binary를 생성
objcopy가 ELF64를 생성하도록 하면 gcc로 compile한 다른 object file들과 link할 수 있다.

$> objcopy -I binary -O elf64-x86-64 -B i386 binary.bmp binary.o
$> gcc -c main.c
$> gcc -o program main.o binary.o

 

* objcopy로 생성된 ELF object에서 담고 있는 symbol의 목록은 nm 명령어나 readelf -s option으로 볼 수 있다.

$> nm binary.o
00000000002fd036 D _binary_binary_bmp_end
00000000002fd036 A _binary_binary_bmp_size
0000000000000000 D _binary_binary_bmp_start

$>readelf -s binary.o
Symbol table '.symtab' contains 5 entries:
   Num:    Value          Size Type    Bind   Vis      Ndx Name
     0: 0000000000000000     0 NOTYPE  LOCAL  DEFAULT  UND 
     1: 0000000000000000     0 SECTION LOCAL  DEFAULT    1 
     2: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT    1 _binary_binary_bmp_start
     3: 00000000002fd036     0 NOTYPE  GLOBAL DEFAULT    1 _binary_binary_bmp_end
     4: 00000000002fd036     0 NOTYPE  GLOBAL DEFAULT  ABS _binary_binary_bmp_size