mirror of
https://github.com/checkpoint-restore/criu
synced 2025-08-31 14:25:49 +00:00
pie: piegen -- Slightly rework the building procedure
- Move relocs application into a separate file which get compiled as a regular C file in criu (pie/pie-relocs.[ch]) - Move types used by piegen into pie/piegen/uapi/types.h Signed-off-by: Cyrill Gorcunov <gorcunov@openvz.org> Signed-off-by: Pavel Emelyanov <xemul@parallels.com>
This commit is contained in:
committed by
Pavel Emelyanov
parent
ac187856c4
commit
f03a4672ce
@@ -72,6 +72,7 @@ obj-y += cr-service.o
|
|||||||
obj-y += sd-daemon.o
|
obj-y += sd-daemon.o
|
||||||
obj-y += plugin.o
|
obj-y += plugin.o
|
||||||
obj-y += cr-errno.o
|
obj-y += cr-errno.o
|
||||||
|
obj-y += pie/pie-relocs.o
|
||||||
|
|
||||||
ifneq ($(MAKECMDGOALS),clean)
|
ifneq ($(MAKECMDGOALS),clean)
|
||||||
incdeps := y
|
incdeps := y
|
||||||
|
@@ -91,6 +91,8 @@
|
|||||||
|
|
||||||
#include "cr-errno.h"
|
#include "cr-errno.h"
|
||||||
|
|
||||||
|
#include "pie/pie-relocs.h"
|
||||||
|
|
||||||
#ifndef arch_export_restore_thread
|
#ifndef arch_export_restore_thread
|
||||||
#define arch_export_restore_thread __export_restore_thread
|
#define arch_export_restore_thread __export_restore_thread
|
||||||
#endif
|
#endif
|
||||||
@@ -2392,10 +2394,9 @@ static int remap_restorer_blob(void *addr)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_X86_64) || defined(CONFIG_X86_32)
|
elf_relocs_apply(addr, addr, sizeof(restorer_blob),
|
||||||
elf_apply_relocs(addr, addr, sizeof(restorer_blob),
|
|
||||||
elf_relocs, ARRAY_SIZE(elf_relocs));
|
elf_relocs, ARRAY_SIZE(elf_relocs));
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -37,6 +37,7 @@
|
|||||||
#include "asm/parasite-syscall.h"
|
#include "asm/parasite-syscall.h"
|
||||||
#include "asm/dump.h"
|
#include "asm/dump.h"
|
||||||
#include "asm/restorer.h"
|
#include "asm/restorer.h"
|
||||||
|
#include "pie/pie-relocs.h"
|
||||||
|
|
||||||
#if defined(CONFIG_X86_32) || defined(CONFIG_X86_64)
|
#if defined(CONFIG_X86_32) || defined(CONFIG_X86_64)
|
||||||
# define parasite_size (round_up(sizeof(parasite_blob) + nr_gotpcrel * sizeof(long), PAGE_SIZE))
|
# define parasite_size (round_up(sizeof(parasite_blob) + nr_gotpcrel * sizeof(long), PAGE_SIZE))
|
||||||
@@ -1223,10 +1224,8 @@ struct parasite_ctl *parasite_infect_seized(pid_t pid, struct pstree_item *item,
|
|||||||
pr_info("Putting parasite blob into %p->%p\n", ctl->local_map, ctl->remote_map);
|
pr_info("Putting parasite blob into %p->%p\n", ctl->local_map, ctl->remote_map);
|
||||||
memcpy(ctl->local_map, parasite_blob, sizeof(parasite_blob));
|
memcpy(ctl->local_map, parasite_blob, sizeof(parasite_blob));
|
||||||
|
|
||||||
#if defined(CONFIG_X86_64) || defined(CONFIG_X86_32)
|
elf_relocs_apply(ctl->local_map, ctl->remote_map, sizeof(parasite_blob),
|
||||||
elf_apply_relocs(ctl->local_map, ctl->remote_map, sizeof(parasite_blob),
|
|
||||||
elf_relocs, ARRAY_SIZE(elf_relocs));
|
elf_relocs, ARRAY_SIZE(elf_relocs));
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Setup the rest of a control block */
|
/* Setup the rest of a control block */
|
||||||
ctl->parasite_ip = (unsigned long)parasite_sym(ctl->remote_map, __export_parasite_head_start);
|
ctl->parasite_ip = (unsigned long)parasite_sym(ctl->remote_map, __export_parasite_head_start);
|
||||||
|
@@ -34,7 +34,7 @@ restorer-libs-e += $(SYSCALL-LIB)
|
|||||||
# applications, which is not the target of the
|
# applications, which is not the target of the
|
||||||
# project.
|
# project.
|
||||||
#
|
#
|
||||||
CFLAGS := $(filter-out -pg,$(CFLAGS))
|
CFLAGS := $(filter-out -pg,$(CFLAGS)) -iquote pie/piegen
|
||||||
|
|
||||||
ifneq ($(filter-out i386 ia32, $(ARCH)),)
|
ifneq ($(filter-out i386 ia32, $(ARCH)),)
|
||||||
cflags-y += -DCR_NOGLIBC -fpie -Wa,--noexecstack -fno-stack-protector
|
cflags-y += -DCR_NOGLIBC -fpie -Wa,--noexecstack -fno-stack-protector
|
||||||
|
47
pie/pie-relocs.c
Normal file
47
pie/pie-relocs.c
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <elf.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <sys/mman.h>
|
||||||
|
|
||||||
|
#include "asm-generic/int.h"
|
||||||
|
|
||||||
|
#include "compiler.h"
|
||||||
|
#include "piegen/uapi/types.h"
|
||||||
|
#include "bug.h"
|
||||||
|
|
||||||
|
__maybe_unused void elf_relocs_apply(void *mem, void *vbase, size_t size, elf_reloc_t *elf_relocs, size_t nr_relocs)
|
||||||
|
{
|
||||||
|
size_t i, j;
|
||||||
|
|
||||||
|
for (i = 0, j = 0; i < nr_relocs; i++) {
|
||||||
|
if (elf_relocs[i].type & PIEGEN_TYPE_LONG) {
|
||||||
|
long *where = mem + elf_relocs[i].offset;
|
||||||
|
long *p = mem + size;
|
||||||
|
|
||||||
|
if (elf_relocs[i].type & PIEGEN_TYPE_GOTPCREL) {
|
||||||
|
int *value = (int *)where;
|
||||||
|
int rel;
|
||||||
|
|
||||||
|
p[j] = (long)vbase + elf_relocs[i].value;
|
||||||
|
rel = (unsigned)((void *)&p[j] - (void *)mem) - elf_relocs[i].offset + elf_relocs[i].addend;
|
||||||
|
|
||||||
|
*value = rel;
|
||||||
|
j++;
|
||||||
|
} else
|
||||||
|
*where = elf_relocs[i].value + elf_relocs[i].addend + (unsigned long)vbase;
|
||||||
|
} else if (elf_relocs[i].type & PIEGEN_TYPE_INT) {
|
||||||
|
int *where = (mem + elf_relocs[i].offset);
|
||||||
|
*where = elf_relocs[i].value + elf_relocs[i].addend + (unsigned long)vbase;
|
||||||
|
} else
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
}
|
15
pie/pie-relocs.h
Normal file
15
pie/pie-relocs.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef __PIE_RELOCS_H__
|
||||||
|
#define __PIE_RELOCS_H__
|
||||||
|
|
||||||
|
#include "piegen/uapi/types.h"
|
||||||
|
|
||||||
|
#include "compiler.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
|
#if defined(CONFIG_X86_64) || defined(CONFIG_X86_32)
|
||||||
|
extern __maybe_unused void elf_relocs_apply(void *mem, void *vbase, size_t size, elf_reloc_t *elf_relocs, size_t nr_relocs);
|
||||||
|
#else
|
||||||
|
static always_inline void elf_relocs_apply(void *mem, void *vbase, size_t size, elf_reloc_t *elf_relocs, size_t nr_relocs) { }
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* __PIE_RELOCS_H__ */
|
@@ -126,6 +126,8 @@ int handle_elf(const piegen_opt_t *opts, void *mem, size_t size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
pr_out("/* Autogenerated from %s */\n", opts->input_filename);
|
pr_out("/* Autogenerated from %s */\n", opts->input_filename);
|
||||||
|
pr_out("#include \"piegen/uapi/types.h\"\n");
|
||||||
|
|
||||||
for (i = 0; i < symtab_hdr->sh_size / symtab_hdr->sh_entsize; i++) {
|
for (i = 0; i < symtab_hdr->sh_size / symtab_hdr->sh_entsize; i++) {
|
||||||
Sym_t *sym = &symbols[i];
|
Sym_t *sym = &symbols[i];
|
||||||
const char *name;
|
const char *name;
|
||||||
@@ -155,13 +157,7 @@ int handle_elf(const piegen_opt_t *opts, void *mem, size_t size)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pr_out("typedef struct {\n"
|
pr_out("static __maybe_unused elf_reloc_t %s[] = {\n", opts->var_name);
|
||||||
" unsigned int offset;\n"
|
|
||||||
" unsigned int type;\n"
|
|
||||||
" long addend;\n"
|
|
||||||
" long value;\n"
|
|
||||||
"} %s;\nstatic __maybe_unused %s %s[] = {\n",
|
|
||||||
opts->type_name, opts->type_name, opts->var_name);
|
|
||||||
|
|
||||||
pr_debug("Relocations\n------------\n");
|
pr_debug("Relocations\n------------\n");
|
||||||
for (i = 0; i < hdr->e_shnum; i++) {
|
for (i = 0; i < hdr->e_shnum; i++) {
|
||||||
@@ -232,16 +228,17 @@ int handle_elf(const piegen_opt_t *opts, void *mem, size_t size)
|
|||||||
value64 = (s64)sh_src->sh_offset + (s64)sym->st_value;
|
value64 = (s64)sh_src->sh_offset + (s64)sym->st_value;
|
||||||
|
|
||||||
switch (ELF_R_TYPE(r->rel.r_info)) {
|
switch (ELF_R_TYPE(r->rel.r_info)) {
|
||||||
|
|
||||||
#ifdef ELF_X86_64
|
#ifdef ELF_X86_64
|
||||||
case R_X86_64_32: /* Symbol + Addend (4 bytes) */
|
case R_X86_64_32: /* Symbol + Addend (4 bytes) */
|
||||||
pr_debug("\t\t\t\tR_X86_64_32 at 0x%-4lx val 0x%x\n", place, value32);
|
pr_debug("\t\t\t\tR_X86_64_32 at 0x%-4lx val 0x%x\n", place, value32);
|
||||||
pr_out(" { .offset = 0x%-8x, .type = 0, "
|
pr_out(" { .offset = 0x%-8x, .type = PIEGEN_TYPE_INT, "
|
||||||
".addend = %-8d, .value = 0x%-16x, }, /* R_X86_64_32 */\n",
|
".addend = %-8d, .value = 0x%-16x, }, /* R_X86_64_32 */\n",
|
||||||
(unsigned int)place, addend32, value32);
|
(unsigned int)place, addend32, value32);
|
||||||
break;
|
break;
|
||||||
case R_X86_64_64: /* Symbol + Addend (8 bytes) */
|
case R_X86_64_64: /* Symbol + Addend (8 bytes) */
|
||||||
pr_debug("\t\t\t\tR_X86_64_64 at 0x%-4lx val 0x%lx\n", place, value64);
|
pr_debug("\t\t\t\tR_X86_64_64 at 0x%-4lx val 0x%lx\n", place, value64);
|
||||||
pr_out(" { .offset = 0x%-8x, .type = 1, "
|
pr_out(" { .offset = 0x%-8x, .type = PIEGEN_TYPE_LONG, "
|
||||||
".addend = %-8ld, .value = 0x%-16lx, }, /* R_X86_64_64 */\n",
|
".addend = %-8ld, .value = 0x%-16lx, }, /* R_X86_64_64 */\n",
|
||||||
(unsigned int)place, (long)addend64, (long)value64);
|
(unsigned int)place, (long)addend64, (long)value64);
|
||||||
break;
|
break;
|
||||||
@@ -261,16 +258,17 @@ int handle_elf(const piegen_opt_t *opts, void *mem, size_t size)
|
|||||||
break;
|
break;
|
||||||
case R_X86_64_GOTPCREL: /* SymbolOffsetInGot + GOT + Addend - Place (4 bytes) */
|
case R_X86_64_GOTPCREL: /* SymbolOffsetInGot + GOT + Addend - Place (4 bytes) */
|
||||||
pr_debug("\t\t\t\tR_X86_64_GOTPCREL at 0x%-4lx val 0x%x\n", place, value32);
|
pr_debug("\t\t\t\tR_X86_64_GOTPCREL at 0x%-4lx val 0x%x\n", place, value32);
|
||||||
pr_out(" { .offset = 0x%-8x, .type = 3, "
|
pr_out(" { .offset = 0x%-8x, .type = PIEGEN_TYPE_LONG | PIEGEN_TYPE_GOTPCREL, "
|
||||||
".addend = %-8d, .value = 0x%-16x, }, /* R_X86_64_GOTPCREL */\n",
|
".addend = %-8d, .value = 0x%-16x, }, /* R_X86_64_GOTPCREL */\n",
|
||||||
(unsigned int)place, addend32, value32);
|
(unsigned int)place, addend32, value32);
|
||||||
nr_gotpcrel++;
|
nr_gotpcrel++;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef ELF_X86_32
|
#ifdef ELF_X86_32
|
||||||
case R_386_32: /* Symbol + Addend */
|
case R_386_32: /* Symbol + Addend */
|
||||||
pr_debug("\t\t\t\tR_386_32 at 0x%-4lx val 0x%x\n", place, value32 + addend32);
|
pr_debug("\t\t\t\tR_386_32 at 0x%-4lx val 0x%x\n", place, value32 + addend32);
|
||||||
pr_out(" { .offset = 0x%-8x, .type = 0, "
|
pr_out(" { .offset = 0x%-8x, .type = PIEGEN_TYPE_INT, "
|
||||||
".addend = %-4d, .value = 0x%x, },\n",
|
".addend = %-4d, .value = 0x%x, },\n",
|
||||||
(unsigned int)place, addend32, value32);
|
(unsigned int)place, addend32, value32);
|
||||||
break;
|
break;
|
||||||
@@ -282,6 +280,7 @@ int handle_elf(const piegen_opt_t *opts, void *mem, size_t size)
|
|||||||
*((s32 *)where) = value32 + addend32 - place;
|
*((s32 *)where) = value32 + addend32 - place;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
default:
|
default:
|
||||||
pr_err("Unsupported relocation\n");
|
pr_err("Unsupported relocation\n");
|
||||||
goto err;
|
goto err;
|
||||||
@@ -302,36 +301,6 @@ int handle_elf(const piegen_opt_t *opts, void *mem, size_t size)
|
|||||||
}
|
}
|
||||||
pr_out("};\n");
|
pr_out("};\n");
|
||||||
|
|
||||||
#if defined(CONFIG_X86_64) || defined(CONFIG_X86_32)
|
|
||||||
pr_out(
|
|
||||||
"static __maybe_unused void elf_apply_relocs(void *mem, void *vbase, size_t size, %s *elf_relocs, size_t nr_relocs)\n"
|
|
||||||
"{\n"
|
|
||||||
" size_t i, j;\n"
|
|
||||||
"\n"
|
|
||||||
" for (i = 0, j = 0; i < nr_relocs; i++) {\n"
|
|
||||||
" if (elf_relocs[i].type) {\n"
|
|
||||||
" long *where = mem + elf_relocs[i].offset;\n"
|
|
||||||
" long *p = mem + size;\n"
|
|
||||||
"\n"
|
|
||||||
" if (elf_relocs[i].type & 2) {\n"
|
|
||||||
" int *value = (int *)where;\n"
|
|
||||||
" int rel;\n"
|
|
||||||
"\n"
|
|
||||||
" p[j] = (long)vbase + elf_relocs[i].value;\n"
|
|
||||||
" rel = (unsigned)((void *)&p[j] - (void *)mem) - elf_relocs[i].offset + elf_relocs[i].addend;\n"
|
|
||||||
"\n"
|
|
||||||
" *value = rel;\n"
|
|
||||||
" j++;\n"
|
|
||||||
" } else\n"
|
|
||||||
" *where = elf_relocs[i].value + elf_relocs[i].addend + (unsigned long)vbase;\n"
|
|
||||||
" } else {\n"
|
|
||||||
" int *where = (mem + elf_relocs[i].offset);\n"
|
|
||||||
" *where = elf_relocs[i].value + elf_relocs[i].addend + (unsigned long)vbase;\n"
|
|
||||||
" }\n"
|
|
||||||
" }\n"
|
|
||||||
"}\n", opts->type_name);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
err:
|
err:
|
||||||
free(sec_hdrs);
|
free(sec_hdrs);
|
||||||
return -1;
|
return -1;
|
||||||
|
@@ -20,7 +20,6 @@
|
|||||||
piegen_opt_t opts = {
|
piegen_opt_t opts = {
|
||||||
.input_filename = "file.o",
|
.input_filename = "file.o",
|
||||||
.stream_name = "stream",
|
.stream_name = "stream",
|
||||||
.type_name = "elf_reloc_t",
|
|
||||||
.prefix_name = "__",
|
.prefix_name = "__",
|
||||||
.var_name = "elf_relocs",
|
.var_name = "elf_relocs",
|
||||||
.nrgotpcrel_name = "nr_gotpcrel",
|
.nrgotpcrel_name = "nr_gotpcrel",
|
||||||
@@ -59,11 +58,10 @@ int main(int argc, char *argv[])
|
|||||||
void *mem;
|
void *mem;
|
||||||
int fd;
|
int fd;
|
||||||
|
|
||||||
static const char short_opts[] = "f:s:t:p:v:h";
|
static const char short_opts[] = "f:s:p:v:h";
|
||||||
static struct option long_opts[] = {
|
static struct option long_opts[] = {
|
||||||
{ "file", required_argument, 0, 'f' },
|
{ "file", required_argument, 0, 'f' },
|
||||||
{ "stream", required_argument, 0, 's' },
|
{ "stream", required_argument, 0, 's' },
|
||||||
{ "type", required_argument, 0, 't' },
|
|
||||||
{ "sym-prefix", required_argument, 0, 'p' },
|
{ "sym-prefix", required_argument, 0, 'p' },
|
||||||
{ "variable", required_argument, 0, 'v' },
|
{ "variable", required_argument, 0, 'v' },
|
||||||
{ "help", required_argument, 0, 'h' },
|
{ "help", required_argument, 0, 'h' },
|
||||||
@@ -88,9 +86,6 @@ int main(int argc, char *argv[])
|
|||||||
case 'p':
|
case 'p':
|
||||||
opts.prefix_name = optarg;
|
opts.prefix_name = optarg;
|
||||||
break;
|
break;
|
||||||
case 't':
|
|
||||||
opts.type_name = optarg;
|
|
||||||
break;
|
|
||||||
case 'v':
|
case 'v':
|
||||||
opts.var_name = optarg;
|
opts.var_name = optarg;
|
||||||
break;
|
break;
|
||||||
|
@@ -7,7 +7,6 @@
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
char *input_filename;
|
char *input_filename;
|
||||||
char *stream_name;
|
char *stream_name;
|
||||||
char *type_name;
|
|
||||||
char *prefix_name;
|
char *prefix_name;
|
||||||
char *var_name;
|
char *var_name;
|
||||||
char *nrgotpcrel_name;
|
char *nrgotpcrel_name;
|
||||||
|
15
pie/piegen/uapi/types.h
Normal file
15
pie/piegen/uapi/types.h
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#ifndef __PIEGEN_TYPES_H__
|
||||||
|
#define __PIEGEN_TYPES_H__
|
||||||
|
|
||||||
|
#define PIEGEN_TYPE_INT (1u << 0)
|
||||||
|
#define PIEGEN_TYPE_LONG (1u << 1)
|
||||||
|
#define PIEGEN_TYPE_GOTPCREL (1u << 2)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned int offset;
|
||||||
|
unsigned int type;
|
||||||
|
long addend;
|
||||||
|
long value;
|
||||||
|
} elf_reloc_t;
|
||||||
|
|
||||||
|
#endif /* __PIEGEN_TYPES_H__ */
|
Reference in New Issue
Block a user