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 u8 embedded_insn : 1; 70 u8 local_label : 1; 71 u8 frame_pointer : 1; 72 u8 ignore : 1; 73 u8 nocfi : 1; 74 struct list_head pv_target; 75 struct reloc *relocs; 76 struct section *group_sec; 77 }; 78 79 struct reloc { 80 struct elf_hash_node hash; 81 struct section *sec; 82 struct symbol *sym; 83 unsigned long _sym_next_reloc; 84 }; 85 86 struct elf { 87 Elf *elf; 88 GElf_Ehdr ehdr; 89 int fd; 90 bool changed; 91 char *name; 92 unsigned int num_files; 93 struct list_head sections; 94 unsigned long num_relocs; 95 96 int symbol_bits; 97 int symbol_name_bits; 98 int section_bits; 99 int section_name_bits; 100 int reloc_bits; 101 102 struct elf_hash_node **symbol_hash; 103 struct elf_hash_node **symbol_name_hash; 104 struct elf_hash_node **section_hash; 105 struct elf_hash_node **section_name_hash; 106 struct elf_hash_node **reloc_hash; 107 108 struct section *section_data; 109 struct symbol *symbol_data; 110 }; 111 112 struct elf *elf_open_read(const char *name, int flags); 113 114 struct section *elf_create_section(struct elf *elf, const char *name, 115 size_t entsize, unsigned int nr); 116 struct section *elf_create_section_pair(struct elf *elf, const char *name, 117 size_t entsize, unsigned int nr, 118 unsigned int reloc_nr); 119 120 struct symbol *elf_create_prefix_symbol(struct elf *elf, struct symbol *orig, long size); 121 122 struct reloc *elf_init_reloc_text_sym(struct elf *elf, struct section *sec, 123 unsigned long offset, 124 unsigned int reloc_idx, 125 struct section *insn_sec, 126 unsigned long insn_off); 127 128 struct reloc *elf_init_reloc_data_sym(struct elf *elf, struct section *sec, 129 unsigned long offset, 130 unsigned int reloc_idx, 131 struct symbol *sym, 132 s64 addend); 133 134 int elf_write_insn(struct elf *elf, struct section *sec, 135 unsigned long offset, unsigned int len, 136 const char *insn); 137 int elf_write(struct elf *elf); 138 void elf_close(struct elf *elf); 139 140 struct section *find_section_by_name(const struct elf *elf, const char *name); 141 struct symbol *find_func_by_offset(struct section *sec, unsigned long offset); 142 struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset); 143 struct symbol *find_symbol_by_name(const struct elf *elf, const char *name); 144 struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset); 145 int find_symbol_hole_containing(const struct section *sec, unsigned long offset); 146 struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset); 147 struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec, 148 unsigned long offset, unsigned int len); 149 struct symbol *find_func_containing(struct section *sec, unsigned long offset); 150 151 /* 152 * Try to see if it's a whole archive (vmlinux.o or module). 153 * 154 * Note this will miss the case where a module only has one source file. 155 */ 156 static inline bool has_multiple_files(struct elf *elf) 157 { 158 return elf->num_files > 1; 159 } 160 161 static inline size_t elf_addr_size(struct elf *elf) 162 { 163 return elf->ehdr.e_ident[EI_CLASS] == ELFCLASS32 ? 4 : 8; 164 } 165 166 static inline size_t elf_rela_size(struct elf *elf) 167 { 168 return elf_addr_size(elf) == 4 ? sizeof(Elf32_Rela) : sizeof(Elf64_Rela); 169 } 170 171 static inline unsigned int elf_data_rela_type(struct elf *elf) 172 { 173 return elf_addr_size(elf) == 4 ? R_DATA32 : R_DATA64; 174 } 175 176 static inline unsigned int elf_text_rela_type(struct elf *elf) 177 { 178 return elf_addr_size(elf) == 4 ? R_TEXT32 : R_TEXT64; 179 } 180 181 static inline bool is_reloc_sec(struct section *sec) 182 { 183 return sec->sh.sh_type == SHT_RELA || sec->sh.sh_type == SHT_REL; 184 } 185 186 static inline bool sec_changed(struct section *sec) 187 { 188 return sec->_changed; 189 } 190 191 static inline void mark_sec_changed(struct elf *elf, struct section *sec, 192 bool changed) 193 { 194 sec->_changed = changed; 195 elf->changed |= changed; 196 } 197 198 static inline unsigned int sec_num_entries(struct section *sec) 199 { 200 return sec->sh.sh_size / sec->sh.sh_entsize; 201 } 202 203 static inline unsigned int reloc_idx(struct reloc *reloc) 204 { 205 return reloc - reloc->sec->relocs; 206 } 207 208 static inline void *reloc_rel(struct reloc *reloc) 209 { 210 struct section *rsec = reloc->sec; 211 212 return rsec->data->d_buf + (reloc_idx(reloc) * rsec->sh.sh_entsize); 213 } 214 215 static inline bool is_32bit_reloc(struct reloc *reloc) 216 { 217 /* 218 * Elf32_Rel: 8 bytes 219 * Elf32_Rela: 12 bytes 220 * Elf64_Rel: 16 bytes 221 * Elf64_Rela: 24 bytes 222 */ 223 return reloc->sec->sh.sh_entsize < 16; 224 } 225 226 #define __get_reloc_field(reloc, field) \ 227 ({ \ 228 is_32bit_reloc(reloc) ? \ 229 ((Elf32_Rela *)reloc_rel(reloc))->field : \ 230 ((Elf64_Rela *)reloc_rel(reloc))->field; \ 231 }) 232 233 #define __set_reloc_field(reloc, field, val) \ 234 ({ \ 235 if (is_32bit_reloc(reloc)) \ 236 ((Elf32_Rela *)reloc_rel(reloc))->field = val; \ 237 else \ 238 ((Elf64_Rela *)reloc_rel(reloc))->field = val; \ 239 }) 240 241 static inline u64 reloc_offset(struct reloc *reloc) 242 { 243 return __get_reloc_field(reloc, r_offset); 244 } 245 246 static inline void set_reloc_offset(struct elf *elf, struct reloc *reloc, u64 offset) 247 { 248 __set_reloc_field(reloc, r_offset, offset); 249 mark_sec_changed(elf, reloc->sec, true); 250 } 251 252 static inline s64 reloc_addend(struct reloc *reloc) 253 { 254 return __get_reloc_field(reloc, r_addend); 255 } 256 257 static inline void set_reloc_addend(struct elf *elf, struct reloc *reloc, s64 addend) 258 { 259 __set_reloc_field(reloc, r_addend, addend); 260 mark_sec_changed(elf, reloc->sec, true); 261 } 262 263 264 static inline unsigned int reloc_sym(struct reloc *reloc) 265 { 266 u64 info = __get_reloc_field(reloc, r_info); 267 268 return is_32bit_reloc(reloc) ? 269 ELF32_R_SYM(info) : 270 ELF64_R_SYM(info); 271 } 272 273 static inline unsigned int reloc_type(struct reloc *reloc) 274 { 275 u64 info = __get_reloc_field(reloc, r_info); 276 277 return is_32bit_reloc(reloc) ? 278 ELF32_R_TYPE(info) : 279 ELF64_R_TYPE(info); 280 } 281 282 static inline void set_reloc_sym(struct elf *elf, struct reloc *reloc, unsigned int sym) 283 { 284 u64 info = is_32bit_reloc(reloc) ? 285 ELF32_R_INFO(sym, reloc_type(reloc)) : 286 ELF64_R_INFO(sym, reloc_type(reloc)); 287 288 __set_reloc_field(reloc, r_info, info); 289 290 mark_sec_changed(elf, reloc->sec, true); 291 } 292 static inline void set_reloc_type(struct elf *elf, struct reloc *reloc, unsigned int type) 293 { 294 u64 info = is_32bit_reloc(reloc) ? 295 ELF32_R_INFO(reloc_sym(reloc), type) : 296 ELF64_R_INFO(reloc_sym(reloc), type); 297 298 __set_reloc_field(reloc, r_info, info); 299 300 mark_sec_changed(elf, reloc->sec, true); 301 } 302 303 #define RELOC_JUMP_TABLE_BIT 1UL 304 305 /* Does reloc mark the beginning of a jump table? */ 306 static inline bool is_jump_table(struct reloc *reloc) 307 { 308 return reloc->_sym_next_reloc & RELOC_JUMP_TABLE_BIT; 309 } 310 311 static inline void set_jump_table(struct reloc *reloc) 312 { 313 reloc->_sym_next_reloc |= RELOC_JUMP_TABLE_BIT; 314 } 315 316 static inline struct reloc *sym_next_reloc(struct reloc *reloc) 317 { 318 return (struct reloc *)(reloc->_sym_next_reloc & ~RELOC_JUMP_TABLE_BIT); 319 } 320 321 static inline void set_sym_next_reloc(struct reloc *reloc, struct reloc *next) 322 { 323 unsigned long bit = reloc->_sym_next_reloc & RELOC_JUMP_TABLE_BIT; 324 325 reloc->_sym_next_reloc = (unsigned long)next | bit; 326 } 327 328 #define for_each_sec(file, sec) \ 329 list_for_each_entry(sec, &file->elf->sections, list) 330 331 #define sec_for_each_sym(sec, sym) \ 332 list_for_each_entry(sym, &sec->symbol_list, list) 333 334 #define for_each_sym(file, sym) \ 335 for (struct section *__sec, *__fake = (struct section *)1; \ 336 __fake; __fake = NULL) \ 337 for_each_sec(file, __sec) \ 338 sec_for_each_sym(__sec, sym) 339 340 #define for_each_reloc(rsec, reloc) \ 341 for (int __i = 0, __fake = 1; __fake; __fake = 0) \ 342 for (reloc = rsec->relocs; \ 343 __i < sec_num_entries(rsec); \ 344 __i++, reloc++) 345 346 #define for_each_reloc_from(rsec, reloc) \ 347 for (int __i = reloc_idx(reloc); \ 348 __i < sec_num_entries(rsec); \ 349 __i++, reloc++) 350 351 #define OFFSET_STRIDE_BITS 4 352 #define OFFSET_STRIDE (1UL << OFFSET_STRIDE_BITS) 353 #define OFFSET_STRIDE_MASK (~(OFFSET_STRIDE - 1)) 354 355 #define for_offset_range(_offset, _start, _end) \ 356 for (_offset = ((_start) & OFFSET_STRIDE_MASK); \ 357 _offset >= ((_start) & OFFSET_STRIDE_MASK) && \ 358 _offset <= ((_end) & OFFSET_STRIDE_MASK); \ 359 _offset += OFFSET_STRIDE) 360 361 static inline u32 sec_offset_hash(struct section *sec, unsigned long offset) 362 { 363 u32 ol, oh, idx = sec->idx; 364 365 offset &= OFFSET_STRIDE_MASK; 366 367 ol = offset; 368 oh = (offset >> 16) >> 16; 369 370 __jhash_mix(ol, oh, idx); 371 372 return ol; 373 } 374 375 static inline u32 reloc_hash(struct reloc *reloc) 376 { 377 return sec_offset_hash(reloc->sec, reloc_offset(reloc)); 378 } 379 380 #endif /* _OBJTOOL_ELF_H */ 381