Commit 9d8e0d52 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'x86-boot-2024-05-13' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 boot updates from Ingo Molnar:

 - Move the kernel cmdline setup earlier in the boot process (again),
   to address a split_lock_detect= boot parameter bug

 - Ignore relocations in .notes sections

 - Simplify boot stack setup

 - Re-introduce a bootloader quirk wrt CR4 handling

 - Miscellaneous cleanups & fixes

* tag 'x86-boot-2024-05-13' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/boot/64: Clear most of CR4 in startup_64(), except PAE, MCE and LA57
  x86/boot: Move kernel cmdline setup earlier in the boot process (again)
  x86/build: Clean up arch/x86/tools/relocs.c a bit
  x86/boot: Ignore relocations in .notes sections in walk_relocs() too
  x86: Rename __{start,end}_init_task to __{start,end}_init_stack
  x86/boot: Simplify boot stack setup
parents d791a4da a0025f58
...@@ -398,6 +398,11 @@ SYM_CODE_START(startup_64) ...@@ -398,6 +398,11 @@ SYM_CODE_START(startup_64)
call sev_enable call sev_enable
#endif #endif
/* Preserve only the CR4 bits that must be preserved, and clear the rest */
movq %cr4, %rax
andl $(X86_CR4_PAE | X86_CR4_MCE | X86_CR4_LA57), %eax
movq %rax, %cr4
/* /*
* configure_5level_paging() updates the number of paging levels using * configure_5level_paging() updates the number of paging levels using
* a trampoline in 32-bit addressable memory if the current number does * a trampoline in 32-bit addressable memory if the current number does
......
...@@ -635,12 +635,10 @@ static __always_inline void prefetchw(const void *x) ...@@ -635,12 +635,10 @@ static __always_inline void prefetchw(const void *x)
#define KSTK_ESP(task) (task_pt_regs(task)->sp) #define KSTK_ESP(task) (task_pt_regs(task)->sp)
#else #else
extern unsigned long __end_init_task[]; extern unsigned long __top_init_kernel_stack[];
#define INIT_THREAD { \ #define INIT_THREAD { \
.sp = (unsigned long)&__end_init_task - \ .sp = (unsigned long)&__top_init_kernel_stack, \
TOP_OF_KERNEL_STACK_PADDING - \
sizeof(struct pt_regs), \
} }
extern unsigned long KSTK_ESP(struct task_struct *task); extern unsigned long KSTK_ESP(struct task_struct *task);
......
...@@ -44,9 +44,6 @@ ...@@ -44,9 +44,6 @@
#define X86_CAPABILITY new_cpu_data+CPUINFO_x86_capability #define X86_CAPABILITY new_cpu_data+CPUINFO_x86_capability
#define X86_VENDOR_ID new_cpu_data+CPUINFO_x86_vendor_id #define X86_VENDOR_ID new_cpu_data+CPUINFO_x86_vendor_id
#define SIZEOF_PTREGS 17*4
/* /*
* Worst-case size of the kernel mapping we need to make: * Worst-case size of the kernel mapping we need to make:
* a relocatable kernel can live anywhere in lowmem, so we need to be able * a relocatable kernel can live anywhere in lowmem, so we need to be able
...@@ -488,13 +485,7 @@ SYM_DATA_END(initial_page_table) ...@@ -488,13 +485,7 @@ SYM_DATA_END(initial_page_table)
.data .data
.balign 4 .balign 4
/* SYM_DATA(initial_stack, .long __top_init_kernel_stack)
* The SIZEOF_PTREGS gap is a convention which helps the in-kernel unwinder
* reliably detect the end of the stack.
*/
SYM_DATA(initial_stack,
.long init_thread_union + THREAD_SIZE -
SIZEOF_PTREGS - TOP_OF_KERNEL_STACK_PADDING)
__INITRODATA __INITRODATA
int_msg: int_msg:
......
...@@ -66,7 +66,7 @@ SYM_CODE_START_NOALIGN(startup_64) ...@@ -66,7 +66,7 @@ SYM_CODE_START_NOALIGN(startup_64)
mov %rsi, %r15 mov %rsi, %r15
/* Set up the stack for verify_cpu() */ /* Set up the stack for verify_cpu() */
leaq (__end_init_task - TOP_OF_KERNEL_STACK_PADDING - PTREGS_SIZE)(%rip), %rsp leaq __top_init_kernel_stack(%rip), %rsp
/* Setup GSBASE to allow stack canary access for C code */ /* Setup GSBASE to allow stack canary access for C code */
movl $MSR_GS_BASE, %ecx movl $MSR_GS_BASE, %ecx
......
...@@ -753,6 +753,22 @@ void __init setup_arch(char **cmdline_p) ...@@ -753,6 +753,22 @@ void __init setup_arch(char **cmdline_p)
boot_cpu_data.x86_phys_bits = MAX_PHYSMEM_BITS; boot_cpu_data.x86_phys_bits = MAX_PHYSMEM_BITS;
#endif #endif
#ifdef CONFIG_CMDLINE_BOOL
#ifdef CONFIG_CMDLINE_OVERRIDE
strscpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
#else
if (builtin_cmdline[0]) {
/* append boot loader cmdline to builtin */
strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE);
strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE);
strscpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
}
#endif
#endif
strscpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line;
/* /*
* If we have OLPC OFW, we might end up relocating the fixmap due to * If we have OLPC OFW, we might end up relocating the fixmap due to
* reserve_top(), so do this before touching the ioremap area. * reserve_top(), so do this before touching the ioremap area.
...@@ -832,22 +848,6 @@ void __init setup_arch(char **cmdline_p) ...@@ -832,22 +848,6 @@ void __init setup_arch(char **cmdline_p)
bss_resource.start = __pa_symbol(__bss_start); bss_resource.start = __pa_symbol(__bss_start);
bss_resource.end = __pa_symbol(__bss_stop)-1; bss_resource.end = __pa_symbol(__bss_stop)-1;
#ifdef CONFIG_CMDLINE_BOOL
#ifdef CONFIG_CMDLINE_OVERRIDE
strscpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
#else
if (builtin_cmdline[0]) {
/* append boot loader cmdline to builtin */
strlcat(builtin_cmdline, " ", COMMAND_LINE_SIZE);
strlcat(builtin_cmdline, boot_command_line, COMMAND_LINE_SIZE);
strscpy(boot_command_line, builtin_cmdline, COMMAND_LINE_SIZE);
}
#endif
#endif
strscpy(command_line, boot_command_line, COMMAND_LINE_SIZE);
*cmdline_p = command_line;
/* /*
* x86_configure_nx() is called before parse_early_param() to detect * x86_configure_nx() is called before parse_early_param() to detect
* whether hardware doesn't support NX (so that the early EHCI debug * whether hardware doesn't support NX (so that the early EHCI debug
......
...@@ -172,6 +172,9 @@ SECTIONS ...@@ -172,6 +172,9 @@ SECTIONS
/* init_task */ /* init_task */
INIT_TASK_DATA(THREAD_SIZE) INIT_TASK_DATA(THREAD_SIZE)
/* equivalent to task_pt_regs(&init_task) */
__top_init_kernel_stack = __end_init_stack - TOP_OF_KERNEL_STACK_PADDING - PTREGS_SIZE;
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
/* 32 bit has nosave before _edata */ /* 32 bit has nosave before _edata */
NOSAVE_DATA NOSAVE_DATA
......
...@@ -11,41 +11,42 @@ ...@@ -11,41 +11,42 @@
#define Elf_Shdr ElfW(Shdr) #define Elf_Shdr ElfW(Shdr)
#define Elf_Sym ElfW(Sym) #define Elf_Sym ElfW(Sym)
static Elf_Ehdr ehdr; static Elf_Ehdr ehdr;
static unsigned long shnum; static unsigned long shnum;
static unsigned int shstrndx; static unsigned int shstrndx;
static unsigned int shsymtabndx; static unsigned int shsymtabndx;
static unsigned int shxsymtabndx; static unsigned int shxsymtabndx;
static int sym_index(Elf_Sym *sym); static int sym_index(Elf_Sym *sym);
struct relocs { struct relocs {
uint32_t *offset; uint32_t *offset;
unsigned long count; unsigned long count;
unsigned long size; unsigned long size;
}; };
static struct relocs relocs16; static struct relocs relocs16;
static struct relocs relocs32; static struct relocs relocs32;
#if ELF_BITS == 64 #if ELF_BITS == 64
static struct relocs relocs32neg; static struct relocs relocs32neg;
static struct relocs relocs64; static struct relocs relocs64;
#define FMT PRIu64 # define FMT PRIu64
#else #else
#define FMT PRIu32 # define FMT PRIu32
#endif #endif
struct section { struct section {
Elf_Shdr shdr; Elf_Shdr shdr;
struct section *link; struct section *link;
Elf_Sym *symtab; Elf_Sym *symtab;
Elf32_Word *xsymtab; Elf32_Word *xsymtab;
Elf_Rel *reltab; Elf_Rel *reltab;
char *strtab; char *strtab;
}; };
static struct section *secs; static struct section *secs;
static const char * const sym_regex_kernel[S_NSYMTYPES] = { static const char * const sym_regex_kernel[S_NSYMTYPES] = {
/* /*
* Following symbols have been audited. There values are constant and do * Following symbols have been audited. There values are constant and do
* not change if bzImage is loaded at a different physical address than * not change if bzImage is loaded at a different physical address than
...@@ -115,13 +116,13 @@ static const char * const sym_regex_realmode[S_NSYMTYPES] = { ...@@ -115,13 +116,13 @@ static const char * const sym_regex_realmode[S_NSYMTYPES] = {
"^pa_", "^pa_",
}; };
static const char * const *sym_regex; static const char * const *sym_regex;
static regex_t sym_regex_c[S_NSYMTYPES];
static regex_t sym_regex_c[S_NSYMTYPES];
static int is_reloc(enum symtype type, const char *sym_name) static int is_reloc(enum symtype type, const char *sym_name)
{ {
return sym_regex[type] && return sym_regex[type] && !regexec(&sym_regex_c[type], sym_name, 0, NULL, 0);
!regexec(&sym_regex_c[type], sym_name, 0, NULL, 0);
} }
static void regex_init(int use_real_mode) static void regex_init(int use_real_mode)
...@@ -139,8 +140,7 @@ static void regex_init(int use_real_mode) ...@@ -139,8 +140,7 @@ static void regex_init(int use_real_mode)
if (!sym_regex[i]) if (!sym_regex[i])
continue; continue;
err = regcomp(&sym_regex_c[i], sym_regex[i], err = regcomp(&sym_regex_c[i], sym_regex[i], REG_EXTENDED|REG_NOSUB);
REG_EXTENDED|REG_NOSUB);
if (err) { if (err) {
regerror(err, &sym_regex_c[i], errbuf, sizeof(errbuf)); regerror(err, &sym_regex_c[i], errbuf, sizeof(errbuf));
...@@ -163,9 +163,10 @@ static const char *sym_type(unsigned type) ...@@ -163,9 +163,10 @@ static const char *sym_type(unsigned type)
#undef SYM_TYPE #undef SYM_TYPE
}; };
const char *name = "unknown sym type name"; const char *name = "unknown sym type name";
if (type < ARRAY_SIZE(type_name)) {
if (type < ARRAY_SIZE(type_name))
name = type_name[type]; name = type_name[type];
}
return name; return name;
} }
...@@ -179,9 +180,10 @@ static const char *sym_bind(unsigned bind) ...@@ -179,9 +180,10 @@ static const char *sym_bind(unsigned bind)
#undef SYM_BIND #undef SYM_BIND
}; };
const char *name = "unknown sym bind name"; const char *name = "unknown sym bind name";
if (bind < ARRAY_SIZE(bind_name)) {
if (bind < ARRAY_SIZE(bind_name))
name = bind_name[bind]; name = bind_name[bind];
}
return name; return name;
} }
...@@ -196,9 +198,10 @@ static const char *sym_visibility(unsigned visibility) ...@@ -196,9 +198,10 @@ static const char *sym_visibility(unsigned visibility)
#undef SYM_VISIBILITY #undef SYM_VISIBILITY
}; };
const char *name = "unknown sym visibility name"; const char *name = "unknown sym visibility name";
if (visibility < ARRAY_SIZE(visibility_name)) {
if (visibility < ARRAY_SIZE(visibility_name))
name = visibility_name[visibility]; name = visibility_name[visibility];
}
return name; return name;
} }
...@@ -244,9 +247,10 @@ static const char *rel_type(unsigned type) ...@@ -244,9 +247,10 @@ static const char *rel_type(unsigned type)
#undef REL_TYPE #undef REL_TYPE
}; };
const char *name = "unknown type rel type name"; const char *name = "unknown type rel type name";
if (type < ARRAY_SIZE(type_name) && type_name[type]) {
if (type < ARRAY_SIZE(type_name) && type_name[type])
name = type_name[type]; name = type_name[type];
}
return name; return name;
} }
...@@ -256,15 +260,14 @@ static const char *sec_name(unsigned shndx) ...@@ -256,15 +260,14 @@ static const char *sec_name(unsigned shndx)
const char *name; const char *name;
sec_strtab = secs[shstrndx].strtab; sec_strtab = secs[shstrndx].strtab;
name = "<noname>"; name = "<noname>";
if (shndx < shnum) {
if (shndx < shnum)
name = sec_strtab + secs[shndx].shdr.sh_name; name = sec_strtab + secs[shndx].shdr.sh_name;
} else if (shndx == SHN_ABS)
else if (shndx == SHN_ABS) {
name = "ABSOLUTE"; name = "ABSOLUTE";
} else if (shndx == SHN_COMMON)
else if (shndx == SHN_COMMON) {
name = "COMMON"; name = "COMMON";
}
return name; return name;
} }
...@@ -272,18 +275,19 @@ static const char *sym_name(const char *sym_strtab, Elf_Sym *sym) ...@@ -272,18 +275,19 @@ static const char *sym_name(const char *sym_strtab, Elf_Sym *sym)
{ {
const char *name; const char *name;
name = "<noname>"; name = "<noname>";
if (sym->st_name) {
if (sym->st_name)
name = sym_strtab + sym->st_name; name = sym_strtab + sym->st_name;
} else
else {
name = sec_name(sym_index(sym)); name = sec_name(sym_index(sym));
}
return name; return name;
} }
static Elf_Sym *sym_lookup(const char *symname) static Elf_Sym *sym_lookup(const char *symname)
{ {
int i; int i;
for (i = 0; i < shnum; i++) { for (i = 0; i < shnum; i++) {
struct section *sec = &secs[i]; struct section *sec = &secs[i];
long nsyms; long nsyms;
...@@ -309,14 +313,15 @@ static Elf_Sym *sym_lookup(const char *symname) ...@@ -309,14 +313,15 @@ static Elf_Sym *sym_lookup(const char *symname)
} }
#if BYTE_ORDER == LITTLE_ENDIAN #if BYTE_ORDER == LITTLE_ENDIAN
#define le16_to_cpu(val) (val) # define le16_to_cpu(val) (val)
#define le32_to_cpu(val) (val) # define le32_to_cpu(val) (val)
#define le64_to_cpu(val) (val) # define le64_to_cpu(val) (val)
#endif #endif
#if BYTE_ORDER == BIG_ENDIAN #if BYTE_ORDER == BIG_ENDIAN
#define le16_to_cpu(val) bswap_16(val) # define le16_to_cpu(val) bswap_16(val)
#define le32_to_cpu(val) bswap_32(val) # define le32_to_cpu(val) bswap_32(val)
#define le64_to_cpu(val) bswap_64(val) # define le64_to_cpu(val) bswap_64(val)
#endif #endif
static uint16_t elf16_to_cpu(uint16_t val) static uint16_t elf16_to_cpu(uint16_t val)
...@@ -337,13 +342,13 @@ static uint64_t elf64_to_cpu(uint64_t val) ...@@ -337,13 +342,13 @@ static uint64_t elf64_to_cpu(uint64_t val)
{ {
return le64_to_cpu(val); return le64_to_cpu(val);
} }
#define elf_addr_to_cpu(x) elf64_to_cpu(x) # define elf_addr_to_cpu(x) elf64_to_cpu(x)
#define elf_off_to_cpu(x) elf64_to_cpu(x) # define elf_off_to_cpu(x) elf64_to_cpu(x)
#define elf_xword_to_cpu(x) elf64_to_cpu(x) # define elf_xword_to_cpu(x) elf64_to_cpu(x)
#else #else
#define elf_addr_to_cpu(x) elf32_to_cpu(x) # define elf_addr_to_cpu(x) elf32_to_cpu(x)
#define elf_off_to_cpu(x) elf32_to_cpu(x) # define elf_off_to_cpu(x) elf32_to_cpu(x)
#define elf_xword_to_cpu(x) elf32_to_cpu(x) # define elf_xword_to_cpu(x) elf32_to_cpu(x)
#endif #endif
static int sym_index(Elf_Sym *sym) static int sym_index(Elf_Sym *sym)
...@@ -365,22 +370,17 @@ static int sym_index(Elf_Sym *sym) ...@@ -365,22 +370,17 @@ static int sym_index(Elf_Sym *sym)
static void read_ehdr(FILE *fp) static void read_ehdr(FILE *fp)
{ {
if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1) { if (fread(&ehdr, sizeof(ehdr), 1, fp) != 1)
die("Cannot read ELF header: %s\n", die("Cannot read ELF header: %s\n", strerror(errno));
strerror(errno)); if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0)
}
if (memcmp(ehdr.e_ident, ELFMAG, SELFMAG) != 0) {
die("No ELF magic\n"); die("No ELF magic\n");
} if (ehdr.e_ident[EI_CLASS] != ELF_CLASS)
if (ehdr.e_ident[EI_CLASS] != ELF_CLASS) {
die("Not a %d bit executable\n", ELF_BITS); die("Not a %d bit executable\n", ELF_BITS);
} if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB)
if (ehdr.e_ident[EI_DATA] != ELFDATA2LSB) {
die("Not a LSB ELF executable\n"); die("Not a LSB ELF executable\n");
} if (ehdr.e_ident[EI_VERSION] != EV_CURRENT)
if (ehdr.e_ident[EI_VERSION] != EV_CURRENT) {
die("Unknown ELF version\n"); die("Unknown ELF version\n");
}
/* Convert the fields to native endian */ /* Convert the fields to native endian */
ehdr.e_type = elf_half_to_cpu(ehdr.e_type); ehdr.e_type = elf_half_to_cpu(ehdr.e_type);
ehdr.e_machine = elf_half_to_cpu(ehdr.e_machine); ehdr.e_machine = elf_half_to_cpu(ehdr.e_machine);
...@@ -439,19 +439,18 @@ static void read_shdrs(FILE *fp) ...@@ -439,19 +439,18 @@ static void read_shdrs(FILE *fp)
Elf_Shdr shdr; Elf_Shdr shdr;
secs = calloc(shnum, sizeof(struct section)); secs = calloc(shnum, sizeof(struct section));
if (!secs) { if (!secs)
die("Unable to allocate %ld section headers\n", die("Unable to allocate %ld section headers\n", shnum);
shnum);
} if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0)
if (fseek(fp, ehdr.e_shoff, SEEK_SET) < 0) { die("Seek to %" FMT " failed: %s\n", ehdr.e_shoff, strerror(errno));
die("Seek to %" FMT " failed: %s\n",
ehdr.e_shoff, strerror(errno));
}
for (i = 0; i < shnum; i++) { for (i = 0; i < shnum; i++) {
struct section *sec = &secs[i]; struct section *sec = &secs[i];
if (fread(&shdr, sizeof(shdr), 1, fp) != 1) if (fread(&shdr, sizeof(shdr), 1, fp) != 1)
die("Cannot read ELF section headers %d/%ld: %s\n", die("Cannot read ELF section headers %d/%ld: %s\n", i, shnum, strerror(errno));
i, shnum, strerror(errno));
sec->shdr.sh_name = elf_word_to_cpu(shdr.sh_name); sec->shdr.sh_name = elf_word_to_cpu(shdr.sh_name);
sec->shdr.sh_type = elf_word_to_cpu(shdr.sh_type); sec->shdr.sh_type = elf_word_to_cpu(shdr.sh_type);
sec->shdr.sh_flags = elf_xword_to_cpu(shdr.sh_flags); sec->shdr.sh_flags = elf_xword_to_cpu(shdr.sh_flags);
...@@ -471,31 +470,28 @@ static void read_shdrs(FILE *fp) ...@@ -471,31 +470,28 @@ static void read_shdrs(FILE *fp)
static void read_strtabs(FILE *fp) static void read_strtabs(FILE *fp)
{ {
int i; int i;
for (i = 0; i < shnum; i++) { for (i = 0; i < shnum; i++) {
struct section *sec = &secs[i]; struct section *sec = &secs[i];
if (sec->shdr.sh_type != SHT_STRTAB) {
if (sec->shdr.sh_type != SHT_STRTAB)
continue; continue;
}
sec->strtab = malloc(sec->shdr.sh_size); sec->strtab = malloc(sec->shdr.sh_size);
if (!sec->strtab) { if (!sec->strtab)
die("malloc of %" FMT " bytes for strtab failed\n", die("malloc of %" FMT " bytes for strtab failed\n", sec->shdr.sh_size);
sec->shdr.sh_size);
} if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0)
if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { die("Seek to %" FMT " failed: %s\n", sec->shdr.sh_offset, strerror(errno));
die("Seek to %" FMT " failed: %s\n",
sec->shdr.sh_offset, strerror(errno)); if (fread(sec->strtab, 1, sec->shdr.sh_size, fp) != sec->shdr.sh_size)
} die("Cannot read symbol table: %s\n", strerror(errno));
if (fread(sec->strtab, 1, sec->shdr.sh_size, fp)
!= sec->shdr.sh_size) {
die("Cannot read symbol table: %s\n",
strerror(errno));
}
} }
} }
static void read_symtabs(FILE *fp) static void read_symtabs(FILE *fp)
{ {
int i,j; int i, j;
for (i = 0; i < shnum; i++) { for (i = 0; i < shnum; i++) {
struct section *sec = &secs[i]; struct section *sec = &secs[i];
...@@ -504,19 +500,15 @@ static void read_symtabs(FILE *fp) ...@@ -504,19 +500,15 @@ static void read_symtabs(FILE *fp)
switch (sec->shdr.sh_type) { switch (sec->shdr.sh_type) {
case SHT_SYMTAB_SHNDX: case SHT_SYMTAB_SHNDX:
sec->xsymtab = malloc(sec->shdr.sh_size); sec->xsymtab = malloc(sec->shdr.sh_size);
if (!sec->xsymtab) { if (!sec->xsymtab)
die("malloc of %" FMT " bytes for xsymtab failed\n", die("malloc of %" FMT " bytes for xsymtab failed\n", sec->shdr.sh_size);
sec->shdr.sh_size);
} if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0)
if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { die("Seek to %" FMT " failed: %s\n", sec->shdr.sh_offset, strerror(errno));
die("Seek to %" FMT " failed: %s\n",
sec->shdr.sh_offset, strerror(errno)); if (fread(sec->xsymtab, 1, sec->shdr.sh_size, fp) != sec->shdr.sh_size)
} die("Cannot read extended symbol table: %s\n", strerror(errno));
if (fread(sec->xsymtab, 1, sec->shdr.sh_size, fp)
!= sec->shdr.sh_size) {
die("Cannot read extended symbol table: %s\n",
strerror(errno));
}
shxsymtabndx = i; shxsymtabndx = i;
continue; continue;
...@@ -524,19 +516,15 @@ static void read_symtabs(FILE *fp) ...@@ -524,19 +516,15 @@ static void read_symtabs(FILE *fp)
num_syms = sec->shdr.sh_size / sizeof(Elf_Sym); num_syms = sec->shdr.sh_size / sizeof(Elf_Sym);
sec->symtab = malloc(sec->shdr.sh_size); sec->symtab = malloc(sec->shdr.sh_size);
if (!sec->symtab) { if (!sec->symtab)
die("malloc of %" FMT " bytes for symtab failed\n", die("malloc of %" FMT " bytes for symtab failed\n", sec->shdr.sh_size);
sec->shdr.sh_size);
} if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0)
if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { die("Seek to %" FMT " failed: %s\n", sec->shdr.sh_offset, strerror(errno));
die("Seek to %" FMT " failed: %s\n",
sec->shdr.sh_offset, strerror(errno)); if (fread(sec->symtab, 1, sec->shdr.sh_size, fp) != sec->shdr.sh_size)
} die("Cannot read symbol table: %s\n", strerror(errno));
if (fread(sec->symtab, 1, sec->shdr.sh_size, fp)
!= sec->shdr.sh_size) {
die("Cannot read symbol table: %s\n",
strerror(errno));
}
for (j = 0; j < num_syms; j++) { for (j = 0; j < num_syms; j++) {
Elf_Sym *sym = &sec->symtab[j]; Elf_Sym *sym = &sec->symtab[j];
...@@ -557,28 +545,27 @@ static void read_symtabs(FILE *fp) ...@@ -557,28 +545,27 @@ static void read_symtabs(FILE *fp)
static void read_relocs(FILE *fp) static void read_relocs(FILE *fp)
{ {
int i,j; int i, j;
for (i = 0; i < shnum; i++) { for (i = 0; i < shnum; i++) {
struct section *sec = &secs[i]; struct section *sec = &secs[i];
if (sec->shdr.sh_type != SHT_REL_TYPE) {
if (sec->shdr.sh_type != SHT_REL_TYPE)
continue; continue;
}
sec->reltab = malloc(sec->shdr.sh_size); sec->reltab = malloc(sec->shdr.sh_size);
if (!sec->reltab) { if (!sec->reltab)
die("malloc of %" FMT " bytes for relocs failed\n", die("malloc of %" FMT " bytes for relocs failed\n", sec->shdr.sh_size);
sec->shdr.sh_size);
} if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0)
if (fseek(fp, sec->shdr.sh_offset, SEEK_SET) < 0) { die("Seek to %" FMT " failed: %s\n", sec->shdr.sh_offset, strerror(errno));
die("Seek to %" FMT " failed: %s\n",
sec->shdr.sh_offset, strerror(errno)); if (fread(sec->reltab, 1, sec->shdr.sh_size, fp) != sec->shdr.sh_size)
} die("Cannot read symbol table: %s\n", strerror(errno));
if (fread(sec->reltab, 1, sec->shdr.sh_size, fp)
!= sec->shdr.sh_size) {
die("Cannot read symbol table: %s\n",
strerror(errno));
}
for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) { for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
Elf_Rel *rel = &sec->reltab[j]; Elf_Rel *rel = &sec->reltab[j];
rel->r_offset = elf_addr_to_cpu(rel->r_offset); rel->r_offset = elf_addr_to_cpu(rel->r_offset);
rel->r_info = elf_xword_to_cpu(rel->r_info); rel->r_info = elf_xword_to_cpu(rel->r_info);
#if (SHT_REL_TYPE == SHT_RELA) #if (SHT_REL_TYPE == SHT_RELA)
...@@ -601,23 +588,27 @@ static void print_absolute_symbols(void) ...@@ -601,23 +588,27 @@ static void print_absolute_symbols(void)
printf("Absolute symbols\n"); printf("Absolute symbols\n");
printf(" Num: Value Size Type Bind Visibility Name\n"); printf(" Num: Value Size Type Bind Visibility Name\n");
for (i = 0; i < shnum; i++) { for (i = 0; i < shnum; i++) {
struct section *sec = &secs[i]; struct section *sec = &secs[i];
char *sym_strtab; char *sym_strtab;
int j; int j;
if (sec->shdr.sh_type != SHT_SYMTAB) { if (sec->shdr.sh_type != SHT_SYMTAB)
continue; continue;
}
sym_strtab = sec->link->strtab; sym_strtab = sec->link->strtab;
for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Sym); j++) { for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Sym); j++) {
Elf_Sym *sym; Elf_Sym *sym;
const char *name; const char *name;
sym = &sec->symtab[j]; sym = &sec->symtab[j];
name = sym_name(sym_strtab, sym); name = sym_name(sym_strtab, sym);
if (sym->st_shndx != SHN_ABS) {
if (sym->st_shndx != SHN_ABS)
continue; continue;
}
printf(format, printf(format,
j, sym->st_value, sym->st_size, j, sym->st_value, sym->st_size,
sym_type(ELF_ST_TYPE(sym->st_info)), sym_type(ELF_ST_TYPE(sym->st_info)),
...@@ -645,34 +636,37 @@ static void print_absolute_relocs(void) ...@@ -645,34 +636,37 @@ static void print_absolute_relocs(void)
char *sym_strtab; char *sym_strtab;
Elf_Sym *sh_symtab; Elf_Sym *sh_symtab;
int j; int j;
if (sec->shdr.sh_type != SHT_REL_TYPE) {
if (sec->shdr.sh_type != SHT_REL_TYPE)
continue; continue;
}
sec_symtab = sec->link; sec_symtab = sec->link;
sec_applies = &secs[sec->shdr.sh_info]; sec_applies = &secs[sec->shdr.sh_info];
if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) { if (!(sec_applies->shdr.sh_flags & SHF_ALLOC))
continue; continue;
}
/* /*
* Do not perform relocations in .notes section; any * Do not perform relocations in .notes section; any
* values there are meant for pre-boot consumption (e.g. * values there are meant for pre-boot consumption (e.g.
* startup_xen). * startup_xen).
*/ */
if (sec_applies->shdr.sh_type == SHT_NOTE) { if (sec_applies->shdr.sh_type == SHT_NOTE)
continue; continue;
}
sh_symtab = sec_symtab->symtab; sh_symtab = sec_symtab->symtab;
sym_strtab = sec_symtab->link->strtab; sym_strtab = sec_symtab->link->strtab;
for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) { for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
Elf_Rel *rel; Elf_Rel *rel;
Elf_Sym *sym; Elf_Sym *sym;
const char *name; const char *name;
rel = &sec->reltab[j]; rel = &sec->reltab[j];
sym = &sh_symtab[ELF_R_SYM(rel->r_info)]; sym = &sh_symtab[ELF_R_SYM(rel->r_info)];
name = sym_name(sym_strtab, sym); name = sym_name(sym_strtab, sym);
if (sym->st_shndx != SHN_ABS) {
if (sym->st_shndx != SHN_ABS)
continue; continue;
}
/* Absolute symbols are not relocated if bzImage is /* Absolute symbols are not relocated if bzImage is
* loaded at a non-compiled address. Display a warning * loaded at a non-compiled address. Display a warning
...@@ -691,10 +685,8 @@ static void print_absolute_relocs(void) ...@@ -691,10 +685,8 @@ static void print_absolute_relocs(void)
continue; continue;
if (!printed) { if (!printed) {
printf("WARNING: Absolute relocations" printf("WARNING: Absolute relocations present\n");
" present\n"); printf("Offset Info Type Sym.Value Sym.Name\n");
printf("Offset Info Type Sym.Value "
"Sym.Name\n");
printed = 1; printed = 1;
} }
...@@ -718,8 +710,8 @@ static void add_reloc(struct relocs *r, uint32_t offset) ...@@ -718,8 +710,8 @@ static void add_reloc(struct relocs *r, uint32_t offset)
void *mem = realloc(r->offset, newsize * sizeof(r->offset[0])); void *mem = realloc(r->offset, newsize * sizeof(r->offset[0]));
if (!mem) if (!mem)
die("realloc of %ld entries for relocs failed\n", die("realloc of %ld entries for relocs failed\n", newsize);
newsize);
r->offset = mem; r->offset = mem;
r->size = newsize; r->size = newsize;
} }
...@@ -730,6 +722,7 @@ static void walk_relocs(int (*process)(struct section *sec, Elf_Rel *rel, ...@@ -730,6 +722,7 @@ static void walk_relocs(int (*process)(struct section *sec, Elf_Rel *rel,
Elf_Sym *sym, const char *symname)) Elf_Sym *sym, const char *symname))
{ {
int i; int i;
/* Walk through the relocations */ /* Walk through the relocations */
for (i = 0; i < shnum; i++) { for (i = 0; i < shnum; i++) {
char *sym_strtab; char *sym_strtab;
...@@ -738,16 +731,25 @@ static void walk_relocs(int (*process)(struct section *sec, Elf_Rel *rel, ...@@ -738,16 +731,25 @@ static void walk_relocs(int (*process)(struct section *sec, Elf_Rel *rel,
int j; int j;
struct section *sec = &secs[i]; struct section *sec = &secs[i];
if (sec->shdr.sh_type != SHT_REL_TYPE) { if (sec->shdr.sh_type != SHT_REL_TYPE)
continue; continue;
}
sec_symtab = sec->link; sec_symtab = sec->link;
sec_applies = &secs[sec->shdr.sh_info]; sec_applies = &secs[sec->shdr.sh_info];
if (!(sec_applies->shdr.sh_flags & SHF_ALLOC)) { if (!(sec_applies->shdr.sh_flags & SHF_ALLOC))
continue; continue;
}
/*
* Do not perform relocations in .notes sections; any
* values there are meant for pre-boot consumption (e.g.
* startup_xen).
*/
if (sec_applies->shdr.sh_type == SHT_NOTE)
continue;
sh_symtab = sec_symtab->symtab; sh_symtab = sec_symtab->symtab;
sym_strtab = sec_symtab->link->strtab; sym_strtab = sec_symtab->link->strtab;
for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) { for (j = 0; j < sec->shdr.sh_size/sizeof(Elf_Rel); j++) {
Elf_Rel *rel = &sec->reltab[j]; Elf_Rel *rel = &sec->reltab[j];
Elf_Sym *sym = &sh_symtab[ELF_R_SYM(rel->r_info)]; Elf_Sym *sym = &sh_symtab[ELF_R_SYM(rel->r_info)];
...@@ -781,14 +783,16 @@ static void walk_relocs(int (*process)(struct section *sec, Elf_Rel *rel, ...@@ -781,14 +783,16 @@ static void walk_relocs(int (*process)(struct section *sec, Elf_Rel *rel,
* kernel data and does not require special treatment. * kernel data and does not require special treatment.
* *
*/ */
static int per_cpu_shndx = -1; static int per_cpu_shndx = -1;
static Elf_Addr per_cpu_load_addr; static Elf_Addr per_cpu_load_addr;
static void percpu_init(void) static void percpu_init(void)
{ {
int i; int i;
for (i = 0; i < shnum; i++) { for (i = 0; i < shnum; i++) {
ElfW(Sym) *sym; ElfW(Sym) *sym;
if (strcmp(sec_name(i), ".data..percpu")) if (strcmp(sec_name(i), ".data..percpu"))
continue; continue;
...@@ -801,6 +805,7 @@ static void percpu_init(void) ...@@ -801,6 +805,7 @@ static void percpu_init(void)
per_cpu_shndx = i; per_cpu_shndx = i;
per_cpu_load_addr = sym->st_value; per_cpu_load_addr = sym->st_value;
return; return;
} }
} }
...@@ -871,8 +876,7 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, ...@@ -871,8 +876,7 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym,
* Only used by jump labels * Only used by jump labels
*/ */
if (is_percpu_sym(sym, symname)) if (is_percpu_sym(sym, symname))
die("Invalid R_X86_64_PC64 relocation against per-CPU symbol %s\n", die("Invalid R_X86_64_PC64 relocation against per-CPU symbol %s\n", symname);
symname);
break; break;
case R_X86_64_32: case R_X86_64_32:
...@@ -892,8 +896,7 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, ...@@ -892,8 +896,7 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym,
if (is_reloc(S_ABS, symname)) if (is_reloc(S_ABS, symname))
break; break;
die("Invalid absolute %s relocation: %s\n", die("Invalid absolute %s relocation: %s\n", rel_type(r_type), symname);
rel_type(r_type), symname);
break; break;
} }
...@@ -913,8 +916,7 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, ...@@ -913,8 +916,7 @@ static int do_reloc64(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym,
break; break;
default: default:
die("Unsupported relocation type: %s (%d)\n", die("Unsupported relocation type: %s (%d)\n", rel_type(r_type), r_type);
rel_type(r_type), r_type);
break; break;
} }
...@@ -951,8 +953,7 @@ static int do_reloc32(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, ...@@ -951,8 +953,7 @@ static int do_reloc32(struct section *sec, Elf_Rel *rel, Elf_Sym *sym,
if (is_reloc(S_ABS, symname)) if (is_reloc(S_ABS, symname))
break; break;
die("Invalid absolute %s relocation: %s\n", die("Invalid absolute %s relocation: %s\n", rel_type(r_type), symname);
rel_type(r_type), symname);
break; break;
} }
...@@ -960,16 +961,14 @@ static int do_reloc32(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, ...@@ -960,16 +961,14 @@ static int do_reloc32(struct section *sec, Elf_Rel *rel, Elf_Sym *sym,
break; break;
default: default:
die("Unsupported relocation type: %s (%d)\n", die("Unsupported relocation type: %s (%d)\n", rel_type(r_type), r_type);
rel_type(r_type), r_type);
break; break;
} }
return 0; return 0;
} }
static int do_reloc_real(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, static int do_reloc_real(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, const char *symname)
const char *symname)
{ {
unsigned r_type = ELF32_R_TYPE(rel->r_info); unsigned r_type = ELF32_R_TYPE(rel->r_info);
int shn_abs = (sym->st_shndx == SHN_ABS) && !is_reloc(S_REL, symname); int shn_abs = (sym->st_shndx == SHN_ABS) && !is_reloc(S_REL, symname);
...@@ -1004,9 +1003,7 @@ static int do_reloc_real(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, ...@@ -1004,9 +1003,7 @@ static int do_reloc_real(struct section *sec, Elf_Rel *rel, Elf_Sym *sym,
if (!is_reloc(S_LIN, symname)) if (!is_reloc(S_LIN, symname))
break; break;
} }
die("Invalid %s %s relocation: %s\n", die("Invalid %s %s relocation: %s\n", shn_abs ? "absolute" : "relative", rel_type(r_type), symname);
shn_abs ? "absolute" : "relative",
rel_type(r_type), symname);
break; break;
case R_386_32: case R_386_32:
...@@ -1027,14 +1024,11 @@ static int do_reloc_real(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, ...@@ -1027,14 +1024,11 @@ static int do_reloc_real(struct section *sec, Elf_Rel *rel, Elf_Sym *sym,
add_reloc(&relocs32, rel->r_offset); add_reloc(&relocs32, rel->r_offset);
break; break;
} }
die("Invalid %s %s relocation: %s\n", die("Invalid %s %s relocation: %s\n", shn_abs ? "absolute" : "relative", rel_type(r_type), symname);
shn_abs ? "absolute" : "relative",
rel_type(r_type), symname);
break; break;
default: default:
die("Unsupported relocation type: %s (%d)\n", die("Unsupported relocation type: %s (%d)\n", rel_type(r_type), r_type);
rel_type(r_type), r_type);
break; break;
} }
...@@ -1046,7 +1040,10 @@ static int do_reloc_real(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, ...@@ -1046,7 +1040,10 @@ static int do_reloc_real(struct section *sec, Elf_Rel *rel, Elf_Sym *sym,
static int cmp_relocs(const void *va, const void *vb) static int cmp_relocs(const void *va, const void *vb)
{ {
const uint32_t *a, *b; const uint32_t *a, *b;
a = va; b = vb;
a = va;
b = vb;
return (*a == *b)? 0 : (*a > *b)? 1 : -1; return (*a == *b)? 0 : (*a > *b)? 1 : -1;
} }
...@@ -1060,6 +1057,7 @@ static int write32(uint32_t v, FILE *f) ...@@ -1060,6 +1057,7 @@ static int write32(uint32_t v, FILE *f)
unsigned char buf[4]; unsigned char buf[4];
put_unaligned_le32(v, buf); put_unaligned_le32(v, buf);
return fwrite(buf, 1, 4, f) == 4 ? 0 : -1; return fwrite(buf, 1, 4, f) == 4 ? 0 : -1;
} }
...@@ -1072,8 +1070,7 @@ static void emit_relocs(int as_text, int use_real_mode) ...@@ -1072,8 +1070,7 @@ static void emit_relocs(int as_text, int use_real_mode)
{ {
int i; int i;
int (*write_reloc)(uint32_t, FILE *) = write32; int (*write_reloc)(uint32_t, FILE *) = write32;
int (*do_reloc)(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, int (*do_reloc)(struct section *sec, Elf_Rel *rel, Elf_Sym *sym, const char *symname);
const char *symname);
#if ELF_BITS == 64 #if ELF_BITS == 64
if (!use_real_mode) if (!use_real_mode)
...@@ -1160,6 +1157,7 @@ static int do_reloc_info(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym, ...@@ -1160,6 +1157,7 @@ static int do_reloc_info(struct section *sec, Elf_Rel *rel, ElfW(Sym) *sym,
rel_type(ELF_R_TYPE(rel->r_info)), rel_type(ELF_R_TYPE(rel->r_info)),
symname, symname,
sec_name(sym_index(sym))); sec_name(sym_index(sym)));
return 0; return 0;
} }
...@@ -1185,19 +1183,24 @@ void process(FILE *fp, int use_real_mode, int as_text, ...@@ -1185,19 +1183,24 @@ void process(FILE *fp, int use_real_mode, int as_text,
read_strtabs(fp); read_strtabs(fp);
read_symtabs(fp); read_symtabs(fp);
read_relocs(fp); read_relocs(fp);
if (ELF_BITS == 64) if (ELF_BITS == 64)
percpu_init(); percpu_init();
if (show_absolute_syms) { if (show_absolute_syms) {
print_absolute_symbols(); print_absolute_symbols();
return; return;
} }
if (show_absolute_relocs) { if (show_absolute_relocs) {
print_absolute_relocs(); print_absolute_relocs();
return; return;
} }
if (show_reloc_info) { if (show_reloc_info) {
print_reloc_info(); print_reloc_info();
return; return;
} }
emit_relocs(as_text, use_real_mode); emit_relocs(as_text, use_real_mode);
} }
...@@ -49,7 +49,7 @@ SYM_CODE_START(startup_xen) ...@@ -49,7 +49,7 @@ SYM_CODE_START(startup_xen)
ANNOTATE_NOENDBR ANNOTATE_NOENDBR
cld cld
leaq (__end_init_task - TOP_OF_KERNEL_STACK_PADDING - PTREGS_SIZE)(%rip), %rsp leaq __top_init_kernel_stack(%rip), %rsp
/* Set up %gs. /* Set up %gs.
* *
......
...@@ -399,13 +399,13 @@ ...@@ -399,13 +399,13 @@
#define INIT_TASK_DATA(align) \ #define INIT_TASK_DATA(align) \
. = ALIGN(align); \ . = ALIGN(align); \
__start_init_task = .; \ __start_init_stack = .; \
init_thread_union = .; \ init_thread_union = .; \
init_stack = .; \ init_stack = .; \
KEEP(*(.data..init_task)) \ KEEP(*(.data..init_task)) \
KEEP(*(.data..init_thread_info)) \ KEEP(*(.data..init_thread_info)) \
. = __start_init_task + THREAD_SIZE; \ . = __start_init_stack + THREAD_SIZE; \
__end_init_task = .; __end_init_stack = .;
#define JUMP_TABLE_DATA \ #define JUMP_TABLE_DATA \
. = ALIGN(8); \ . = ALIGN(8); \
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment