blob: 807f8c670097473b569ba015cb64e79c6f3da45d [file] [log] [blame]
Thomas Gleixner1ccea772019-05-19 15:51:43 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Josh Poimboeuf442f04c2016-02-28 22:22:41 -06002/*
3 * Copyright (C) 2015 Josh Poimboeuf <jpoimboe@redhat.com>
Josh Poimboeuf442f04c2016-02-28 22:22:41 -06004 */
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>
Josh Poimboeuf042ba732016-03-09 00:07:00 -060012#include <linux/hashtable.h>
Peter Zijlstra2a362ec2020-03-12 09:34:42 +010013#include <linux/rbtree.h>
Peter Zijlstraae358192020-03-12 09:32:10 +010014#include <linux/jhash.h>
Josh Poimboeuf442f04c2016-02-28 22:22:41 -060015
Jan Beulich2e51f262016-05-16 15:31:07 -050016#ifdef LIBELF_USE_DEPRECATED
17# define elf_getshdrnum elf_getshnum
18# define elf_getshdrstrndx elf_getshstrndx
19#endif
20
Josh Poimboeuf627fce12017-07-11 10:33:42 -050021/*
22 * Fallback for systems without this "read, mmaping if possible" cmd.
23 */
24#ifndef ELF_C_READ_MMAP
25#define ELF_C_READ_MMAP ELF_C_READ
26#endif
27
Josh Poimboeuf442f04c2016-02-28 22:22:41 -060028struct section {
29 struct list_head list;
Peter Zijlstra530389962020-03-10 18:43:35 +010030 struct hlist_node hash;
Peter Zijlstraae358192020-03-12 09:32:10 +010031 struct hlist_node name_hash;
Josh Poimboeuf442f04c2016-02-28 22:22:41 -060032 GElf_Shdr sh;
Peter Zijlstra2a362ec2020-03-12 09:34:42 +010033 struct rb_root symbol_tree;
Josh Poimboeufa196e172016-03-09 00:06:57 -060034 struct list_head symbol_list;
Matt Helsleyf1974222020-05-29 14:01:13 -070035 struct list_head reloc_list;
36 struct section *base, *reloc;
Josh Poimboeuf442f04c2016-02-28 22:22:41 -060037 struct symbol *sym;
Josh Poimboeufbaa414692017-06-28 10:11:07 -050038 Elf_Data *data;
Josh Poimboeuf442f04c2016-02-28 22:22:41 -060039 char *name;
40 int idx;
Josh Poimboeuf442f04c2016-02-28 22:22:41 -060041 unsigned int len;
Peter Zijlstrac4a33932020-03-10 18:57:41 +010042 bool changed, text, rodata, noinstr;
Josh Poimboeuf442f04c2016-02-28 22:22:41 -060043};
44
45struct symbol {
46 struct list_head list;
Peter Zijlstra2a362ec2020-03-12 09:34:42 +010047 struct rb_node node;
Josh Poimboeuf042ba732016-03-09 00:07:00 -060048 struct hlist_node hash;
Peter Zijlstracdb3d052020-03-12 10:17:38 +010049 struct hlist_node name_hash;
Josh Poimboeuf442f04c2016-02-28 22:22:41 -060050 GElf_Sym sym;
51 struct section *sec;
52 char *name;
Josh Poimboeuf042ba732016-03-09 00:07:00 -060053 unsigned int idx;
Josh Poimboeuf442f04c2016-02-28 22:22:41 -060054 unsigned char bind, type;
55 unsigned long offset;
56 unsigned int len;
Peter Zijlstra09f30d82019-02-28 14:17:50 +010057 struct symbol *pfunc, *cfunc, *alias;
Peter Zijlstraea242132019-02-25 12:50:09 +010058 bool uaccess_safe;
Josh Poimboeuf1e7e4782020-08-18 15:57:45 +020059 bool static_call_tramp;
Josh Poimboeuf442f04c2016-02-28 22:22:41 -060060};
61
Matt Helsleyf1974222020-05-29 14:01:13 -070062struct reloc {
Josh Poimboeuf442f04c2016-02-28 22:22:41 -060063 struct list_head list;
Josh Poimboeuf042ba732016-03-09 00:07:00 -060064 struct hlist_node hash;
Matt Helsleyfb414782020-05-29 14:01:14 -070065 union {
66 GElf_Rela rela;
67 GElf_Rel rel;
68 };
Josh Poimboeufe7c2bc32019-07-17 20:36:53 -050069 struct section *sec;
Josh Poimboeuf442f04c2016-02-28 22:22:41 -060070 struct symbol *sym;
Josh Poimboeuf042ba732016-03-09 00:07:00 -060071 unsigned long offset;
Peter Zijlstrafdabdd02020-06-12 15:43:00 +020072 unsigned int type;
Josh Poimboeuf442f04c2016-02-28 22:22:41 -060073 int addend;
Peter Zijlstrafdabdd02020-06-12 15:43:00 +020074 int idx;
Jann Hornbd98c812019-07-17 20:36:54 -050075 bool jump_table_start;
Josh Poimboeuf442f04c2016-02-28 22:22:41 -060076};
77
Peter Zijlstra34f7c962020-03-12 14:29:38 +010078#define ELF_HASH_BITS 20
79
Josh Poimboeuf442f04c2016-02-28 22:22:41 -060080struct elf {
81 Elf *elf;
82 GElf_Ehdr ehdr;
83 int fd;
Peter Zijlstra2b10be22020-04-17 23:15:00 +020084 bool changed;
Josh Poimboeuf442f04c2016-02-28 22:22:41 -060085 char *name;
86 struct list_head sections;
Peter Zijlstra34f7c962020-03-12 14:29:38 +010087 DECLARE_HASHTABLE(symbol_hash, ELF_HASH_BITS);
88 DECLARE_HASHTABLE(symbol_name_hash, ELF_HASH_BITS);
89 DECLARE_HASHTABLE(section_hash, ELF_HASH_BITS);
90 DECLARE_HASHTABLE(section_name_hash, ELF_HASH_BITS);
Matt Helsleyf1974222020-05-29 14:01:13 -070091 DECLARE_HASHTABLE(reloc_hash, ELF_HASH_BITS);
Josh Poimboeuf442f04c2016-02-28 22:22:41 -060092};
93
Peter Zijlstra74b873e2020-03-12 11:30:50 +010094#define OFFSET_STRIDE_BITS 4
95#define OFFSET_STRIDE (1UL << OFFSET_STRIDE_BITS)
96#define OFFSET_STRIDE_MASK (~(OFFSET_STRIDE - 1))
97
Josh Poimboeuf53fb6e92020-04-25 14:19:01 -050098#define for_offset_range(_offset, _start, _end) \
99 for (_offset = ((_start) & OFFSET_STRIDE_MASK); \
100 _offset >= ((_start) & OFFSET_STRIDE_MASK) && \
101 _offset <= ((_end) & OFFSET_STRIDE_MASK); \
Peter Zijlstra74b873e2020-03-12 11:30:50 +0100102 _offset += OFFSET_STRIDE)
103
Peter Zijlstra8b5fa6b2020-03-12 11:23:36 +0100104static inline u32 sec_offset_hash(struct section *sec, unsigned long offset)
105{
Peter Zijlstra74b873e2020-03-12 11:30:50 +0100106 u32 ol, oh, idx = sec->idx;
107
108 offset &= OFFSET_STRIDE_MASK;
109
110 ol = offset;
Peter Zijlstra963d5662020-04-20 10:33:32 +0200111 oh = (offset >> 16) >> 16;
Peter Zijlstra8b5fa6b2020-03-12 11:23:36 +0100112
113 __jhash_mix(ol, oh, idx);
114
115 return ol;
116}
117
Matt Helsleyf1974222020-05-29 14:01:13 -0700118static inline u32 reloc_hash(struct reloc *reloc)
Peter Zijlstra8b5fa6b2020-03-12 11:23:36 +0100119{
Matt Helsleyf1974222020-05-29 14:01:13 -0700120 return sec_offset_hash(reloc->sec, reloc->offset);
Peter Zijlstra8b5fa6b2020-03-12 11:23:36 +0100121}
Josh Poimboeuf442f04c2016-02-28 22:22:41 -0600122
Ingo Molnarbc359ff2020-04-22 12:32:04 +0200123struct elf *elf_open_read(const char *name, int flags);
Josh Poimboeuf1e7e4782020-08-18 15:57:45 +0200124struct section *elf_create_section(struct elf *elf, const char *name, unsigned int sh_flags, size_t entsize, int nr);
Matt Helsleyfb414782020-05-29 14:01:14 -0700125struct section *elf_create_reloc_section(struct elf *elf, struct section *base, int reltype);
Matt Helsleyf1974222020-05-29 14:01:13 -0700126void elf_add_reloc(struct elf *elf, struct reloc *reloc);
Peter Zijlstrafdabdd02020-06-12 15:43:00 +0200127int elf_write_insn(struct elf *elf, struct section *sec,
128 unsigned long offset, unsigned int len,
129 const char *insn);
Peter Zijlstrad832c002020-06-18 17:55:29 +0200130int elf_write_reloc(struct elf *elf, struct reloc *reloc);
Peter Zijlstra2b10be22020-04-17 23:15:00 +0200131int elf_write(struct elf *elf);
Ingo Molnar894e48c2020-04-22 12:32:03 +0200132void elf_close(struct elf *elf);
133
134struct section *find_section_by_name(const struct elf *elf, const char *name);
Josh Poimboeuf7acfe532020-02-17 21:41:54 -0600135struct symbol *find_func_by_offset(struct section *sec, unsigned long offset);
Josh Poimboeuf442f04c2016-02-28 22:22:41 -0600136struct symbol *find_symbol_by_offset(struct section *sec, unsigned long offset);
Ingo Molnar894e48c2020-04-22 12:32:03 +0200137struct symbol *find_symbol_by_name(const struct elf *elf, const char *name);
Miroslav Benesb490f452020-04-24 16:30:42 +0200138struct symbol *find_symbol_containing(const struct section *sec, unsigned long offset);
Matt Helsleyf1974222020-05-29 14:01:13 -0700139struct reloc *find_reloc_by_dest(const struct elf *elf, struct section *sec, unsigned long offset);
140struct reloc *find_reloc_by_dest_range(const struct elf *elf, struct section *sec,
Peter Zijlstra8b5fa6b2020-03-12 11:23:36 +0100141 unsigned long offset, unsigned int len);
Peter Zijlstra53d20722020-03-16 10:36:53 +0100142struct symbol *find_func_containing(struct section *sec, unsigned long offset);
Peter Zijlstrad832c002020-06-18 17:55:29 +0200143int elf_rebuild_reloc_section(struct elf *elf, struct section *sec);
Josh Poimboeuf442f04c2016-02-28 22:22:41 -0600144
Josh Poimboeufbaa414692017-06-28 10:11:07 -0500145#define for_each_sec(file, sec) \
146 list_for_each_entry(sec, &file->elf->sections, list)
Josh Poimboeuf442f04c2016-02-28 22:22:41 -0600147
148#endif /* _OBJTOOL_ELF_H */