template<typename ElfRelIteratorT>
bool
soinfo::relocate(const VersionTracker& version_tracker, ElfRelIteratorT&& rel_iterator,
const soinfo_list_t& global_group, const soinfo_list_t& local_group){
for
(size_t idx
=
0
; rel_iterator.has_next();
+
+
idx) {
const auto rel
=
rel_iterator.
next
();
if
(rel
=
=
nullptr) {
return
false;
}
/
/
获取rel 的类型 , 和符号索引
ElfW(Word)
type
=
ELFW(R_TYPE)(rel
-
>r_info);
ElfW(Word) sym
=
ELFW(R_SYM)(rel
-
>r_info);
/
/
rel 内存地址
ElfW(Addr) reloc
=
static_cast<ElfW(Addr)>(rel
-
>r_offset
+
load_bias);
ElfW(Addr) sym_addr
=
0
;
const char
*
sym_name
=
nullptr;
ElfW(Addr) addend
=
get_addend(rel, reloc);
DEBUG(
"Processing \"%s\" relocation at index %zd"
, get_realpath(), idx);
if
(
type
=
=
R_GENERIC_NONE) {
continue
;
}
const ElfW(Sym)
*
s
=
nullptr;
soinfo
*
lsi
=
nullptr;
if
(sym !
=
0
) {
/
/
从符号表中获取到符号名称
sym_name
=
get_string(symtab_[sym].st_name);
const version_info
*
vi
=
nullptr;
if
(!lookup_version_info(version_tracker, sym, sym_name, &vi)) {
return
false;
}
/
/
这个函数可以解释LD_PRELOAD 对于相同符号名称linker的处理方式。
if
(!soinfo_do_lookup(this, sym_name, vi, &lsi, global_group, local_group, &s)) {
return
false;
}
if
(s
=
=
nullptr) {
/
/
We only allow an undefined symbol
if
this
is
a weak reference...
s
=
&symtab_[sym];
if
(ELF_ST_BIND(s
-
>st_info) !
=
STB_WEAK) {
DL_ERR(
"cannot locate symbol \"%s\" referenced by \"%s\"..."
, sym_name, get_realpath());
return
false;
}
case R_ARM_ABS32:
/
*
*
The sym_addr was initialized to be zero above,
or
the relocation
*
code below does
not
care about value of sym_addr.
*
No need to do anything.
*
/
break
;
case R_X86_64_PC32:
sym_addr
=
reloc;
break
;
case R_386_PC32:
sym_addr
=
reloc;
break
;
default:
DL_ERR(
"unknown weak reloc type %d @ %p (%zu)"
,
type
, rel, idx);
return
false;
}
}
else
{
/
/
We got a definition.
/
*
.......
*
/
}
count_relocation(kRelocSymbol);
}
/
/
重定位运算。
switch (
type
) {
case R_GENERIC_JUMP_SLOT:
count_relocation(kRelocAbsolute);
MARK(rel
-
>r_offset);
TRACE_TYPE(RELO,
"RELO JMP_SLOT %16p <- %16p %s\n"
,
reinterpret_cast<void
*
>(reloc),
reinterpret_cast<void
*
>(sym_addr
+
addend), sym_name);
*
reinterpret_cast<ElfW(Addr)
*
>(reloc)
=
(sym_addr
+
addend);
break
;
case R_GENERIC_GLOB_DAT:
count_relocation(kRelocAbsolute);
MARK(rel
-
>r_offset);
TRACE_TYPE(RELO,
"RELO GLOB_DAT %16p <- %16p %s\n"
,
reinterpret_cast<void
*
>(reloc),
reinterpret_cast<void
*
>(sym_addr
+
addend), sym_name);
*
reinterpret_cast<ElfW(Addr)
*
>(reloc)
=
(sym_addr
+
addend);
break
;
case R_GENERIC_RELATIVE:
count_relocation(kRelocRelative);
MARK(rel
-
>r_offset);
TRACE_TYPE(RELO,
"RELO RELATIVE %16p <- %16p\n"
,
reinterpret_cast<void
*
>(reloc),
reinterpret_cast<void
*
>(load_bias
+
addend));
*
reinterpret_cast<ElfW(Addr)
*
>(reloc)
=
(load_bias
+
addend);
break
;
case R_GENERIC_IRELATIVE:
count_relocation(kRelocRelative);
MARK(rel
-
>r_offset);
TRACE_TYPE(RELO,
"RELO IRELATIVE %16p <- %16p\n"
,
reinterpret_cast<void
*
>(reloc),
reinterpret_cast<void
*
>(load_bias
+
addend));
{
/
*
...
*
/
/
*
...
*
/
*
reinterpret_cast<ElfW(Addr)
*
>(reloc)
=
ifunc_addr;
}
break
;
case R_ARM_ABS32:
count_relocation(kRelocAbsolute);
MARK(rel
-
>r_offset);
TRACE_TYPE(RELO,
"RELO ABS %08x <- %08x %s"
, reloc, sym_addr, sym_name);
*
reinterpret_cast<ElfW(Addr)
*
>(reloc)
+
=
sym_addr;
break
;
case R_ARM_REL32:
count_relocation(kRelocRelative);
MARK(rel
-
>r_offset);
TRACE_TYPE(RELO,
"RELO REL32 %08x <- %08x - %08x %s"
,
reloc, sym_addr, rel
-
>r_offset, sym_name);
*
reinterpret_cast<ElfW(Addr)
*
>(reloc)
+
=
sym_addr
-
rel
-
>r_offset;
break
;
case R_ARM_COPY:
/
*
*
ET_EXEC
is
not
supported so this should
not
happen.
*
*
http:
/
/
infocenter.arm.com
/
help
/
topic
/
com.arm.doc.ihi0044d
/
IHI0044D_aaelf.pdf
*
*
Section
4.6
.
1.10
"Dynamic relocations"
*
R_ARM_COPY may only appear
in
executable objects where e_type
is
*
set
to ET_EXEC.
*
/
DL_ERR(
"%s R_ARM_COPY relocations are not supported"
, get_realpath());
return
false;
default:
DL_ERR(
"unknown reloc type %d @ %p (%zu)"
,
type
, rel, idx);
return
false;
}
}
return
true;
}