static
char
getTargetFuncInfo
(
int
fd
,
const
char
*
funcName
,
funcInfo
*
info
)
{
char
flag
=
-
1
,
*
dynstr
;
int
i
;
Elf32_Sym
funSym
;
Elf32_Phdr
phdr
;
Elf32_Off
dyn_off
;
Elf32_Word
dyn_size
,
dyn_strsz
;
Elf32_Dyn
dyn
;
Elf32_Addr
dyn_symtab
,
dyn_strtab
,
dyn_hash
;
unsigned
funHash
,
nbucket
,
nchain
,
funIndex
;
lseek
(
fd
,
ehdr
.
e_phoff
,
SEEK_SET
)
;
//elf header中e_phoff表示的是程序头的偏移
/*
循环遍历,找到.dynamic这个section 并记录其大小和偏移
*/
for
(
i
=
0
;
i
<
ehdr
.
e_phnum
;
i
++
)
{
if
(
read
(
fd
,
&phdr
,
sizeof
(
Elf32_Phdr
)
)
!=
sizeof
(
Elf32_Phdr
)
)
{
//读取peogram header 保存在phdr中
puts
(
"Read segment failed"
)
;
goto
_error
;
}
if
(
phdr
.
p_type
==
PT_DYNAMIC
)
{
// PT_DYNAMIC 表示数组元素给出动态链接信息
dyn_size
=
phdr
.
p_filesz
;
// p_filesz 段在文件映像中所占的字节数
dyn_off
=
phdr
.
p_offset
;
// 从文件头到该段第一个字节的偏移
flag
=
0
;
printf
(
"Find section %s, size = 0x%x, addr = 0x%x\n"
,
".dynamic"
,
dyn_size
,
dyn_off
)
;
break
;
}
}
if
(
flag
)
{
puts
(
"Find .dynamic failed"
)
;
goto
_error
;
}
flag
=
0
;
lseek
(
fd
,
dyn_off
,
SEEK_SET
)
;
//定位到.dynamic
for
(
i
=
0
;
i
<
dyn_size
/
sizeof
(
Elf32_Dyn
)
;
i
++
)
{
if
(
read
(
fd
,
&dyn
,
sizeof
(
Elf32_Dyn
)
)
!=
sizeof
(
Elf32_Dyn
)
)
{
puts
(
"Read .dynamic information failed"
)
;
goto
_error
;
}
if
(
dyn
.
d_tag
==
DT_SYMTAB
)
{
//循环遍历,找到d_tag为DT_SYMATAB的一项, dyn此元素包含符号表的地址
dyn_symtab
=
dyn
.
d_un
.
d_ptr
;
//此 Elf32_Addr 对象代表程序的虚拟地址
flag
+=
1
;
printf
(
"Find .dynsym, addr = 0x%x\n"
,
dyn_symtab
)
;
}
if
(
dyn
.
d_tag
==
DT_HASH
)
{
//循环遍历,找到.hash
dyn_hash
=
dyn
.
d_un
.
d_ptr
;
flag
+=
2
;
printf
(
"Find .hash, addr = 0x%x\n"
,
dyn_hash
)
;
}
if
(
dyn
.
d_tag
==
DT_STRTAB
)
{
//找到.dynstr的位置
dyn_strtab
=
dyn
.
d_un
.
d_ptr
;
flag
+=
4
;
printf
(
"Find .dynstr, addr = 0x%x\n"
,
dyn_strtab
)
;
}
if
(
dyn
.
d_tag
==
DT_STRSZ
)
{
//找到.dynstr的大小
dyn_strsz
=
dyn
.
d_un
.
d_val
;
flag
+=
8
;
printf
(
"Find .dynstr size, size = 0x%x\n"
,
dyn_strsz
)
;
}
}
if
(
(
flag
&
0x0f
)
!=
0x0f
)
{
//判断是不是全部都找到了
puts
(
"Find needed .section failed\n"
)
;
goto
_error
;
}
dynstr
=
(
char
*
)
malloc
(
dyn_strsz
)
;
//根据大小申请内存空间
if
(
dynstr
==
NULL
)
{
puts
(
"Malloc .dynstr space failed"
)
;
goto
_error
;
}
lseek
(
fd
,
dyn_strtab
,
SEEK_SET
)
;
//定位到dyn_strtab 读取.dynstr里面的字符串值
if
(
read
(
fd
,
dynstr
,
dyn_strsz
)
!=
dyn_strsz
)
{
puts
(
"Read .dynstr failed"
)
;
goto
_error
;
}
// print_all(dynstr, dyn_strsz);
funHash
=
elfhash
(
funcName
)
;
//调用elf_hash函数,根据函数名计算一个索引值
printf
(
"Function %s hashVal = 0x%x\n"
,
funcName
,
funHash
)
;
lseek
(
fd
,
dyn_hash
,
SEEK_SET
)
;
//读取hash表中的nbucket
if
(
read
(
fd
,
&nbucket
,
4
)
!=
4
)
{
puts
(
"Read hash nbucket failed\n"
)
;
goto
_error
;
}
printf
(
"nbucket = %d\n"
,
nbucket
)
;
if
(
read
(
fd
,
&nchain
,
4
)
!=
4
)
{
//读取hash表中的nchain
puts
(
"Read hash nchain failed\n"
)
;
goto
_error
;
}
// printf("nchain = %d\n", nchain);
funHash
=
funHash
%
nbucket
;
printf
(
"funHash mod nbucket = %d \n"
,
funHash
)
;
lseek
(
fd
,
funHash
*
4
,
SEEK_CUR
)
;
if
(
read
(
fd
,
&funIndex
,
4
)
!=
4
)
{
puts
(
"Read funIndex failed\n"
)
;
goto
_error
;
}
lseek
(
fd
,
dyn_symtab
+
funIndex
*
sizeof
(
Elf32_Sym
)
,
SEEK_SET
)
;
//
if
(
read
(
fd
,
&funSym
,
sizeof
(
Elf32_Sym
)
)
!=
sizeof
(
Elf32_Sym
)
)
{
puts
(
"Read funSym failed"
)
;
goto
_error
;
}
if
(
strcmp
(
dynstr
+
funSym
.
st_name
,
funcName
)
!=
0
)
//循环,在chain表中查找需要的符号表
{
while
(
1
)
{
lseek
(
fd
,
dyn_hash
+
4
*
(
2
+
nbucket
+
funIndex
)
,
SEEK_SET
)
;
//在chain数组中定位
if
(
read
(
fd
,
&funIndex
,
4
)
!=
4
)
{
puts
(
"Read funIndex failed\n"
)
;
goto
_error
;
}
if
(
funIndex
==
0
)
{
puts
(
"Cannot find funtion!\n"
)
;
goto
_error
;
}
lseek
(
fd
,
dyn_symtab
+
funIndex
*
sizeof
(
Elf32_Sym
)
,
SEEK_SET
)
;
//根据索引,在syn_symtab中找到对应的结构体
if
(
read
(
fd
,
&funSym
,
sizeof
(
Elf32_Sym
)
)
!=
sizeof
(
Elf32_Sym
)
)
{
puts
(
"In FOR loop, Read funSym failed"
)
;
goto
_error
;
}
if
(
strcmp
(
dynstr
+
funSym
.
st_name
,
funcName
)
==
0
)
{
break
;
}
}
}
printf
(
"Find: %s, offset = 0x%x, size = 0x%x\n"
,
funcName
,
funSym
.
st_value
,
funSym
.
st_size
)
;
info
->
st_value
=
funSym
.
st_value
;
info
->
st_size
=
funSym
.
st_size
;
free
(
dynstr
)
;
return
0
;
_error
:
free
(
dynstr
)
;
return
-
1
;
}