18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */ 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com> 48c2ecf20Sopenharmony_ci */ 58c2ecf20Sopenharmony_ci 68c2ecf20Sopenharmony_ci#ifndef _OBJTOOL_ELF_H 78c2ecf20Sopenharmony_ci#define _OBJTOOL_ELF_H 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <stdio.h> 108c2ecf20Sopenharmony_ci#include <gelf.h> 118c2ecf20Sopenharmony_ci#include <linux/list.h> 128c2ecf20Sopenharmony_ci#include <linux/hashtable.h> 138c2ecf20Sopenharmony_ci#include <linux/rbtree.h> 148c2ecf20Sopenharmony_ci#include <linux/jhash.h> 158c2ecf20Sopenharmony_ci 168c2ecf20Sopenharmony_ci#ifdef LIBELF_USE_DEPRECATED 178c2ecf20Sopenharmony_ci# define elf_getshdrnum elf_getshnum 188c2ecf20Sopenharmony_ci# define elf_getshdrstrndx elf_getshstrndx 198c2ecf20Sopenharmony_ci#endif 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci/* 228c2ecf20Sopenharmony_ci * Fallback for systems without this "read, mmaping if possible" cmd. 238c2ecf20Sopenharmony_ci */ 248c2ecf20Sopenharmony_ci#ifndef ELF_C_READ_MMAP 258c2ecf20Sopenharmony_ci#define ELF_C_READ_MMAP ELF_C_READ 268c2ecf20Sopenharmony_ci#endif 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistruct section { 298c2ecf20Sopenharmony_ci struct list_head list; 308c2ecf20Sopenharmony_ci struct hlist_node hash; 318c2ecf20Sopenharmony_ci struct hlist_node name_hash; 328c2ecf20Sopenharmony_ci GElf_Shdr sh; 338c2ecf20Sopenharmony_ci struct rb_root symbol_tree; 348c2ecf20Sopenharmony_ci struct list_head symbol_list; 358c2ecf20Sopenharmony_ci struct list_head reloc_list; 368c2ecf20Sopenharmony_ci struct section *base, *reloc; 378c2ecf20Sopenharmony_ci struct symbol *sym; 388c2ecf20Sopenharmony_ci Elf_Data *data; 398c2ecf20Sopenharmony_ci char *name; 408c2ecf20Sopenharmony_ci int idx; 418c2ecf20Sopenharmony_ci unsigned int len; 428c2ecf20Sopenharmony_ci bool changed, text, rodata, noinstr; 438c2ecf20Sopenharmony_ci}; 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_cistruct symbol { 468c2ecf20Sopenharmony_ci struct list_head list; 478c2ecf20Sopenharmony_ci struct rb_node node; 488c2ecf20Sopenharmony_ci struct hlist_node hash; 498c2ecf20Sopenharmony_ci struct hlist_node name_hash; 508c2ecf20Sopenharmony_ci GElf_Sym sym; 518c2ecf20Sopenharmony_ci struct section *sec; 528c2ecf20Sopenharmony_ci char *name; 538c2ecf20Sopenharmony_ci unsigned int idx; 548c2ecf20Sopenharmony_ci unsigned char bind, type; 558c2ecf20Sopenharmony_ci unsigned long offset; 568c2ecf20Sopenharmony_ci unsigned int len; 578c2ecf20Sopenharmony_ci struct symbol *pfunc, *cfunc, *alias; 588c2ecf20Sopenharmony_ci u8 uaccess_safe : 1; 598c2ecf20Sopenharmony_ci u8 static_call_tramp : 1; 608c2ecf20Sopenharmony_ci u8 retpoline_thunk : 1; 618c2ecf20Sopenharmony_ci u8 return_thunk : 1; 628c2ecf20Sopenharmony_ci u8 fentry : 1; 638c2ecf20Sopenharmony_ci u8 kcov : 1; 648c2ecf20Sopenharmony_ci u8 embedded_insn : 1; 658c2ecf20Sopenharmony_ci}; 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistruct reloc { 688c2ecf20Sopenharmony_ci struct list_head list; 698c2ecf20Sopenharmony_ci struct hlist_node hash; 708c2ecf20Sopenharmony_ci union { 718c2ecf20Sopenharmony_ci GElf_Rela rela; 728c2ecf20Sopenharmony_ci GElf_Rel rel; 738c2ecf20Sopenharmony_ci }; 748c2ecf20Sopenharmony_ci struct section *sec; 758c2ecf20Sopenharmony_ci struct symbol *sym; 768c2ecf20Sopenharmony_ci unsigned long offset; 778c2ecf20Sopenharmony_ci unsigned int type; 788c2ecf20Sopenharmony_ci s64 addend; 798c2ecf20Sopenharmony_ci int idx; 808c2ecf20Sopenharmony_ci bool jump_table_start; 818c2ecf20Sopenharmony_ci}; 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci#define ELF_HASH_BITS 20 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistruct elf { 868c2ecf20Sopenharmony_ci Elf *elf; 878c2ecf20Sopenharmony_ci GElf_Ehdr ehdr; 888c2ecf20Sopenharmony_ci int fd; 898c2ecf20Sopenharmony_ci bool changed; 908c2ecf20Sopenharmony_ci char *name; 918c2ecf20Sopenharmony_ci struct list_head sections; 928c2ecf20Sopenharmony_ci DECLARE_HASHTABLE(symbol_hash, ELF_HASH_BITS); 938c2ecf20Sopenharmony_ci DECLARE_HASHTABLE(symbol_name_hash, ELF_HASH_BITS); 948c2ecf20Sopenharmony_ci DECLARE_HASHTABLE(section_hash, ELF_HASH_BITS); 958c2ecf20Sopenharmony_ci DECLARE_HASHTABLE(section_name_hash, ELF_HASH_BITS); 968c2ecf20Sopenharmony_ci DECLARE_HASHTABLE(reloc_hash, ELF_HASH_BITS); 978c2ecf20Sopenharmony_ci}; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci#define OFFSET_STRIDE_BITS 4 1008c2ecf20Sopenharmony_ci#define OFFSET_STRIDE (1UL << OFFSET_STRIDE_BITS) 1018c2ecf20Sopenharmony_ci#define OFFSET_STRIDE_MASK (~(OFFSET_STRIDE - 1)) 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci#define for_offset_range(_offset, _start, _end) \ 1048c2ecf20Sopenharmony_ci for (_offset = ((_start) & OFFSET_STRIDE_MASK); \ 1058c2ecf20Sopenharmony_ci _offset >= ((_start) & OFFSET_STRIDE_MASK) && \ 1068c2ecf20Sopenharmony_ci _offset <= ((_end) & OFFSET_STRIDE_MASK); \ 1078c2ecf20Sopenharmony_ci _offset += OFFSET_STRIDE) 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic inline u32 sec_offset_hash(struct section *sec, unsigned long offset) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci u32 ol, oh, idx = sec->idx; 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci offset &= OFFSET_STRIDE_MASK; 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci ol = offset; 1168c2ecf20Sopenharmony_ci oh = (offset >> 16) >> 16; 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_ci __jhash_mix(ol, oh, idx); 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci return ol; 1218c2ecf20Sopenharmony_ci} 1228c2ecf20Sopenharmony_ci 1238c2ecf20Sopenharmony_cistatic inline u32 reloc_hash(struct reloc *reloc) 1248c2ecf20Sopenharmony_ci{ 1258c2ecf20Sopenharmony_ci return sec_offset_hash(reloc->sec, reloc->offset); 1268c2ecf20Sopenharmony_ci} 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_cistruct elf *elf_open_read(const char *name, int flags); 1298c2ecf20Sopenharmony_cistruct section *elf_create_section(struct elf *elf, const char *name, unsigned int sh_flags, size_t entsize, int nr); 1308c2ecf20Sopenharmony_ci 1318c2ecf20Sopenharmony_ciint elf_add_reloc(struct elf *elf, struct section *sec, unsigned long offset, 1328c2ecf20Sopenharmony_ci unsigned int type, struct symbol *sym, s64 addend); 1338c2ecf20Sopenharmony_ciint elf_add_reloc_to_insn(struct elf *elf, struct section *sec, 1348c2ecf20Sopenharmony_ci unsigned long offset, unsigned int type, 1358c2ecf20Sopenharmony_ci struct section *insn_sec, unsigned long insn_off); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ciint elf_write_insn(struct elf *elf, struct section *sec, 1388c2ecf20Sopenharmony_ci unsigned long offset, unsigned int len, 1398c2ecf20Sopenharmony_ci const char *insn); 1408c2ecf20Sopenharmony_ciint elf_write_reloc(struct elf *elf, struct reloc *reloc); 1418c2ecf20Sopenharmony_ciint elf_write(struct elf *elf); 1428c2ecf20Sopenharmony_civoid elf_close(struct elf *elf); 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_cistruct section *find_section_by_name(const struct elf *elf, const char *name); 1458c2ecf20Sopenharmony_cistruct symbol *find_func_by_offset(struct section *sec, unsigned long offset); 1468c2ecf20Sopenharmony_cistruct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset); 1478c2ecf20Sopenharmony_cistruct symbol *find_symbol_by_name(const struct elf *elf, const char *name); 1488c2ecf20Sopenharmony_cistruct symbol *find_symbol_containing(const struct section *sec, unsigned long offset); 1498c2ecf20Sopenharmony_cistruct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset); 1508c2ecf20Sopenharmony_cistruct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec, 1518c2ecf20Sopenharmony_ci unsigned long offset, unsigned int len); 1528c2ecf20Sopenharmony_cistruct symbol *find_func_containing(struct section *sec, unsigned long offset); 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci#define for_each_sec(file, sec) \ 1558c2ecf20Sopenharmony_ci list_for_each_entry(sec, &file->elf->sections, list) 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci#endif /* _OBJTOOL_ELF_H */ 158