From: Milian Wolff Date: Fri, 5 Dec 2014 23:06:19 +0000 (+0100) Subject: first work towards runtime injection, not really working yet X-Git-Tag: submit/tizen/20180620.112952^2~384^2~13 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9e6fcc375af036b00a5f7c31fac61de03da21542;p=sdk%2Ftools%2Fheaptrack.git first work towards runtime injection, not really working yet --- diff --git a/heaptrack_inject.cpp b/heaptrack_inject.cpp new file mode 100644 index 0000000..dcdb9cc --- /dev/null +++ b/heaptrack_inject.cpp @@ -0,0 +1,116 @@ +/* + * Copyright 2014 Milian Wolff + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include +#include +#include +#include + +/** + * @file heaptrack_inject.cpp + * + * @brief Experimental support for symbol overloading after runtime injection. + */ + +namespace { + +auto original_malloc = &malloc; + +void* overwrite_malloc(size_t size) +{ + auto ret = original_malloc(size); + printf("HALLOOOOOO! %lu %p\n", size, ret); + return ret; +} + +template +struct elftable +{ + T* table = nullptr; + ElfW(Xword) size = ElfW(Xword)(); + + bool consume(const ElfW(Dyn) *dyn) + { + if (dyn->d_tag == AddrTag) { + table = reinterpret_cast(dyn->d_un.d_ptr); + return true; + } else if (dyn->d_tag == SizeTag) { + size = dyn->d_un.d_val; + return true; + } + return false; + } +}; + +using elf_string_table = elftable; +using elf_jmprel_table = elftable; +using elf_symbol_table = elftable; + +bool overwrite_symbols(const ElfW(Dyn) *dyn) +{ + elf_symbol_table symbols; + elf_jmprel_table jmprels; + elf_string_table strings; + for (; dyn->d_tag != DT_NULL; ++dyn) { + symbols.consume(dyn) || jmprels.consume(dyn) || strings.consume(dyn); + } + printf("\tfound:\tsymtab: %p = %lu, jmptab: %p = %lu, strtab %p = %lu\n", + symbols.table, symbols.size, + jmprels.table, jmprels.size, + strings.table, strings.size); + + auto relaend = reinterpret_cast(reinterpret_cast(jmprels.table) + jmprels.size); + for (auto rela = jmprels.table; rela < relaend; rela++) { + auto relsymidx = ELF64_R_SYM(rela->r_info); + const char *relsymname = strings.table + symbols.table[relsymidx].st_name; + if (strcmp("malloc", relsymname) == 0) { + printf("!!!!!!!!!1 found malloc: %p\n", reinterpret_cast(rela->r_offset)); + *reinterpret_cast(rela->r_offset) = &overwrite_malloc; + return true; + } + } + return false; +} + +int iterate_phdrs(dl_phdr_info *info, size_t /*size*/, void *data) +{ + printf(" iterate dlpi: %s\n", info->dlpi_name); + for (auto phdr = info->dlpi_phdr, end = phdr + info->dlpi_phnum; phdr != end; ++phdr) { + if (phdr->p_type == PT_DYNAMIC && (phdr->p_flags & (PF_W | PF_R)) == (PF_W | PF_R)) { + printf(" try dyn with flags=%d\n", phdr->p_flags); + if (overwrite_symbols(reinterpret_cast(phdr->p_vaddr + info->dlpi_addr))) { +// return 1; +// NOTE: stopping at the first found malloc symbol makes the "simple" demo work, +// but more complicated apps with shared libraries still don't work as expected + } + } + } + return 0; +} + +struct InitializeInjection +{ + InitializeInjection() + { + printf("init\n"); + dl_iterate_phdr(&iterate_phdrs, nullptr); + } +} initialize; + +}