2016-07-12 19:59:43 +00:00
|
|
|
/*
|
|
|
|
* kpatch-elf.h
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU General Public License
|
|
|
|
* as published by the Free Software Foundation; either version 2
|
|
|
|
* of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with this program; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA,
|
|
|
|
* 02110-1301, USA.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _KPATCH_ELF_H_
|
|
|
|
#define _KPATCH_ELF_H_
|
|
|
|
|
2018-03-21 03:35:25 +00:00
|
|
|
#include <stdbool.h>
|
2016-07-12 19:59:43 +00:00
|
|
|
#include <gelf.h>
|
|
|
|
#include "list.h"
|
|
|
|
#include "log.h"
|
|
|
|
|
2017-01-23 20:42:42 +00:00
|
|
|
#define KLP_SYM_PREFIX ".klp.sym."
|
|
|
|
#define KLP_RELASEC_PREFIX ".klp.rela."
|
|
|
|
#define KLP_ARCH_PREFIX ".klp.arch."
|
|
|
|
#define SHF_RELA_LIVEPATCH 0x00100000
|
|
|
|
#define SHN_LIVEPATCH 0xff20
|
|
|
|
|
2016-07-12 19:59:43 +00:00
|
|
|
/*******************
|
|
|
|
* Data structures
|
|
|
|
* ****************/
|
|
|
|
struct section;
|
|
|
|
struct symbol;
|
|
|
|
struct rela;
|
|
|
|
|
|
|
|
enum status {
|
|
|
|
NEW,
|
|
|
|
CHANGED,
|
|
|
|
SAME
|
|
|
|
};
|
|
|
|
|
|
|
|
struct section {
|
|
|
|
struct list_head list;
|
|
|
|
struct section *twin;
|
|
|
|
GElf_Shdr sh;
|
|
|
|
Elf_Data *data;
|
|
|
|
char *name;
|
2018-04-13 07:11:48 +00:00
|
|
|
unsigned int index;
|
2016-07-12 19:59:43 +00:00
|
|
|
enum status status;
|
|
|
|
int include;
|
|
|
|
int ignore;
|
|
|
|
int grouped;
|
|
|
|
union {
|
|
|
|
struct { /* if (is_rela_section()) */
|
|
|
|
struct section *base;
|
|
|
|
struct list_head relas;
|
|
|
|
};
|
|
|
|
struct { /* else */
|
|
|
|
struct section *rela;
|
|
|
|
struct symbol *secsym, *sym;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2021-08-22 17:16:52 +00:00
|
|
|
enum symbol_strip {
|
|
|
|
SYMBOL_DEFAULT,
|
|
|
|
SYMBOL_USED,
|
|
|
|
SYMBOL_STRIP,
|
|
|
|
};
|
|
|
|
|
2016-07-12 19:59:43 +00:00
|
|
|
struct symbol {
|
|
|
|
struct list_head list;
|
|
|
|
struct symbol *twin;
|
2018-06-12 14:05:30 +00:00
|
|
|
struct symbol *parent;
|
create-diff-object: support x86 NOP-padded functions
Kernel v6.2+ commit bea75b33895f ("x86/Kconfig: Introduce function
padding") added 16 bytes of NOP padding in front of each function.
For objects built with --function-sections, this means that function
symbols no longer sit at the beginning of their respective ELF sections,
but 16 bytes offset.
In the same release, kernel v6.2+ commit 9f2899fe36a6 ("objtool: Add
option to generate prefix symbols") adds ELF function symbols with
prefix "__pfx_" to indicate the start of a function, inclusive of
NOP-padding.
For example:
$ objdump -Dr -j.text.cmdline_proc_show fs/proc/cmdline.o
...
Disassembly of section .text.cmdline_proc_show:
0000000000000000 <__pfx_cmdline_proc_show>:
0: 90 nop
1: 90 nop
2: 90 nop
3: 90 nop
4: 90 nop
5: 90 nop
6: 90 nop
7: 90 nop
8: 90 nop
9: 90 nop
a: 90 nop
b: 90 nop
c: 90 nop
d: 90 nop
e: 90 nop
f: 90 nop
0000000000000010 <cmdline_proc_show>:
10: e8 00 00 00 00 callq 15 <cmdline_proc_show+0x5>
11: R_X86_64_PLT32 __fentry__-0x4
15: 55 push %rbp
16: 48 8b 35 00 00 00 00 mov 0x0(%rip),%rsi # 1d <cmdline_proc_show+0xd>
19: R_X86_64_PC32 saved_command_line-0x4
1d: 48 89 fd mov %rdi,%rbp
20: e8 00 00 00 00 callq 25 <cmdline_proc_show+0x15>
21: R_X86_64_PLT32 seq_puts-0x4
25: 48 89 ef mov %rbp,%rdi
28: be 0a 00 00 00 mov $0xa,%esi
2d: e8 00 00 00 00 callq 32 <cmdline_proc_show+0x22>
2e: R_X86_64_PLT32 seq_putc-0x4
32: 31 c0 xor %eax,%eax
34: 5d pop %rbp
35: e9 00 00 00 00 jmpq 3a <cmdline_proc_show+0x2a>
36: R_X86_64_PLT32 __x86_return_thunk-0x4
Kpatch-build needs to gracefully handle NOP-padding when it is present.
At the same time, it should include "__pfx_<function>" symbols when
their respective functions change, but not treat prefix such functions
as first-class functions.
This also adds support for CONFIG_CFI_CLANG, which also creates prefixed
symbols with the name "__cfi_<function>".
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
2023-01-16 14:33:55 +00:00
|
|
|
struct symbol *pfx;
|
2019-09-16 10:57:05 +00:00
|
|
|
struct list_head children;
|
|
|
|
struct list_head subfunction_node;
|
2016-07-12 19:59:43 +00:00
|
|
|
struct section *sec;
|
|
|
|
GElf_Sym sym;
|
|
|
|
char *name;
|
2021-08-02 09:32:23 +00:00
|
|
|
struct object_symbol *lookup_table_file_sym;
|
2018-04-13 07:11:48 +00:00
|
|
|
unsigned int index;
|
2016-07-12 19:59:43 +00:00
|
|
|
unsigned char bind, type;
|
|
|
|
enum status status;
|
|
|
|
union {
|
|
|
|
int include; /* used in the patched elf */
|
2021-08-22 17:16:52 +00:00
|
|
|
enum symbol_strip strip; /* used in the output elf */
|
2016-07-12 19:59:43 +00:00
|
|
|
};
|
2017-05-27 05:32:31 +00:00
|
|
|
int has_func_profiling;
|
create-diff-object: support x86 NOP-padded functions
Kernel v6.2+ commit bea75b33895f ("x86/Kconfig: Introduce function
padding") added 16 bytes of NOP padding in front of each function.
For objects built with --function-sections, this means that function
symbols no longer sit at the beginning of their respective ELF sections,
but 16 bytes offset.
In the same release, kernel v6.2+ commit 9f2899fe36a6 ("objtool: Add
option to generate prefix symbols") adds ELF function symbols with
prefix "__pfx_" to indicate the start of a function, inclusive of
NOP-padding.
For example:
$ objdump -Dr -j.text.cmdline_proc_show fs/proc/cmdline.o
...
Disassembly of section .text.cmdline_proc_show:
0000000000000000 <__pfx_cmdline_proc_show>:
0: 90 nop
1: 90 nop
2: 90 nop
3: 90 nop
4: 90 nop
5: 90 nop
6: 90 nop
7: 90 nop
8: 90 nop
9: 90 nop
a: 90 nop
b: 90 nop
c: 90 nop
d: 90 nop
e: 90 nop
f: 90 nop
0000000000000010 <cmdline_proc_show>:
10: e8 00 00 00 00 callq 15 <cmdline_proc_show+0x5>
11: R_X86_64_PLT32 __fentry__-0x4
15: 55 push %rbp
16: 48 8b 35 00 00 00 00 mov 0x0(%rip),%rsi # 1d <cmdline_proc_show+0xd>
19: R_X86_64_PC32 saved_command_line-0x4
1d: 48 89 fd mov %rdi,%rbp
20: e8 00 00 00 00 callq 25 <cmdline_proc_show+0x15>
21: R_X86_64_PLT32 seq_puts-0x4
25: 48 89 ef mov %rbp,%rdi
28: be 0a 00 00 00 mov $0xa,%esi
2d: e8 00 00 00 00 callq 32 <cmdline_proc_show+0x22>
2e: R_X86_64_PLT32 seq_putc-0x4
32: 31 c0 xor %eax,%eax
34: 5d pop %rbp
35: e9 00 00 00 00 jmpq 3a <cmdline_proc_show+0x2a>
36: R_X86_64_PLT32 __x86_return_thunk-0x4
Kpatch-build needs to gracefully handle NOP-padding when it is present.
At the same time, it should include "__pfx_<function>" symbols when
their respective functions change, but not treat prefix such functions
as first-class functions.
This also adds support for CONFIG_CFI_CLANG, which also creates prefixed
symbols with the name "__cfi_<function>".
Signed-off-by: Joe Lawrence <joe.lawrence@redhat.com>
Signed-off-by: Josh Poimboeuf <jpoimboe@redhat.com>
2023-01-16 14:33:55 +00:00
|
|
|
bool is_pfx;
|
2016-07-12 19:59:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct rela {
|
|
|
|
struct list_head list;
|
|
|
|
GElf_Rela rela;
|
|
|
|
struct symbol *sym;
|
|
|
|
unsigned int type;
|
2018-04-13 07:11:48 +00:00
|
|
|
unsigned int offset;
|
2020-01-17 15:32:11 +00:00
|
|
|
long addend;
|
2016-07-12 19:59:43 +00:00
|
|
|
char *string;
|
2022-12-01 21:21:36 +00:00
|
|
|
bool need_klp_reloc;
|
2016-07-12 19:59:43 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct string {
|
|
|
|
struct list_head list;
|
|
|
|
char *name;
|
|
|
|
};
|
|
|
|
|
2022-01-21 17:02:20 +00:00
|
|
|
enum architecture {
|
|
|
|
PPC64 = 0x1 << 0,
|
|
|
|
X86_64 = 0x1 << 1,
|
2022-04-02 00:39:18 +00:00
|
|
|
S390 = 0x1 << 2,
|
2022-01-21 17:02:20 +00:00
|
|
|
};
|
|
|
|
|
2016-07-12 19:59:43 +00:00
|
|
|
struct kpatch_elf {
|
|
|
|
Elf *elf;
|
2022-01-21 17:02:20 +00:00
|
|
|
enum architecture arch;
|
2016-07-12 19:59:43 +00:00
|
|
|
struct list_head sections;
|
|
|
|
struct list_head symbols;
|
|
|
|
struct list_head strings;
|
2021-01-12 16:15:45 +00:00
|
|
|
Elf_Data *symtab_shndx;
|
2016-07-12 19:59:43 +00:00
|
|
|
int fd;
|
|
|
|
};
|
|
|
|
|
|
|
|
/*******************
|
|
|
|
* Helper functions
|
|
|
|
******************/
|
|
|
|
char *status_str(enum status status);
|
2022-05-11 21:11:57 +00:00
|
|
|
bool is_rela_section(struct section *sec);
|
|
|
|
bool is_text_section(struct section *sec);
|
|
|
|
bool is_debug_section(struct section *sec);
|
2016-07-12 19:59:43 +00:00
|
|
|
|
|
|
|
struct section *find_section_by_index(struct list_head *list, unsigned int index);
|
|
|
|
struct section *find_section_by_name(struct list_head *list, const char *name);
|
|
|
|
struct symbol *find_symbol_by_index(struct list_head *list, size_t index);
|
|
|
|
struct symbol *find_symbol_by_name(struct list_head *list, const char *name);
|
2017-01-23 20:43:27 +00:00
|
|
|
struct rela *find_rela_by_offset(struct section *relasec, unsigned int offset);
|
2016-07-12 19:59:43 +00:00
|
|
|
|
|
|
|
#define ALLOC_LINK(_new, _list) \
|
|
|
|
{ \
|
|
|
|
(_new) = malloc(sizeof(*(_new))); \
|
|
|
|
if (!(_new)) \
|
|
|
|
ERROR("malloc"); \
|
|
|
|
memset((_new), 0, sizeof(*(_new))); \
|
|
|
|
INIT_LIST_HEAD(&(_new)->list); \
|
2018-05-29 14:50:46 +00:00
|
|
|
if (_list) \
|
|
|
|
list_add_tail(&(_new)->list, (_list)); \
|
2016-07-12 19:59:43 +00:00
|
|
|
}
|
|
|
|
|
2022-01-21 17:02:20 +00:00
|
|
|
unsigned int absolute_rela_type(struct kpatch_elf *kelf);
|
2016-07-12 19:59:43 +00:00
|
|
|
int offset_of_string(struct list_head *list, char *name);
|
2022-05-11 23:25:13 +00:00
|
|
|
long rela_target_offset(struct kpatch_elf *kelf, struct section *relasec,
|
|
|
|
struct rela *rela);
|
|
|
|
unsigned int insn_length(struct kpatch_elf *kelf, void *addr);
|
2016-07-12 19:59:43 +00:00
|
|
|
|
2017-07-27 07:26:00 +00:00
|
|
|
#ifndef R_PPC64_ENTRY
|
|
|
|
#define R_PPC64_ENTRY 118
|
|
|
|
#endif
|
|
|
|
|
2016-07-12 19:59:43 +00:00
|
|
|
/*************
|
|
|
|
* Functions
|
|
|
|
* **********/
|
|
|
|
struct kpatch_elf *kpatch_elf_open(const char *name);
|
|
|
|
void kpatch_dump_kelf(struct kpatch_elf *kelf);
|
|
|
|
|
2022-05-11 21:11:57 +00:00
|
|
|
bool is_null_sym(struct symbol *sym);
|
|
|
|
bool is_file_sym(struct symbol *sym);
|
|
|
|
bool is_local_func_sym(struct symbol *sym);
|
|
|
|
bool is_local_sym(struct symbol *sym);
|
2023-02-21 14:28:21 +00:00
|
|
|
bool is_ubsan_sec(const char *name);
|
2016-07-12 19:59:43 +00:00
|
|
|
|
|
|
|
void print_strtab(char *buf, size_t size);
|
|
|
|
void kpatch_create_shstrtab(struct kpatch_elf *kelf);
|
|
|
|
void kpatch_create_strtab(struct kpatch_elf *kelf);
|
|
|
|
void kpatch_create_symtab(struct kpatch_elf *kelf);
|
|
|
|
struct section *create_section_pair(struct kpatch_elf *kelf, char *name,
|
|
|
|
int entsize, int nr);
|
2017-01-23 20:43:05 +00:00
|
|
|
void kpatch_remove_and_free_section(struct kpatch_elf *kelf, char *secname);
|
2017-01-23 20:42:47 +00:00
|
|
|
void kpatch_reindex_elements(struct kpatch_elf *kelf);
|
|
|
|
void kpatch_rebuild_rela_section_data(struct section *sec);
|
2020-09-24 21:46:45 +00:00
|
|
|
void kpatch_write_output_elf(struct kpatch_elf *kelf, Elf *elf, char *outfile,
|
|
|
|
mode_t mode);
|
2016-07-12 19:59:43 +00:00
|
|
|
void kpatch_elf_teardown(struct kpatch_elf *kelf);
|
|
|
|
void kpatch_elf_free(struct kpatch_elf *kelf);
|
|
|
|
#endif /* _KPATCH_ELF_H_ */
|