#if (defined __x86_64__) || (defined __aarch64__)
+
# define PLTREL ElfW(Rela)
+
+enum {
+ RELPTR = DT_RELA,
+ RELSZ = DT_RELASZ,
+};
+
#elif (defined __i386__) || (defined __arm__) || (defined __thumb__)
+
# define PLTREL ElfW(Rel)
+
+enum {
+ RELPTR = DT_REL,
+ RELSZ = DT_RELSZ,
+};
+
#else
#error "This arch is not supported"
#endif
ElfW(Dyn) *l_info[0];
};
+struct sdesc_id_t {
+ int ptr_id;
+ int s_size_id;
+};
-const char *lmap_get_name(const struct link_map *map, unsigned long offset)
-{
- const struct ext_map *emap = (const struct ext_map *)map;
- const char *strtab;
- const PLTREL *reloc;
- const ElfW(Sym) *symtab;
- const ElfW(Sym) *sym;
-
- symtab = (const void *)D_PTR(emap, l_info[DT_SYMTAB]);
- strtab = (const void *)D_PTR(emap, l_info[DT_STRTAB]);
- reloc = (const void *)(D_PTR(emap, l_info[DT_JMPREL]) + offset);
- sym = &symtab[ELFW(R_SYM)(reloc->r_info)];
- return strtab + sym->st_name;
-}
+static struct sdesc_id_t got = {
+ .ptr_id = RELPTR,
+ .s_size_id = RELSZ,
+};
-unsigned long lmap_reladdr_by_offset(const struct link_map *map,
- unsigned long offset)
-{
- const struct ext_map *emap = (const struct ext_map *)map;
+static struct sdesc_id_t got_plt = {
+ .ptr_id = DT_JMPREL,
+ .s_size_id = DT_PLTRELSZ,
+};
- return (unsigned long)(D_PTR(emap, l_info[DT_JMPREL]) + offset);
-}
-unsigned long lmap_reladdr_by_name(const struct link_map *map, const char *name)
+static unsigned long _addr_by_name(const struct link_map *map, const char *name,
+ struct sdesc_id_t *sdesc)
{
const struct ext_map *emap = (const struct ext_map *)map;
const char *strtab;
return 0;
/* relocation table doesn't exist */
- if (emap->l_info[DT_PLTRELSZ] == NULL)
+ if (emap->l_info[sdesc->s_size_id] == NULL)
return 0;
symtab = (const void *)D_PTR(emap, l_info[DT_SYMTAB]);
strtab = (const void *)D_PTR(emap, l_info[DT_STRTAB]);
- size = emap->l_info[DT_PLTRELSZ]->d_un.d_val;
+ size = emap->l_info[sdesc->s_size_id]->d_un.d_val;
for (offset = 0; offset < size; offset += sizeof(PLTREL)) {
const PLTREL *reloc;
const ElfW(Sym) *sym;
const char *sym_name;
- reloc = (const void *)(D_PTR(emap, l_info[DT_JMPREL]) + offset);
+ reloc = (const void *)(D_PTR(emap, l_info[sdesc->ptr_id]) +
+ offset);
sym = &symtab[ELFW(R_SYM)(reloc->r_info)];
sym_name = strtab + sym->st_name;
return 0;
}
+
+
+const char *lmap_get_name(const struct link_map *map, unsigned long offset)
+{
+ const struct ext_map *emap = (const struct ext_map *)map;
+ const char *strtab;
+ const PLTREL *reloc;
+ const ElfW(Sym) *symtab;
+ const ElfW(Sym) *sym;
+
+ symtab = (const void *)D_PTR(emap, l_info[DT_SYMTAB]);
+ strtab = (const void *)D_PTR(emap, l_info[DT_STRTAB]);
+ reloc = (const void *)(D_PTR(emap, l_info[DT_JMPREL]) + offset);
+
+ sym = &symtab[ELFW(R_SYM)(reloc->r_info)];
+ return strtab + sym->st_name;
+}
+
+unsigned long lmap_reladdr_by_offset(const struct link_map *map,
+ unsigned long offset)
+{
+ const struct ext_map *emap = (const struct ext_map *)map;
+
+ return (unsigned long)(D_PTR(emap, l_info[DT_JMPREL]) + offset);
+}
+
+unsigned long lmap_reladdr_by_name(const struct link_map *map, const char *name)
+{
+ return _addr_by_name(map, name, &got_plt);
+}
+
+unsigned long lmap_gotaddr_by_name(const struct link_map *map, const char *name)
+{
+ return _addr_by_name(map, name, &got);
+}
static void *_get_orig_on_demand(unsigned long addr)
{
Dl_info sym_info;
+ /* TODO Add other libraries after splitting */
const char probe_lib[] = "/usr/lib/da_probe_tizen.so";
int ret;
const char udev_lib[] = "/lib/libudev.so.1";
const char evdev_lib[] = "/lib/libevdev.so.2";
const char evdev[] = "/usr/lib/libevdev.so.2";
+ const char libc[] = "/lib/libc.so.6";
if (!strcmp(probe_lib, path) ||
!strcmp(event_lib, path) ||
!strcmp(udev_lib, path) ||
!strcmp(udev, path) ||
!strcmp(evdev_lib, path) ||
- !strcmp(evdev, path))
+ !strcmp(evdev, path) ||
+ !strcmp(libc, path))
return true;
return false;
}
+
+static void _patch_sym(struct link_map *map, struct probe_desc_t *probe)
+{
+ unsigned long addr;
+ void *orig;
+
+ /* Patch symbol in .got.plt section */
+ addr = lmap_reladdr_by_name(map, probe->orig_name);
+ if (addr == 0)
+ goto patch_got;
+
+ orig = _get_orig_on_demand(addr);
+ if (orig != NULL) {
+ probe->orig_ptr = (ElfW(Addr))orig;
+ *(ElfW(Addr) *)addr = probe->handler_ptr;
+ }
+
+patch_got:
+ /* Patch symbol in .got section */
+ addr = lmap_gotaddr_by_name(map, probe->orig_name);
+ if (addr == 0)
+ return;
+
+ orig = _get_orig_on_demand(addr);
+ if (orig != NULL) {
+ probe->orig_ptr = (ElfW(Addr))orig;
+ *(ElfW(Addr) *)addr = probe->handler_ptr;
+ }
+}
+
+
static int _patch_bin(struct dl_phdr_info *info, size_t __unused size, void *data)
{
struct link_map *map;
bool is_for_all;
bool is_ign;
unsigned int i;
- unsigned long addr;
- void *orig, *handle;
+ void *handle;
struct feature_desc_t *feature = (struct feature_desc_t *)data;
/* Get binary path */
((feature->probes[i].flags != GT_TARGET_PROBE) && target_bin))
continue;
- addr = lmap_reladdr_by_name(map, feature->probes[i].orig_name);
- if (addr == 0)
- continue;
-
- orig = _get_orig_on_demand(addr);
- if (orig != NULL) {
- feature->probes[i].orig_ptr = (ElfW(Addr))orig;
- *(ElfW(Addr) *)addr = feature->probes[i].handler_ptr;
- }
+ _patch_sym(map, &feature->probes[i]);
}
fail_get_map:
const char *path = l->l_name;
bool target_bin;
bool is_for_all;
- unsigned long addr;
- void *orig;
target_bin = _check_if_patch(path);
target_bin))
continue;
- addr = lmap_reladdr_by_name(l,
- features[i]->probes[j].orig_name);
- if (addr == 0)
- continue;
-
- orig = _get_orig_on_demand(addr);
- if (orig != NULL) {
- features[i]->probes[j].orig_ptr = (ElfW(Addr))orig;
- *(ElfW(Addr) *)addr =
- features[i]->probes[j].handler_ptr;
- }
+ _patch_sym(l, &features[i]->probes[j]);
}
}
}