📄 dl-machine.h
字号:
PPC_DCBT (&plt->fd_func); PPC_DCBT (&rel->fd_aux); PPC_DCBT (&rel->fd_func); /* If sym_map is NULL, it's a weak undefined sym; Leave the plt zero. */ if (sym_map == NULL) return 0; /* If the opd entry is not yet relocated (because it's from a shared object that hasn't been processed yet), then manually reloc it. */ if (map != sym_map && !sym_map->l_relocated#if !defined RTLD_BOOTSTRAP && defined SHARED /* Bootstrap map doesn't have l_relocated set for it. */ && sym_map != &GL(dl_rtld_map)#endif ) offset = sym_map->l_addr; /* For PPC64, fixup_plt copies the function descriptor from opd over the corresponding PLT entry. Initially, PLT Entry[i] is set up for lazy linking, or is zero. For lazy linking, the fd_toc and fd_aux entries are irrelevant, so for thread safety we write them before changing fd_func. */ plt->fd_aux = rel->fd_aux + offset; plt->fd_toc = rel->fd_toc + offset; PPC_DCBF (&plt->fd_toc); PPC_ISYNC; plt->fd_func = rel->fd_func + offset; PPC_DCBST (&plt->fd_func); PPC_ISYNC; return finaladdr;}static inline void __attribute__ ((always_inline))elf_machine_plt_conflict (Elf64_Addr *reloc_addr, Elf64_Addr finaladdr){ Elf64_FuncDesc *plt = (Elf64_FuncDesc *) reloc_addr; Elf64_FuncDesc *rel = (Elf64_FuncDesc *) finaladdr; plt->fd_func = rel->fd_func; plt->fd_aux = rel->fd_aux; plt->fd_toc = rel->fd_toc; PPC_DCBST (&plt->fd_func); PPC_DCBST (&plt->fd_aux); PPC_DCBST (&plt->fd_toc); PPC_SYNC;}/* Return the final value of a plt relocation. */static inline Elf64_Addrelf_machine_plt_value (struct link_map *map, const Elf64_Rela *reloc, Elf64_Addr value){ return value + reloc->r_addend;}/* Names of the architecture-specific auditing callback functions. */#define ARCH_LA_PLTENTER ppc64_gnu_pltenter#define ARCH_LA_PLTEXIT ppc64_gnu_pltexit#endif /* dl_machine_h */#ifdef RESOLVE_MAP#define PPC_LO(v) ((v) & 0xffff)#define PPC_HI(v) (((v) >> 16) & 0xffff)#define PPC_HA(v) PPC_HI ((v) + 0x8000)#define PPC_HIGHER(v) (((v) >> 32) & 0xffff)#define PPC_HIGHERA(v) PPC_HIGHER ((v) + 0x8000)#define PPC_HIGHEST(v) (((v) >> 48) & 0xffff)#define PPC_HIGHESTA(v) PPC_HIGHEST ((v) + 0x8000)#define BIT_INSERT(var, val, mask) \ ((var) = ((var) & ~(Elf64_Addr) (mask)) | ((val) & (mask)))#define dont_expect(X) __builtin_expect ((X), 0)extern void _dl_reloc_overflow (struct link_map *map, const char *name, Elf64_Addr *const reloc_addr, const Elf64_Sym *refsym) attribute_hidden;auto inline void __attribute__ ((always_inline))elf_machine_rela_relative (Elf64_Addr l_addr, const Elf64_Rela *reloc, void *const reloc_addr_arg){ Elf64_Addr *const reloc_addr = reloc_addr_arg; *reloc_addr = l_addr + reloc->r_addend;}#if !defined RTLD_BOOTSTRAP || USE___THREAD/* This computes the value used by TPREL* relocs. */auto inline Elf64_Addr __attribute__ ((always_inline, const))elf_machine_tprel (struct link_map *map, struct link_map *sym_map, const Elf64_Sym *sym, const Elf64_Rela *reloc){# ifndef RTLD_BOOTSTRAP if (sym_map) { CHECK_STATIC_TLS (map, sym_map);# endif return TLS_TPREL_VALUE (sym_map, sym, reloc);# ifndef RTLD_BOOTSTRAP }# endif return 0;}#endif/* Perform the relocation specified by RELOC and SYM (which is fully resolved). MAP is the object containing the reloc. */auto inline void __attribute__ ((always_inline))elf_machine_rela (struct link_map *map, const Elf64_Rela *reloc, const Elf64_Sym *sym, const struct r_found_version *version, void *const reloc_addr_arg){ Elf64_Addr *const reloc_addr = reloc_addr_arg; const int r_type = ELF64_R_TYPE (reloc->r_info);#ifndef RTLD_BOOTSTRAP const Elf64_Sym *const refsym = sym;#endif if (r_type == R_PPC64_RELATIVE) { *reloc_addr = map->l_addr + reloc->r_addend; return; } if (__builtin_expect (r_type == R_PPC64_NONE, 0)) return; /* We need SYM_MAP even in the absence of TLS, for elf_machine_fixup_plt. */ struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type); Elf64_Addr value = ((sym_map == NULL ? 0 : sym_map->l_addr + sym->st_value) + reloc->r_addend); /* For relocs that don't edit code, return. For relocs that might edit instructions, break from the switch. */ switch (r_type) { case R_PPC64_ADDR64: case R_PPC64_GLOB_DAT: *reloc_addr = value; return; case R_PPC64_JMP_SLOT:#ifdef RESOLVE_CONFLICT_FIND_MAP elf_machine_plt_conflict (reloc_addr, value);#else elf_machine_fixup_plt (map, sym_map, reloc, reloc_addr, value);#endif return;#if !defined RTLD_BOOTSTRAP || USE___THREAD case R_PPC64_DTPMOD64:# ifdef RTLD_BOOTSTRAP /* During startup the dynamic linker is always index 1. */ *reloc_addr = 1;# else /* Get the information from the link map returned by the resolve function. */ if (sym_map != NULL) *reloc_addr = sym_map->l_tls_modid;# endif return; case R_PPC64_DTPREL64: /* During relocation all TLS symbols are defined and used. Therefore the offset is already correct. */# ifndef RTLD_BOOTSTRAP if (sym_map != NULL) *reloc_addr = TLS_DTPREL_VALUE (sym, reloc);# endif return; case R_PPC64_TPREL64: *reloc_addr = elf_machine_tprel (map, sym_map, sym, reloc); return; case R_PPC64_TPREL16_LO_DS: value = elf_machine_tprel (map, sym_map, sym, reloc); if (dont_expect ((value & 3) != 0)) _dl_reloc_overflow (map, "R_PPC64_TPREL16_LO_DS", reloc_addr, refsym); *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr, value, 0xfffc); break; case R_PPC64_TPREL16_DS: value = elf_machine_tprel (map, sym_map, sym, reloc); if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0)) _dl_reloc_overflow (map, "R_PPC64_TPREL16_DS", reloc_addr, refsym); *(Elf64_Half *) reloc_addr = BIT_INSERT (*(Elf64_Half *) reloc_addr, value, 0xfffc); break; case R_PPC64_TPREL16: value = elf_machine_tprel (map, sym_map, sym, reloc); if (dont_expect ((value + 0x8000) >= 0x10000)) _dl_reloc_overflow (map, "R_PPC64_TPREL16", reloc_addr, refsym); *(Elf64_Half *) reloc_addr = PPC_LO (value); break; case R_PPC64_TPREL16_LO: value = elf_machine_tprel (map, sym_map, sym, reloc); *(Elf64_Half *) reloc_addr = PPC_LO (value); break; case R_PPC64_TPREL16_HI: value = elf_machine_tprel (map, sym_map, sym, reloc); *(Elf64_Half *) reloc_addr = PPC_HI (value); break; case R_PPC64_TPREL16_HA: value = elf_machine_tprel (map, sym_map, sym, reloc); *(Elf64_Half *) reloc_addr = PPC_HA (value); break; case R_PPC64_TPREL16_HIGHER: value = elf_machine_tprel (map, sym_map, sym, reloc); *(Elf64_Half *) reloc_addr = PPC_HIGHER (value); break; case R_PPC64_TPREL16_HIGHEST: value = elf_machine_tprel (map, sym_map, sym, reloc); *(Elf64_Half *) reloc_addr = PPC_HIGHEST (value); break; case R_PPC64_TPREL16_HIGHERA: value = elf_machine_tprel (map, sym_map, sym, reloc); *(Elf64_Half *) reloc_addr = PPC_HIGHERA (value); break; case R_PPC64_TPREL16_HIGHESTA: value = elf_machine_tprel (map, sym_map, sym, reloc); *(Elf64_Half *) reloc_addr = PPC_HIGHESTA (value); break;#endif#ifndef RTLD_BOOTSTRAP /* None of the following appear in ld.so */ case R_PPC64_ADDR16_LO_DS: if (dont_expect ((value & 3) != 0)) _dl_reloc_overflow (map, "R_PPC64_ADDR16_LO_DS", reloc_addr, refsym); BIT_INSERT (*(Elf64_Half *) reloc_addr, value, 0xfffc); break; case R_PPC64_ADDR16_LO: *(Elf64_Half *) reloc_addr = PPC_LO (value); break; case R_PPC64_ADDR16_HI: *(Elf64_Half *) reloc_addr = PPC_HI (value); break; case R_PPC64_ADDR16_HA: *(Elf64_Half *) reloc_addr = PPC_HA (value); break; case R_PPC64_ADDR30: { Elf64_Addr delta = value - (Elf64_Xword) reloc_addr; if (dont_expect ((delta + 0x80000000) >= 0x10000000 || (delta & 3) != 0)) _dl_reloc_overflow (map, "R_PPC64_ADDR30", reloc_addr, refsym); BIT_INSERT (*(Elf64_Word *) reloc_addr, delta, 0xfffffffc); } break; case R_PPC64_COPY: if (dont_expect (sym == NULL)) /* This can happen in trace mode when an object could not be found. */ return; if (dont_expect (sym->st_size > refsym->st_size || (GLRO(dl_verbose) && sym->st_size < refsym->st_size))) { const char *strtab; strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]); _dl_error_printf ("%s: Symbol `%s' has different size" \ " in shared object," \ " consider re-linking\n", _dl_argv[0] ?: "<program name unknown>", strtab + refsym->st_name); } memcpy (reloc_addr_arg, (char *) value, MIN (sym->st_size, refsym->st_size)); return; case R_PPC64_UADDR64: /* We are big-endian. */ ((char *) reloc_addr_arg)[0] = (value >> 56) & 0xff; ((char *) reloc_addr_arg)[1] = (value >> 48) & 0xff; ((char *) reloc_addr_arg)[2] = (value >> 40) & 0xff; ((char *) reloc_addr_arg)[3] = (value >> 32) & 0xff; ((char *) reloc_addr_arg)[4] = (value >> 24) & 0xff; ((char *) reloc_addr_arg)[5] = (value >> 16) & 0xff; ((char *) reloc_addr_arg)[6] = (value >> 8) & 0xff; ((char *) reloc_addr_arg)[7] = (value >> 0) & 0xff; return; case R_PPC64_UADDR32: /* We are big-endian. */ ((char *) reloc_addr_arg)[0] = (value >> 24) & 0xff; ((char *) reloc_addr_arg)[1] = (value >> 16) & 0xff; ((char *) reloc_addr_arg)[2] = (value >> 8) & 0xff; ((char *) reloc_addr_arg)[3] = (value >> 0) & 0xff; return; case R_PPC64_ADDR32: if (dont_expect ((value + 0x80000000) >= 0x10000000)) _dl_reloc_overflow (map, "R_PPC64_ADDR32", reloc_addr, refsym); *(Elf64_Word *) reloc_addr = value; return; case R_PPC64_ADDR24: if (dont_expect ((value + 0x2000000) >= 0x4000000 || (value & 3) != 0)) _dl_reloc_overflow (map, "R_PPC64_ADDR24", reloc_addr, refsym); BIT_INSERT (*(Elf64_Word *) reloc_addr, value, 0x3fffffc); break; case R_PPC64_ADDR16: if (dont_expect ((value + 0x8000) >= 0x10000)) _dl_reloc_overflow (map, "R_PPC64_ADDR16", reloc_addr, refsym); *(Elf64_Half *) reloc_addr = value; break; case R_PPC64_UADDR16: if (dont_expect ((value + 0x8000) >= 0x10000)) _dl_reloc_overflow (map, "R_PPC64_UADDR16", reloc_addr, refsym); /* We are big-endian. */ ((char *) reloc_addr_arg)[0] = (value >> 8) & 0xff; ((char *) reloc_addr_arg)[1] = (value >> 0) & 0xff; break; case R_PPC64_ADDR16_DS: if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0)) _dl_reloc_overflow (map, "R_PPC64_ADDR16_DS", reloc_addr, refsym); BIT_INSERT (*(Elf64_Half *) reloc_addr, value, 0xfffc); break; case R_PPC64_ADDR16_HIGHER: *(Elf64_Half *) reloc_addr = PPC_HIGHER (value); break; case R_PPC64_ADDR16_HIGHEST: *(Elf64_Half *) reloc_addr = PPC_HIGHEST (value); break; case R_PPC64_ADDR16_HIGHERA: *(Elf64_Half *) reloc_addr = PPC_HIGHERA (value); break; case R_PPC64_ADDR16_HIGHESTA: *(Elf64_Half *) reloc_addr = PPC_HIGHESTA (value); break; case R_PPC64_ADDR14: case R_PPC64_ADDR14_BRTAKEN: case R_PPC64_ADDR14_BRNTAKEN: { if (dont_expect ((value + 0x8000) >= 0x10000 || (value & 3) != 0)) _dl_reloc_overflow (map, "R_PPC64_ADDR14", reloc_addr, refsym); Elf64_Word insn = *(Elf64_Word *) reloc_addr; BIT_INSERT (insn, value, 0xfffc); if (r_type != R_PPC64_ADDR14) { insn &= ~(1 << 21); if (r_type == R_PPC64_ADDR14_BRTAKEN) insn |= 1 << 21; if ((insn & (0x14 << 21)) == (0x04 << 21)) insn |= 0x02 << 21; else if ((insn & (0x14 << 21)) == (0x10 << 21)) insn |= 0x08 << 21; } *(Elf64_Word *) reloc_addr = insn; } break; case R_PPC64_REL32: *(Elf64_Word *) reloc_addr = value - (Elf64_Addr) reloc_addr; return; case R_PPC64_REL64: *reloc_addr = value - (Elf64_Addr) reloc_addr; return;#endif /* !RTLD_BOOTSTRAP */ default: _dl_reloc_bad_type (map, r_type, 0); return; } MODIFIED_CODE_NOQUEUE (reloc_addr);}auto inline void __attribute__ ((always_inline))elf_machine_lazy_rel (struct link_map *map, Elf64_Addr l_addr, const Elf64_Rela *reloc){ /* elf_machine_runtime_setup handles this. */}#endif /* RESOLVE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -