4.1 섹션 덤프
4.1.1 소스코드
/* Demonstrate the binary loader from ../inc/loader.cc */
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "../inc/loader.h"
int
main(int argc, char *argv[])
{
size_t i;
Binary bin;
Section *sec;
Symbol *sym;
std::string fname;
if(argc < 2) {
printf("Usage: %s <binary>\n", argv[0]);
return 1;
}
fname.assign(argv[1]);
if(load_binary(fname, &bin, Binary::BIN_TYPE_AUTO) < 0) {
return 1;
}
printf("loaded binary '%s' %s/%s (%u bits) entry@0x%016jx\n",
bin.filename.c_str(),
bin.type_str.c_str(), bin.arch_str.c_str(),
bin.bits, bin.entry);
for(i = 0; i < bin.sections.size(); i++)
{
sec = &bin.sections[i];
if(argc == 3)
{
if(strcasecmp(argv[2],sec->name.c_str()) == 0)
{
int line = 0;
printf(" 0x%016jx %-8ju %-20s %s\n",
sec->vma, sec->size, sec->name.c_str(),
sec->type == Section::SEC_TYPE_CODE ? "CODE" : "DATA");
printf("Section Data\n offset 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n 000000 ");
for(int bc = 0; bc < sec->size ; bc++)
{
printf("%02x ",sec->bytes[bc]);
if((bc+1)%16 == 0 && bc != 0 && bc != sec->size-1)
{
line ++;
printf("\n %05x0 ",line);
}
}
printf("\n");
break;
}
}
else
{
printf(" 0x%016jx %-8ju %-20s %s\n",
sec->vma, sec->size, sec->name.c_str(),
sec->type == Section::SEC_TYPE_CODE ? "CODE" : "DATA");
}
}
if(bin.symbols.size() > 0) {
printf("scanned symbol tables\n");
"loader_demo.cc" 82L, 1801C 1,1 Top if(bin.symbols.size() > 0) {
printf("scanned symbol tables\n");
for(i = 0; i < bin.symbols.size(); i++) {
sym = &bin.symbols[i];
printf(" %-40s 0x%016jx %s\n",
sym->name.c_str(), sym->addr,
(sym->type & Symbol::SYM_TYPE_FUNC) ? "FUNC" : "");
}
}
unload_binary(&bin);
return 0;
}
C
복사
4.1.2 결과
binary@binary-VirtualBox:~/code/chapter4$ ./loader_demo /bin/ls .data
loaded binary '/bin/ls' elf64-x86-64/i386:x86-64 (64 bits) entry@0x00000000004049a0
0x000000000061e3a0 608 .data DATA
Section Data
offset 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
000000 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000020 01 00 00 00 ff ff ff ff 00 00 00 00 00 00 00 00
000030 c4 69 41 00 00 00 00 00 ce 69 41 00 00 00 00 00
000040 02 00 00 00 00 00 00 00 c8 67 41 00 00 00 00 00
000050 01 00 00 00 00 00 00 00 bd 65 41 00 00 00 00 00
000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000070 01 00 00 00 00 00 00 00 d6 64 41 00 00 00 00 00
000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000090 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0000a0 05 00 00 00 00 00 00 00 da 69 41 00 00 00 00 00
0000b0 05 00 00 00 00 00 00 00 e0 69 41 00 00 00 00 00
0000c0 02 00 00 00 00 00 00 00 ef 69 41 00 00 00 00 00
0000d0 05 00 00 00 00 00 00 00 e6 69 41 00 00 00 00 00
0000e0 05 00 00 00 00 00 00 00 ec 69 41 00 00 00 00 00
0000f0 05 00 00 00 00 00 00 00 ec 69 41 00 00 00 00 00
000100 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000110 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000120 05 00 00 00 00 00 00 00 f2 69 41 00 00 00 00 00
000130 05 00 00 00 00 00 00 00 e6 69 41 00 00 00 00 00
000140 05 00 00 00 00 00 00 00 f8 69 41 00 00 00 00 00
000150 05 00 00 00 00 00 00 00 fe 69 41 00 00 00 00 00
000160 05 00 00 00 00 00 00 00 04 6a 41 00 00 00 00 00
000170 05 00 00 00 00 00 00 00 0a 6a 41 00 00 00 00 00
000180 05 00 00 00 00 00 00 00 10 6a 41 00 00 00 00 00
000190 05 00 00 00 00 00 00 00 16 6a 41 00 00 00 00 00
0001a0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0001b0 03 00 00 00 00 00 00 00 1c 6a 41 00 00 00 00 00
0001c0 01 00 00 00 00 00 00 00 01 01 3f 00 01 00 00 00
0001d0 10 8b 41 00 00 00 00 00 60 9f 40 00 00 00 00 00
0001e0 01 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000200 08 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000210 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000220 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
000230 00 00 00 00 00 00 00 00 e0 e5 61 00 00 00 00 00
000240 00 01 00 00 00 00 00 00 20 f2 61 00 00 00 00 00
000250 01 00 00 00 00 00 00 00 10 26 41 00 00 00 00 00
scanned symbol tables
__ctype_toupper_loc 0x0000000000000000 FUNC
__uflow 0x0000000000000000 FUNC
getenv 0x0000000000000000 FUNC
sigprocmask 0x0000000000000000 FUNC
raise 0x0000000000000000 FUNC
localtime 0x0000000000000000 FUNC
__mempcpy_chk 0x0000000000000000 FUNC
abort 0x0000000000000000 FUNC
__errno_location 0x0000000000000000 FUNC
strncmp 0x0000000000000000 FUNC
_exit 0x0000000000000000 FUNC
strcpy 0x0000000000000000 FUNC
__fpending 0x0000000000000000 FUNC
isatty 0x0000000000000000 FUNC
sigaction 0x0000000000000000 FUNC
iswcntrl 0x0000000000000000 FUNC
wcswidth 0x0000000000000000 FUNC
localeconv 0x0000000000000000 FUNC
mbstowcs 0x0000000000000000 FUNC
readlink 0x0000000000000000 FUNC
clock_gettime 0x0000000000000000 FUNC
setenv 0x0000000000000000 FUNC
textdomain 0x0000000000000000 FUNC
fclose 0x0000000000000000 FUNC
opendir 0x0000000000000000 FUNC
getpwuid 0x0000000000000000 FUNC
bindtextdomain 0x0000000000000000 FUNC
stpcpy 0x0000000000000000 FUNC
dcgettext 0x0000000000000000 FUNC
__ctype_get_mb_cur_max 0x0000000000000000 FUNC
strlen 0x0000000000000000 FUNC
__lxstat 0x0000000000000000 FUNC
__stack_chk_fail 0x0000000000000000 FUNC
getopt_long 0x0000000000000000 FUNC
mbrtowc 0x0000000000000000 FUNC
strchr 0x0000000000000000 FUNC
getgrgid 0x0000000000000000 FUNC
__overflow 0x0000000000000000 FUNC
strrchr 0x0000000000000000 FUNC
fgetfilecon 0x0000000000000000 FUNC
gmtime_r 0x0000000000000000 FUNC
lseek 0x0000000000000000 FUNC
gettimeofday 0x0000000000000000 FUNC
__assert_fail 0x0000000000000000 FUNC
__strtoul_internal 0x0000000000000000 FUNC
fnmatch 0x0000000000000000 FUNC
memset 0x0000000000000000 FUNC
fscanf 0x0000000000000000 FUNC
ioctl 0x0000000000000000 FUNC
close 0x0000000000000000 FUNC
closedir 0x0000000000000000 FUNC
__libc_start_main 0x0000000000000000 FUNC
memcmp 0x0000000000000000 FUNC
_setjmp 0x0000000000000000 FUNC
fputs_unlocked 0x0000000000000000 FUNC
calloc 0x0000000000000000 FUNC
lgetfilecon 0x0000000000000000 FUNC
strcmp 0x0000000000000000 FUNC
signal 0x0000000000000000 FUNC
dirfd 0x0000000000000000 FUNC
getpwnam 0x0000000000000000 FUNC
__memcpy_chk 0x0000000000000000 FUNC
sigemptyset 0x0000000000000000 FUNC
memcpy 0x0000000000000000 FUNC
getgrnam 0x0000000000000000 FUNC
getfilecon 0x0000000000000000 FUNC
tzset 0x0000000000000000 FUNC
fileno 0x0000000000000000 FUNC
tcgetpgrp 0x0000000000000000 FUNC
__xstat 0x0000000000000000 FUNC
readdir 0x0000000000000000 FUNC
wcwidth 0x0000000000000000 FUNC
fflush 0x0000000000000000 FUNC
nl_langinfo 0x0000000000000000 FUNC
ungetc 0x0000000000000000 FUNC
__fxstat 0x0000000000000000 FUNC
strcoll 0x0000000000000000 FUNC
__freading 0x0000000000000000 FUNC
fwrite_unlocked 0x0000000000000000 FUNC
realloc 0x0000000000000000 FUNC
stpncpy 0x0000000000000000 FUNC
fdopen 0x0000000000000000 FUNC
setlocale 0x0000000000000000 FUNC
__printf_chk 0x0000000000000000 FUNC
timegm 0x0000000000000000 FUNC
strftime 0x0000000000000000 FUNC
mempcpy 0x0000000000000000 FUNC
memmove 0x0000000000000000 FUNC
error 0x0000000000000000 FUNC
open 0x0000000000000000 FUNC
fseeko 0x0000000000000000 FUNC
unsetenv 0x0000000000000000 FUNC
strtoul 0x0000000000000000 FUNC
__cxa_atexit 0x0000000000000000 FUNC
wcstombs 0x0000000000000000 FUNC
getxattr 0x0000000000000000 FUNC
freecon 0x0000000000000000 FUNC
sigismember 0x0000000000000000 FUNC
exit 0x0000000000000000 FUNC
fwrite 0x0000000000000000 FUNC
__fprintf_chk 0x0000000000000000 FUNC
fflush_unlocked 0x0000000000000000 FUNC
mbsinit 0x0000000000000000 FUNC
iswprint 0x0000000000000000 FUNC
sigaddset 0x0000000000000000 FUNC
strstr 0x0000000000000000 FUNC
__ctype_tolower_loc 0x0000000000000000 FUNC
__ctype_b_loc 0x0000000000000000 FUNC
__sprintf_chk 0x0000000000000000 FUNC
_fini 0x0000000000413c5c FUNC
_init 0x00000000004022b8 FUNC
free 0x0000000000402340 FUNC
_obstack_memory_used 0x0000000000412930 FUNC
_obstack_begin 0x0000000000412750 FUNC
_obstack_free 0x00000000004128c0 FUNC
localtime_r 0x00000000004023a0 FUNC
_obstack_allocated_p 0x0000000000412890 FUNC
_obstack_begin_1 0x0000000000412770 FUNC
_obstack_newchunk 0x0000000000412790 FUNC
malloc 0x0000000000402790 FUNC
C
복사
4.2 Weak Symbol과 Strong Symbol
4.2.1 결과
gvar에 관해서 WEAK과 STRONG 둘 다 추가했으나 STRONG만 찍힘
binary@binary-VirtualBox:~/code/chapter4$ ./loader_demo ./test/test
loaded binary './test/test' elf64-x86-64/i386:x86-64 (64 bits) entry@0x0000000000400430
0x0000000000400238 28 .interp DATA
0x0000000000400254 32 .note.ABI-tag DATA
0x0000000000400274 36 .note.gnu.build-id DATA
0x0000000000400298 28 .gnu.hash DATA
0x00000000004002b8 96 .dynsym DATA
0x0000000000400318 63 .dynstr DATA
0x0000000000400358 8 .gnu.version DATA
0x0000000000400360 32 .gnu.version_r DATA
0x0000000000400380 24 .rela.dyn DATA
0x0000000000400398 48 .rela.plt DATA
0x00000000004003c8 26 .init CODE
0x00000000004003f0 48 .plt CODE
0x0000000000400420 8 .plt.got CODE
0x0000000000400430 402 .text CODE
0x00000000004005c4 9 .fini CODE
0x00000000004005d0 21 .rodata DATA
0x00000000004005e8 52 .eh_frame_hdr DATA
0x0000000000400620 244 .eh_frame DATA
0x0000000000600e10 8 .init_array DATA
0x0000000000600e18 8 .fini_array DATA
0x0000000000600e20 8 .jcr DATA
0x0000000000600e28 464 .dynamic DATA
0x0000000000600ff8 8 .got DATA
0x0000000000601000 40 .got.plt DATA
0x0000000000601028 20 .data DATA
scanned symbol tables
.interp 0x0000000000400238 LOCAL 0x00105
.note.ABI-tag 0x0000000000400254 LOCAL 0x00105
.note.gnu.build-id 0x0000000000400274 LOCAL 0x00105
.gnu.hash 0x0000000000400298 LOCAL 0x00105
.dynsym 0x00000000004002b8 LOCAL 0x00105
.dynstr 0x0000000000400318 LOCAL 0x00105
.gnu.version 0x0000000000400358 LOCAL 0x00105
.gnu.version_r 0x0000000000400360 LOCAL 0x00105
.rela.dyn 0x0000000000400380 LOCAL 0x00105
.rela.plt 0x0000000000400398 LOCAL 0x00105
.init 0x00000000004003c8 LOCAL 0x00105
.plt 0x00000000004003f0 LOCAL 0x00105
.plt.got 0x0000000000400420 LOCAL 0x00105
.text 0x0000000000400430 LOCAL 0x00105
.fini 0x00000000004005c4 LOCAL 0x00105
.rodata 0x00000000004005d0 LOCAL 0x00105
.eh_frame_hdr 0x00000000004005e8 LOCAL 0x00105
.eh_frame 0x0000000000400620 LOCAL 0x00105
.init_array 0x0000000000600e10 LOCAL 0x00105
.fini_array 0x0000000000600e18 LOCAL 0x00105
.jcr 0x0000000000600e20 LOCAL 0x00105
.dynamic 0x0000000000600e28 LOCAL 0x00105
.got 0x0000000000600ff8 LOCAL 0x00105
.got.plt 0x0000000000601000 LOCAL 0x00105
.data 0x0000000000601028 LOCAL 0x00105
.bss 0x000000000060103c LOCAL 0x00105
.comment 0x0000000000000000 LOCAL 0x00105
crtstuff.c 0x0000000000000000 LOCAL 0x04005
__JCR_LIST__ 0x0000000000600e20 LOCAL 0x10001
deregister_tm_clones 0x0000000000400460 FUNC 0x00009
deregister_tm_clones 0x0000000000400460 LOCAL 0x00009
register_tm_clones 0x00000000004004a0 FUNC 0x00009
register_tm_clones 0x00000000004004a0 LOCAL 0x00009
__do_global_dtors_aux 0x00000000004004e0 FUNC 0x00009
__do_global_dtors_aux 0x00000000004004e0 LOCAL 0x00009
completed.7585 0x000000000060103c LOCAL 0x10001
__do_global_dtors_aux_fini_array_entry 0x0000000000600e18 LOCAL 0x10001
frame_dummy 0x0000000000400500 FUNC 0x00009
frame_dummy 0x0000000000400500 LOCAL 0x00009
__frame_dummy_init_array_entry 0x0000000000600e10 LOCAL 0x10001
main.c 0x0000000000000000 LOCAL 0x04005
test.c 0x0000000000000000 LOCAL 0x04005
crtstuff.c 0x0000000000000000 LOCAL 0x04005
__FRAME_END__ 0x0000000000400710 LOCAL 0x10001
__JCR_END__ 0x0000000000600e20 LOCAL 0x10001
0x0000000000000000 LOCAL 0x04005
__init_array_end 0x0000000000600e18 LOCAL 0x00001
_DYNAMIC 0x0000000000600e28 LOCAL 0x10001
__init_array_start 0x0000000000600e10 LOCAL 0x00001
__GNU_EH_FRAME_HDR 0x00000000004005e8 LOCAL 0x00001
_GLOBAL_OFFSET_TABLE_ 0x0000000000601000 LOCAL 0x10001
__libc_csu_fini 0x00000000004005c0 FUNC 0x0000a
__libc_csu_fini 0x00000000004005c0 GLOBAL 0x0000a
_ITM_deregisterTMCloneTable 0x0000000000000000 WEAK 0x00080
data_start 0x0000000000601028 WEAK 0x00080
_edata 0x000000000060103c GLOBAL 0x00002
_fini 0x00000000004005c4 FUNC 0x0000a
_fini 0x00000000004005c4 GLOBAL 0x0000a
printf@@GLIBC_2.2.5 0x0000000000000000 FUNC 0x00008
__libc_start_main@@GLIBC_2.2.5 0x0000000000000000 FUNC 0x00008
__data_start 0x0000000000601028 GLOBAL 0x00002
__gmon_start__ 0x0000000000000000 WEAK 0x00080
__dso_handle 0x0000000000601030 GLOBAL 0x10002
_IO_stdin_used 0x00000000004005d0 GLOBAL 0x10002
__libc_csu_init 0x0000000000400550 FUNC 0x0000a
__libc_csu_init 0x0000000000400550 GLOBAL 0x0000a
_end 0x0000000000601040 GLOBAL 0x00002
_start 0x0000000000400430 FUNC 0x0000a
_start 0x0000000000400430 GLOBAL 0x0000a
__bss_start 0x000000000060103c GLOBAL 0x00002
main 0x0000000000400526 FUNC 0x0000a
main 0x0000000000400526 GLOBAL 0x0000a
_Jv_RegisterClasses 0x0000000000000000 WEAK 0x00080
__TMC_END__ 0x0000000000601040 GLOBAL 0x10002
_ITM_registerTMCloneTable 0x0000000000000000 WEAK 0x00080
gvar 0x0000000000601038 GLOBAL 0x10002
_init 0x00000000004003c8 FUNC 0x0000a
_init 0x00000000004003c8 GLOBAL 0x0000a
printf 0x0000000000000000 FUNC 0x08008
__libc_start_main 0x0000000000000000 FUNC 0x08008
__gmon_start__ 0x0000000000000000 WEAK 0x08080
C
복사
4.2.2 소스코드
//test.c
int gvar = 5;
//main.c
#include <stdio.h>
int gvar;
int main()
{
printf("shared gvar %d \n",gvar);
return 0;
}
//command
gcc -o test main.c test.c
C
복사
로더 소스코드의 경우 연습문제 4.3과 동일
4.1 → 4.3 → 4.2 순서대로 문제를 진행하였음
4.3 타입 추가
4.3.1 결과
개인적으로 기본적인 Flags값을 가지고 있는 경우 enum이 아닌 define을 사용하여 전부 보여줘야 한다고 생각함.
binary@binary-VirtualBox:~/code/chapter4$ ./loader_demo ../chapter2/compilation_example
loaded binary '../chapter2/compilation_example' elf64-x86-64/i386:x86-64 (64 bits) entry@0x0000000000400430
0x0000000000400238 28 .interp DATA
0x0000000000400254 32 .note.ABI-tag DATA
0x0000000000400274 36 .note.gnu.build-id DATA
0x0000000000400298 28 .gnu.hash DATA
0x00000000004002b8 96 .dynsym DATA
0x0000000000400318 61 .dynstr DATA
0x0000000000400356 8 .gnu.version DATA
0x0000000000400360 32 .gnu.version_r DATA
0x0000000000400380 24 .rela.dyn DATA
0x0000000000400398 48 .rela.plt DATA
0x00000000004003c8 26 .init CODE
0x00000000004003f0 48 .plt CODE
0x0000000000400420 8 .plt.got CODE
0x0000000000400430 402 .text CODE
0x00000000004005c4 9 .fini CODE
0x00000000004005d0 18 .rodata DATA
0x00000000004005e4 52 .eh_frame_hdr DATA
0x0000000000400618 244 .eh_frame DATA
0x0000000000600e10 8 .init_array DATA
0x0000000000600e18 8 .fini_array DATA
0x0000000000600e20 8 .jcr DATA
0x0000000000600e28 464 .dynamic DATA
0x0000000000600ff8 8 .got DATA
0x0000000000601000 40 .got.plt DATA
0x0000000000601028 16 .data DATA
scanned symbol tables
.interp 0x0000000000400238 LOCAL 0x00105
.note.ABI-tag 0x0000000000400254 LOCAL 0x00105
.note.gnu.build-id 0x0000000000400274 LOCAL 0x00105
.gnu.hash 0x0000000000400298 LOCAL 0x00105
.dynsym 0x00000000004002b8 LOCAL 0x00105
.dynstr 0x0000000000400318 LOCAL 0x00105
.gnu.version 0x0000000000400356 LOCAL 0x00105
.gnu.version_r 0x0000000000400360 LOCAL 0x00105
.rela.dyn 0x0000000000400380 LOCAL 0x00105
.rela.plt 0x0000000000400398 LOCAL 0x00105
.init 0x00000000004003c8 LOCAL 0x00105
.plt 0x00000000004003f0 LOCAL 0x00105
.plt.got 0x0000000000400420 LOCAL 0x00105
.text 0x0000000000400430 LOCAL 0x00105
.fini 0x00000000004005c4 LOCAL 0x00105
.rodata 0x00000000004005d0 LOCAL 0x00105
.eh_frame_hdr 0x00000000004005e4 LOCAL 0x00105
.eh_frame 0x0000000000400618 LOCAL 0x00105
.init_array 0x0000000000600e10 LOCAL 0x00105
.fini_array 0x0000000000600e18 LOCAL 0x00105
.jcr 0x0000000000600e20 LOCAL 0x00105
.dynamic 0x0000000000600e28 LOCAL 0x00105
.got 0x0000000000600ff8 LOCAL 0x00105
.got.plt 0x0000000000601000 LOCAL 0x00105
.data 0x0000000000601028 LOCAL 0x00105
.bss 0x0000000000601038 LOCAL 0x00105
.comment 0x0000000000000000 LOCAL 0x00105
crtstuff.c 0x0000000000000000 LOCAL 0x04005
__JCR_LIST__ 0x0000000000600e20 LOCAL 0x10001
deregister_tm_clones 0x0000000000400460 FUNC 0x00009
register_tm_clones 0x00000000004004a0 FUNC 0x00009
__do_global_dtors_aux 0x00000000004004e0 FUNC 0x00009
completed.7585 0x0000000000601038 LOCAL 0x10001
__do_global_dtors_aux_fini_array_entry 0x0000000000600e18 LOCAL 0x10001
frame_dummy 0x0000000000400500 FUNC 0x00009
__frame_dummy_init_array_entry 0x0000000000600e10 LOCAL 0x10001
compilation_example.c 0x0000000000000000 LOCAL 0x04005
crtstuff.c 0x0000000000000000 LOCAL 0x04005
__FRAME_END__ 0x0000000000400708 LOCAL 0x10001
__JCR_END__ 0x0000000000600e20 LOCAL 0x10001
0x0000000000000000 LOCAL 0x04005
__init_array_end 0x0000000000600e18 LOCAL 0x00001
_DYNAMIC 0x0000000000600e28 LOCAL 0x10001
__init_array_start 0x0000000000600e10 LOCAL 0x00001
__GNU_EH_FRAME_HDR 0x00000000004005e4 LOCAL 0x00001
_GLOBAL_OFFSET_TABLE_ 0x0000000000601000 LOCAL 0x10001
__libc_csu_fini 0x00000000004005c0 FUNC 0x0000a
_ITM_deregisterTMCloneTable 0x0000000000000000 WEAK 0x00080
data_start 0x0000000000601028 WEAK 0x00080
puts@@GLIBC_2.2.5 0x0000000000000000 FUNC 0x00008
_edata 0x0000000000601038 GLOBAL 0x00002
_fini 0x00000000004005c4 FUNC 0x0000a
__libc_start_main@@GLIBC_2.2.5 0x0000000000000000 FUNC 0x00008
__data_start 0x0000000000601028 GLOBAL 0x00002
__gmon_start__ 0x0000000000000000 WEAK 0x00080
__dso_handle 0x0000000000601030 GLOBAL 0x10002
_IO_stdin_used 0x00000000004005d0 GLOBAL 0x10002
__libc_csu_init 0x0000000000400550 FUNC 0x0000a
_end 0x0000000000601040 GLOBAL 0x00002
_start 0x0000000000400430 FUNC 0x0000a
__bss_start 0x0000000000601038 GLOBAL 0x00002
main 0x0000000000400526 FUNC 0x0000a
_Jv_RegisterClasses 0x0000000000000000 WEAK 0x00080
__TMC_END__ 0x0000000000601038 GLOBAL 0x10002
_ITM_registerTMCloneTable 0x0000000000000000 WEAK 0x00080
_init 0x00000000004003c8 FUNC 0x0000a
puts 0x0000000000000000 FUNC 0x08008
__libc_start_main 0x0000000000000000 FUNC 0x08008
__gmon_start__ 0x0000000000000000 WEAK 0x08080
C
복사
4.3.2 소스코드
./inc/loader.cc
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
#include <string>
#include <vector>
#include <bfd.h>
#include "loader.h"
static bfd*
open_bfd(std::string &fname)
{
static int bfd_inited = 0;
bfd *bfd_h;
if(!bfd_inited) {
bfd_init();
bfd_inited = 1;
}
bfd_h = bfd_openr(fname.c_str(), NULL);
if(!bfd_h) {
fprintf(stderr, "failed to open binary '%s' (%s)\n",
fname.c_str(), bfd_errmsg(bfd_get_error()));
return NULL;
}
if(!bfd_check_format(bfd_h, bfd_object)) {
fprintf(stderr, "file '%s' does not look like an executable (%s)\n",
fname.c_str(), bfd_errmsg(bfd_get_error()));
return NULL;
}
/* Some versions of bfd_check_format pessimistically set a wrong_format
* error before detecting the format, and then neglect to unset it once
* the format has been detected. We unset it manually to prevent problems. */
bfd_set_error(bfd_error_no_error);
if(bfd_get_flavour(bfd_h) == bfd_target_unknown_flavour) {
fprintf(stderr, "unrecognized format for binary '%s' (%s)\n",
fname.c_str(), bfd_errmsg(bfd_get_error()));
return NULL;
}
return bfd_h;
}
static int
load_symbols_bfd(bfd *bfd_h, Binary *bin)
{
int ret;
long n, nsyms, i;
asymbol **bfd_symtab;
Symbol *sym;
bfd_symtab = NULL;
n = bfd_get_symtab_upper_bound(bfd_h);
if(n < 0) {
fprintf(stderr, "failed to read symtab (%s)\n",
bfd_errmsg(bfd_get_error()));
goto fail;
} else if(n) {
bfd_symtab = (asymbol**)malloc(n);
if(!bfd_symtab) {
fprintf(stderr, "out of memory\n");
goto fail;
}
nsyms = bfd_canonicalize_symtab(bfd_h, bfd_symtab);
if(nsyms < 0) {
fprintf(stderr, "failed to read symtab (%s)\n",
bfd_errmsg(bfd_get_error()));
goto fail;
}
for(i = 0; i < nsyms; i++) {
if(bfd_symtab[i]->flags & BSF_FUNCTION) {
bin->symbols.push_back(Symbol());
sym = &bin->symbols.back();
sym->type = Symbol::SYM_TYPE_FUNC;
sym->name = std::string(bfd_symtab[i]->name);
sym->addr = bfd_asymbol_value(bfd_symtab[i]);
sym->ctype = bfd_symtab[i]->flags;
}
else if(bfd_symtab[i]->flags & BSF_WEAK)
{
bin->symbols.push_back(Symbol());
sym = &bin->symbols.back();
sym->type = Symbol::SYM_TYPE_WEAK;
sym->name = std::string(bfd_symtab[i]->name);
sym->addr = bfd_asymbol_value(bfd_symtab[i]);
sym->ctype = bfd_symtab[i]->flags;
}
else if(bfd_symtab[i]->flags & BSF_GLOBAL)
{
bin->symbols.push_back(Symbol());
sym = &bin->symbols.back();
sym->type = Symbol::SYM_TYPE_GLOBAL;
sym->name = std::string(bfd_symtab[i]->name);
sym->addr = bfd_asymbol_value(bfd_symtab[i]);
sym->ctype = bfd_symtab[i]->flags;
}
else if(bfd_symtab[i]->flags & BSF_LOCAL)
{
bin->symbols.push_back(Symbol());
sym = &bin->symbols.back();
sym->type = Symbol::SYM_TYPE_LOCAL;
sym->name = std::string(bfd_symtab[i]->name);
sym->addr = bfd_asymbol_value(bfd_symtab[i]);
sym->ctype = bfd_symtab[i]->flags;
}
/*else
{
bin->symbols.push_back(Symbol());
sym = &bin->symbols.back();
sym->ctype = bfd_symtab[i]->flags;
sym->name = std::string(bfd_symtab[i]->name);
sym->addr = bfd_asymbol_value(bfd_symtab[i]);
}*/
}
}
ret = 0;
goto cleanup;
fail:
ret = -1;
cleanup:
if(bfd_symtab) free(bfd_symtab);
return ret;
}
static int
load_dynsym_bfd(bfd *bfd_h, Binary *bin)
{
int ret;
long n, nsyms, i;
asymbol **bfd_dynsym;
Symbol *sym;
bfd_dynsym = NULL;
n = bfd_get_dynamic_symtab_upper_bound(bfd_h);
if(n < 0) {
fprintf(stderr, "failed to read dynamic symtab (%s)\n",
bfd_errmsg(bfd_get_error()));
goto fail;
} else if(n) {
bfd_dynsym = (asymbol**)malloc(n);
if(!bfd_dynsym) {
fprintf(stderr, "out of memory\n");
goto fail;
}
nsyms = bfd_canonicalize_dynamic_symtab(bfd_h, bfd_dynsym);
if(nsyms < 0) {
fprintf(stderr, "failed to read dynamic symtab (%s)\n",
bfd_errmsg(bfd_get_error()));
goto fail;
}
for(i = 0; i < nsyms; i++) {
if(bfd_dynsym[i]->flags & BSF_FUNCTION) {
bin->symbols.push_back(Symbol());
sym = &bin->symbols.back();
sym->type = Symbol::SYM_TYPE_FUNC;
sym->name = std::string(bfd_dynsym[i]->name);
sym->addr = bfd_asymbol_value(bfd_dynsym[i]);
sym->ctype = bfd_dynsym[i]->flags;
}
else if(bfd_dynsym[i]->flags & BSF_WEAK)
{
bin->symbols.push_back(Symbol());
sym = &bin->symbols.back();
sym->type = Symbol::SYM_TYPE_WEAK;
sym->name = std::string(bfd_dynsym[i]->name);
sym->addr = bfd_asymbol_value(bfd_dynsym[i]);
sym->ctype = bfd_dynsym[i]->flags;
}
else if(bfd_dynsym[i]->flags & BSF_GLOBAL)
{
bin->symbols.push_back(Symbol());
sym = &bin->symbols.back();
sym->type = Symbol::SYM_TYPE_GLOBAL;
sym->name = std::string(bfd_dynsym[i]->name);
sym->addr = bfd_asymbol_value(bfd_dynsym[i]);
sym->ctype = bfd_dynsym[i]->flags;
}
else if(bfd_dynsym[i]->flags & BSF_LOCAL)
{
bin->symbols.push_back(Symbol());
sym = &bin->symbols.back();
sym->type = Symbol::SYM_TYPE_LOCAL;
sym->name = std::string(bfd_dynsym[i]->name);
sym->addr = bfd_asymbol_value(bfd_dynsym[i]);
sym->ctype = bfd_dynsym[i]->flags;
}
/*else
{
bin->symbols.push_back(Symbol());
sym = &bin->symbols.back();
sym->ctype = bfd_dynsym[i]->flags;
sym->name = std::string(bfd_dynsym[i]->name);
sym->addr = bfd_asymbol_value(bfd_dynsym[i]);
}*/
}
}
ret = 0;
goto cleanup;
fail:
ret = -1;
cleanup:
if(bfd_dynsym) free(bfd_dynsym);
return ret;
}
static int
load_sections_bfd(bfd *bfd_h, Binary *bin)
{
int bfd_flags;
uint64_t vma, size;
const char *secname;
asection* bfd_sec;
Section *sec;
Section::SectionType sectype;
for(bfd_sec = bfd_h->sections; bfd_sec; bfd_sec = bfd_sec->next) {
bfd_flags = bfd_get_section_flags(bfd_h, bfd_sec);
sectype = Section::SEC_TYPE_NONE;
if(bfd_flags & SEC_CODE) {
sectype = Section::SEC_TYPE_CODE;
} else if(bfd_flags & SEC_DATA) {
sectype = Section::SEC_TYPE_DATA;
} else {
continue;
}
vma = bfd_section_vma(bfd_h, bfd_sec);
size = bfd_section_size(bfd_h, bfd_sec);
secname = bfd_section_name(bfd_h, bfd_sec);
if(!secname) secname = "<unnamed>";
bin->sections.push_back(Section());
sec = &bin->sections.back();
sec->binary = bin;
sec->name = std::string(secname);
sec->type = sectype;
sec->vma = vma;
sec->size = size;
sec->bytes = (uint8_t*)malloc(size);
if(!sec->bytes) {
fprintf(stderr, "out of memory\n");
return -1;
}
if(!bfd_get_section_contents(bfd_h, bfd_sec, sec->bytes, 0, size)) {
fprintf(stderr, "failed to read section '%s' (%s)\n",
secname, bfd_errmsg(bfd_get_error()));
return -1;
}
}
return 0;
}
static int
load_binary_bfd(std::string &fname, Binary *bin, Binary::BinaryType type)
{
int ret;
bfd *bfd_h;
const bfd_arch_info_type *bfd_info;
bfd_h = NULL;
bfd_h = open_bfd(fname);
if(!bfd_h) {
goto fail;
}
bin->filename = std::string(fname);
bin->entry = bfd_get_start_address(bfd_h);
bin->type_str = std::string(bfd_h->xvec->name);
switch(bfd_h->xvec->flavour) {
case bfd_target_elf_flavour:
bin->type = Binary::BIN_TYPE_ELF;
break;
case bfd_target_coff_flavour:
bin->type = Binary::BIN_TYPE_PE;
break;
case bfd_target_unknown_flavour:
default:
fprintf(stderr, "unsupported binary type (%s)\n", bfd_h->xvec->name);
goto fail;
}
bfd_info = bfd_get_arch_info(bfd_h);
bin->arch_str = std::string(bfd_info->printable_name);
switch(bfd_info->mach) {
case bfd_mach_i386_i386:
bin->arch = Binary::ARCH_X86;
bin->bits = 32;
break;
case bfd_mach_x86_64:
bin->arch = Binary::ARCH_X86;
bin->bits = 64;
break;
default:
fprintf(stderr, "unsupported architecture (%s)\n",
bfd_info->printable_name);
goto fail;
}
/* Symbol handling is best-effort only (they may not even be present) */
load_symbols_bfd(bfd_h, bin);
load_dynsym_bfd(bfd_h, bin);
if(load_sections_bfd(bfd_h, bin) < 0) goto fail;
ret = 0;
goto cleanup;
fail:
ret = -1;
cleanup:
if(bfd_h) bfd_close(bfd_h);
return ret;
}
int
load_binary(std::string &fname, Binary *bin, Binary::BinaryType type)
{
return load_binary_bfd(fname, bin, type);
}
void
unload_binary(Binary *bin)
{
size_t i;
Section *sec;
for(i = 0; i < bin->sections.size(); i++) {
sec = &bin->sections[i];
if(sec->bytes) {
free(sec->bytes);
}
}
}
C
복사
./inc/loader.h
#ifndef LOADER_H
#define LOADER_H
#include <stdint.h>
#include <string>
#include <vector>
class Binary;
class Section;
class Symbol;
class Symbol {
public:
enum SymbolType {
SYM_TYPE_UKN = 0,
SYM_TYPE_FUNC = 1,
SYM_TYPE_WEAK = 2,
SYM_TYPE_GLOBAL = 3,
SYM_TYPE_LOCAL = 4
};
Symbol() : type(SYM_TYPE_UKN), name(), addr(0), ctype(0) {}
SymbolType type;
std::string name;
uint64_t addr;
unsigned int ctype;
};
class Section {
public:
enum SectionType {
SEC_TYPE_NONE = 0,
SEC_TYPE_CODE = 1,
SEC_TYPE_DATA = 2
};
Section() : binary(NULL), type(SEC_TYPE_NONE), vma(0), size(0), bytes(NULL) {}
bool contains (uint64_t addr) { return (addr >= vma) && (addr-vma < size); }
Binary *binary;
std::string name;
SectionType type;
uint64_t vma;
uint64_t size;
uint8_t *bytes;
};
class Binary {
public:
enum BinaryType {
BIN_TYPE_AUTO = 0,
BIN_TYPE_ELF = 1,
BIN_TYPE_PE = 2
};
enum BinaryArch {
ARCH_NONE = 0,
ARCH_X86 = 1
};
Binary() : type(BIN_TYPE_AUTO), arch(ARCH_NONE), bits(0), entry(0) {}
Section *get_text_section() { for(auto &s : sections) if(s.name == ".text") return &s; return NULL; }
std::string filename;
BinaryType type;
std::string type_str;
BinaryArch arch;
std::string arch_str;
unsigned bits;
uint64_t entry;
std::vector<Section> sections;
std::vector<Symbol> symbols;
};
int load_binary (std::string &fname, Binary *bin, Binary::BinaryType type);
void unload_binary (Binary *bin);
#endif /* LOADER_H */
C
복사
./chapter4loader_demo.cc
/* Demonstrate the binary loader from ../inc/loader.cc */
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "../inc/loader.h"
int
main(int argc, char *argv[])
{
size_t i;
Binary bin;
Section *sec;
Symbol *sym;
std::string fname;
if(argc < 2) {
printf("Usage: %s <binary>\n", argv[0]);
return 1;
}
fname.assign(argv[1]);
if(load_binary(fname, &bin, Binary::BIN_TYPE_AUTO) < 0) {
return 1;
}
printf("loaded binary '%s' %s/%s (%u bits) entry@0x%016jx\n",
bin.filename.c_str(),
bin.type_str.c_str(), bin.arch_str.c_str(),
bin.bits, bin.entry);
for(i = 0; i < bin.sections.size(); i++)
{
sec = &bin.sections[i];
if(argc == 3)
{
if(strcasecmp(argv[2],sec->name.c_str()) == 0)
{
int line = 0;
printf(" 0x%016jx %-8ju %-20s %s\n",
sec->vma, sec->size, sec->name.c_str(),
sec->type == Section::SEC_TYPE_CODE ? "CODE" : "DATA");
printf("Section Data\n offset 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F\n 000000 ");
for(int bc = 0; bc < sec->size ; bc++)
{
printf("%02x ",sec->bytes[bc]);
if((bc+1)%16 == 0 && bc != 0 && bc != sec->size-1)
{
line ++;
printf("\n %05x0 ",line);
}
}
printf("\n");
break;
}
}
else
{
printf(" 0x%016jx %-8ju %-20s %s\n",
sec->vma, sec->size, sec->name.c_str(),
sec->type == Section::SEC_TYPE_CODE ? "CODE" : "DATA");
}
}
if(bin.symbols.size() > 0) {
printf("scanned symbol tables\n");
for(i = 0; i < bin.symbols.size(); i++) {
sym = &bin.symbols[i];
printf(" %-40s 0x%016jx ",sym->name.c_str(), sym->addr);
if(sym->type == Symbol::SYM_TYPE_FUNC)printf("FUNC ");
if(sym->type == Symbol::SYM_TYPE_WEAK)printf("WEAK ");
if(sym->type == Symbol::SYM_TYPE_GLOBAL)printf("GLOBAL ");
if(sym->type == Symbol::SYM_TYPE_LOCAL)printf("LOCAL ");
printf("0x%05x\n",sym->ctype);
}
}
unload_binary(&bin);
return 0;
}
C
복사