1 /* SPDX-License-Identifier: GPL-2.0-or-later */ 2 /* 3 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com> 4 */ 5 6 #ifndef _OBJTOOL_ELF_H 7 #define _OBJTOOL_ELF_H 8 9 #include <stdio.h> 10 #include <gelf.h> 11 #include <linux/list.h> 12 #include <linux/hashtable.h> 13 #include <linux/rbtree.h> 14 #include <linux/jhash.h> 15 #include <arch/elf.h> 16 17 #ifdef LIBELF_USE_DEPRECATED 18 # define elf_getshdrnum elf_getshnum 19 # define elf_getshdrstrndx elf_getshstrndx 20 #endif 21 22 /* 23 * Fallback for systems without this "read, mmaping if possible" cmd. 24 */ 25 #ifndef ELF_C_READ_MMAP 26 #define ELF_C_READ_MMAP ELF_C_READ 27 #endif 28 29 struct elf_hash_node { 30 struct elf_hash_node *next; 31 }; 32 33 struct section { 34 struct list_head list; 35 struct elf_hash_node hash; 36 struct elf_hash_node name_hash; 37 GElf_Shdr sh; 38 struct rb_root_cached symbol_tree; 39 struct list_head symbol_list; 40 struct section *base, *rsec; 41 struct symbol *sym; 42 Elf_Data *data; 43 char *name; 44 int idx; 45 bool _changed, text, rodata, noinstr, init, truncate; 46 struct reloc *relocs; 47 }; 48 49 struct symbol { 50 struct list_head list; 51 struct rb_node node; 52 struct elf_hash_node hash; 53 struct elf_hash_node name_hash; 54 GElf_Sym sym; 55 struct section *sec; 56 char *name; 57 unsigned int idx, len; 58 unsigned long offset; 59 unsigned long __subtree_last; 60 struct symbol *pfunc, *cfunc, *alias; 61 unsigned char bind, type; 62 u8 uaccess_safe : 1; 63 u8 static_call_tramp : 1; 64 u8 retpoline_thunk : 1; 65 u8 return_thunk : 1; 66 u8 fentry : 1; 67 u8 profiling_func : 1; 68 u8 warned : 1; 69 struct list_head pv_target; 70 struct reloc *relocs; 71 }; 72 73 struct reloc { 74 struct elf_hash_node hash; 75 struct section *sec; 76 struct symbol *sym; 77 struct reloc *sym_next_reloc; 78 }; 79 80 struct elf { 81 Elf *elf; 82 GElf_Ehdr ehdr; 83 int fd; 84 bool changed; 85 char *name; 86 unsigned int num_files; 87 struct list_head sections; 88 unsigned long num_relocs; 89 90 int symbol_bits; 91 int symbol_name_bits; 92 int section_bits; 93 int section_name_bits; 94 int reloc_bits; 95 96 struct elf_hash_node **symbol_hash; 97 struct elf_hash_node **symbol_name_hash; 98 struct elf_hash_node **section_hash; 99 struct elf_hash_node **section_name_hash; 100 struct elf_hash_node **reloc_hash; 101 102 struct section *section_data; 103 struct symbol *symbol_data; 104 }; 105 106 struct elf *elf_open_read(const char *name, int flags); 107 108 struct section *elf_create_section(struct elf *elf, const char *name, 109 size_t entsize, unsigned int nr); 110 struct section *elf_create_section_pair(struct elf *elf, const char *name, 111 size_t entsize, unsigned int nr, 112 unsigned int reloc_nr); 113 114 struct symbol *elf_create_prefix_symbol(struct elf *elf, struct symbol *orig, long size); 115 116 struct reloc *elf_init_reloc_text_sym(struct elf *elf, struct section *sec, 117 unsigned long offset, 118 unsigned int reloc_idx, 119 struct section *insn_sec, 120 unsigned long insn_off); 121 122 struct reloc *elf_init_reloc_data_sym(struct elf *elf, struct section *sec, 123 unsigned long offset, 124 unsigned int reloc_idx, 125 struct symbol *sym, 126 s64 addend); 127 128 int elf_write_insn(struct elf *elf, struct section *sec, 129 unsigned long offset, unsigned int len, 130 const char *insn); 131 int elf_write(struct elf *elf); 132 void elf_close(struct elf *elf); 133 134 struct section *find_section_by_name(const struct elf *elf, const char *name); 135 struct symbol *find_func_by_offset(struct section *sec, unsigned long offset); 136 struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset); 137 struct symbol *find_symbol_by_name(const struct elf *elf, const char *name); 138 struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset); 139 int find_symbol_hole_containing(const struct section *sec, unsigned long offset); 140 struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset); 141 struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec, 142 unsigned long offset, unsigned int len); 143 struct symbol *find_func_containing(struct section *sec, unsigned long offset); 144 145 /* 146 * Try to see if it's a whole archive (vmlinux.o or module). 147 * 148 * Note this will miss the case where a module only has one source file. 149 */ 150 static inline bool has_multiple_files(struct elf *elf) 151 { 152 return elf->num_files > 1; 153 } 154 155 static inline size_t elf_addr_size(struct elf *elf) 156 { 157 return elf->ehdr.e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; 158 } 159 160 static inline size_t elf_rela_size(struct elf *elf) 161 { 162 return elf_addr_size(elf) == 4 ? sizeof(Elf32_Rela) : sizeof(Elf64_Rela); 163 } 164 165 static inline unsigned int elf_data_rela_type(struct elf *elf) 166 { 167 return elf_addr_size(elf) == 4 ? R_DATA32 : R_DATA64; 168 } 169 170 static inline unsigned int elf_text_rela_type(struct elf *elf) 171 { 172 return elf_addr_size(elf) == 4 ? R_TEXT32 : R_TEXT64; 173 } 174 175 static inline bool is_reloc_sec(struct section *sec) 176 { 177 return sec->sh.sh_type == SHT_RELA || sec->sh.sh_type == SHT_REL; 178 } 179 180 static inline bool sec_changed(struct section *sec) 181 { 182 return sec->_changed; 183 } 184 185 static inline void mark_sec_changed(struct elf *elf, struct section *sec, 186 bool changed) 187 { 188 sec->_changed = changed; 189 elf->changed |= changed; 190 } 191 192 static inline unsigned int sec_num_entries(struct section *sec) 193 { 194 return sec->sh.sh_size / sec->sh.sh_entsize; 195 } 196 197 static inline unsigned int reloc_idx(struct reloc *reloc) 198 { 199 return reloc - reloc->sec->relocs; 200 } 201 202 static inline void *reloc_rel(struct reloc *reloc) 203 { 204 struct section *rsec = reloc->sec; 205 206 return rsec->data->d_buf + (reloc_idx(reloc) * rsec->sh.sh_entsize); 207 } 208 209 static inline bool is_32bit_reloc(struct reloc *reloc) 210 { 211 /* 212 * Elf32_Rel: 8 bytes 213 * Elf32_Rela: 12 bytes 214 * Elf64_Rel: 16 bytes 215 * Elf64_Rela: 24 bytes 216 */ 217 return reloc->sec->sh.sh_entsize < 16; 218 } 219 220 #define __get_reloc_field(reloc, field) \ 221 ({ \ 222 is_32bit_reloc(reloc) ? \ 223 ((Elf32_Rela *)reloc_rel(reloc))->field : \ 224 ((Elf64_Rela *)reloc_rel(reloc))->field; \ 225 }) 226 227 #define __set_reloc_field(reloc, field, val) \ 228 ({ \ 229 if (is_32bit_reloc(reloc)) \ 230 ((Elf32_Rela *)reloc_rel(reloc))->field = val; \ 231 else \ 232 ((Elf64_Rela *)reloc_rel(reloc))->field = val; \ 233 }) 234 235 static inline u64 reloc_offset(struct reloc *reloc) 236 { 237 return __get_reloc_field(reloc, r_offset); 238 } 239 240 static inline void set_reloc_offset(struct elf *elf, struct reloc *reloc, u64 offset) 241 { 242 __set_reloc_field(reloc, r_offset, offset); 243 mark_sec_changed(elf, reloc->sec, true); 244 } 245 246 static inline s64 reloc_addend(struct reloc *reloc) 247 { 248 return __get_reloc_field(reloc, r_addend); 249 } 250 251 static inline void set_reloc_addend(struct elf *elf, struct reloc *reloc, s64 addend) 252 { 253 __set_reloc_field(reloc, r_addend, addend); 254 mark_sec_changed(elf, reloc->sec, true); 255 } 256 257 258 static inline unsigned int reloc_sym(struct reloc *reloc) 259 { 260 u64 info = __get_reloc_field(reloc, r_info); 261 262 return is_32bit_reloc(reloc) ? 263 ELF32_R_SYM(info) : 264 ELF64_R_SYM(info); 265 } 266 267 static inline unsigned int reloc_type(struct reloc *reloc) 268 { 269 u64 info = __get_reloc_field(reloc, r_info); 270 271 return is_32bit_reloc(reloc) ? 272 ELF32_R_TYPE(info) : 273 ELF64_R_TYPE(info); 274 } 275 276 static inline void set_reloc_sym(struct elf *elf, struct reloc *reloc, unsigned int sym) 277 { 278 u64 info = is_32bit_reloc(reloc) ? 279 ELF32_R_INFO(sym, reloc_type(reloc)) : 280 ELF64_R_INFO(sym, reloc_type(reloc)); 281 282 __set_reloc_field(reloc, r_info, info); 283 284 mark_sec_changed(elf, reloc->sec, true); 285 } 286 static inline void set_reloc_type(struct elf *elf, struct reloc *reloc, unsigned int type) 287 { 288 u64 info = is_32bit_reloc(reloc) ? 289 ELF32_R_INFO(reloc_sym(reloc), type) : 290 ELF64_R_INFO(reloc_sym(reloc), type); 291 292 __set_reloc_field(reloc, r_info, info); 293 294 mark_sec_changed(elf, reloc->sec, true); 295 } 296 297 #define for_each_sec(file, sec) \ 298 list_for_each_entry(sec, &file->elf->sections, list) 299 300 #define sec_for_each_sym(sec, sym) \ 301 list_for_each_entry(sym, &sec->symbol_list, list) 302 303 #define for_each_sym(file, sym) \ 304 for (struct section *__sec, *__fake = (struct section *)1; \ 305 __fake; __fake = NULL) \ 306 for_each_sec(file, __sec) \ 307 sec_for_each_sym(__sec, sym) 308 309 #define for_each_reloc(rsec, reloc) \ 310 for (int __i = 0, __fake = 1; __fake; __fake = 0) \ 311 for (reloc = rsec->relocs; \ 312 __i < sec_num_entries(rsec); \ 313 __i++, reloc++) 314 315 #define for_each_reloc_from(rsec, reloc) \ 316 for (int __i = reloc_idx(reloc); \ 317 __i < sec_num_entries(rsec); \ 318 __i++, reloc++) 319 320 #define OFFSET_STRIDE_BITS 4 321 #define OFFSET_STRIDE (1UL << OFFSET_STRIDE_BITS) 322 #define OFFSET_STRIDE_MASK (~(OFFSET_STRIDE - 1)) 323 324 #define for_offset_range(_offset, _start, _end) \ 325 for (_offset = ((_start) & OFFSET_STRIDE_MASK); \ 326 _offset >= ((_start) & OFFSET_STRIDE_MASK) && \ 327 _offset <= ((_end) & OFFSET_STRIDE_MASK); \ 328 _offset += OFFSET_STRIDE) 329 330 static inline u32 sec_offset_hash(struct section *sec, unsigned long offset) 331 { 332 u32 ol, oh, idx = sec->idx; 333 334 offset &= OFFSET_STRIDE_MASK; 335 336 ol = offset; 337 oh = (offset >> 16) >> 16; 338 339 __jhash_mix(ol, oh, idx); 340 341 return ol; 342 } 343 344 static inline u32 reloc_hash(struct reloc *reloc) 345 { 346 return sec_offset_hash(reloc->sec, reloc_offset(reloc)); 347 } 348 349 #endif /* _OBJTOOL_ELF_H */ 350