static
int
get_strtab_symtab(
struct
dl_phdr_info* info,
size_t
size,
void
* ptr)
{
auto
* data =
reinterpret_cast
<Data*>(ptr);
if
(data->index != data->target) {
data->index += 1;
return
0;
}
#if DEBUG_LOG
std::cout <<
"name "
<< info->dlpi_name << std::endl;
#endif
ElfW(Dyn)* dynamic{nullptr};
ElfW(Addr) bias{0};
bool
first_phdr{
true
};
for
(
size_t
i = 0; i < info->dlpi_phnum; ++i) {
if
(info->dlpi_phdr[i].p_type == PT_LOAD and first_phdr) {
first_phdr =
false
;
bias = info->dlpi_addr - info->dlpi_phdr[i].p_vaddr;
}
if
(info->dlpi_phdr[i].p_type == PT_DYNAMIC) {
dynamic =
reinterpret_cast
<ElfW(Dyn)*>(info->dlpi_phdr[i].p_vaddr + bias);
}
}
for
(ElfW(Dyn)* d = dynamic; d->d_tag != DT_NULL; ++d) {
switch
(d->d_tag) {
case
DT_SYMTAB:
data->symtab =
reinterpret_cast
<ElfW(Sym)*>(bias + d->d_un.d_ptr);
break
;
case
DT_STRTAB:
data->strtab =
reinterpret_cast
<
const
char
*>(bias + d->d_un.d_ptr);
break
;
}
}
data->base = info->dlpi_addr;
data->name = info->dlpi_name;
#if DEBUG_LOG
std::cout <<
"strtab "
<< (
void
*)data->strtab << std::endl;
std::cout <<
"symtab "
<< (
void
*)data->symtab << std::endl;
std::cout <<
"phdr "
<< info->dlpi_phdr << std::endl;
std::cout <<
"dynamic "
<< dynamic << std::endl;
std::cout <<
"bias "
<< (
void
*)bias << std::endl;
#endif
return
1;
}
static
Data get_soinfo_next_ptr(
size_t
target)
{
Data data { nullptr, nullptr, target, 0 };
dl_iterate_phdr(get_strtab_symtab, &data);
FILE
* fp =
fopen
(
"/proc/self/maps"
,
"re"
);
if
(fp == nullptr) {
return
{ 0, 0, 0, 0, 0, {}, 0 };
}
char
line[BUFSIZ];
while
(
fgets
(line,
sizeof
(line), fp) != nullptr) {
uintptr_t
begin;
uintptr_t
end;
char
r,w;
if
(
sscanf
(line,
"%"
SCNxPTR
"-%"
SCNxPTR
" %c%c"
, &begin, &end, &r, &w) == 4) {
if
(r ==
'r'
) {
void
* ptr = memmem(
reinterpret_cast
<
void
*>(begin), end - begin, &data,
sizeof
(
void
*) * 2);
if
(ptr != nullptr and ptr != &data) {
#if DEBUG_LOG && 0
printf
(
"%s"
, line);
for
(
int
i = 0; i < 8; ++i) {
std::cout << (
reinterpret_cast
<
void
**>(ptr)[-i+1]) << std::endl;
}
#endif
data.next_ptr = &
reinterpret_cast
<
void
**>(ptr)[-2];
break
;
}
}
}
}
fclose
(fp);
return
data;
}