Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F145615319
D25223.id73423.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
12 KB
Referenced Files
None
Subscribers
None
D25223.id73423.diff
View Options
Index: head/sys/amd64/amd64/machdep.c
===================================================================
--- head/sys/amd64/amd64/machdep.c
+++ head/sys/amd64/amd64/machdep.c
@@ -1508,7 +1508,7 @@
#ifdef DDB
ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
- db_fetch_ksymtab(ksym_start, ksym_end);
+ db_fetch_ksymtab(ksym_start, ksym_end, 0);
#endif
efi_systbl_phys = MD_FETCH(kmdp, MODINFOMD_FW_HANDLE, vm_paddr_t);
Index: head/sys/arm/arm/machdep_boot.c
===================================================================
--- head/sys/arm/arm/machdep_boot.c
+++ head/sys/arm/arm/machdep_boot.c
@@ -302,7 +302,7 @@
#ifdef DDB
ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
- db_fetch_ksymtab(ksym_start, ksym_end);
+ db_fetch_ksymtab(ksym_start, ksym_end, 0);
#endif
return lastaddr;
}
Index: head/sys/arm64/arm64/machdep_boot.c
===================================================================
--- head/sys/arm64/arm64/machdep_boot.c
+++ head/sys/arm64/arm64/machdep_boot.c
@@ -208,7 +208,7 @@
#ifdef DDB
ksym_start = MD_FETCH(kmdp, MODINFOMD_SSYM, uintptr_t);
ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
- db_fetch_ksymtab(ksym_start, ksym_end);
+ db_fetch_ksymtab(ksym_start, ksym_end, 0);
#endif
return (lastaddr);
}
Index: head/sys/ddb/db_main.c
===================================================================
--- head/sys/ddb/db_main.c
+++ head/sys/ddb/db_main.c
@@ -48,6 +48,14 @@
#include <ddb/db_command.h>
#include <ddb/db_sym.h>
+struct db_private {
+ char* strtab;
+ vm_offset_t relbase;
+};
+typedef struct db_private *db_private_t;
+
+#define DB_PRIVATE(x) ((db_private_t)(x->private))
+
SYSCTL_NODE(_debug, OID_AUTO, ddb, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
"DDB settings");
@@ -64,7 +72,8 @@
* the symtab and strtab in memory. This is used when loaded from
* boot loaders different than the native one (like Xen).
*/
-vm_offset_t ksymtab, kstrtab, ksymtab_size;
+vm_offset_t ksymtab, kstrtab, ksymtab_size, ksymtab_relbase;
+static struct db_private ksymtab_private;
bool
X_db_line_at_pc(db_symtab_t *symtab, c_db_sym_t sym, char **file, int *line,
@@ -86,7 +95,8 @@
sym = (Elf_Sym *)symtab->start;
while ((char *)sym < symtab->end) {
if (sym->st_name != 0 &&
- !strcmp(symtab->private + sym->st_name, symbol))
+ !strcmp(DB_PRIVATE(symtab)->strtab +
+ sym->st_name, symbol))
return ((c_db_sym_t)sym);
sym++;
}
@@ -101,7 +111,7 @@
c_linker_sym_t lsym;
Elf_Sym *sym, *match;
unsigned long diff;
- db_addr_t stoffs;
+ db_addr_t stoffs = off;
if (symtab->private == NULL) {
if (!linker_ddb_search_symbol((caddr_t)off, &lsym, &diff)) {
@@ -110,10 +120,11 @@
}
return (NULL);
}
+ else
+ stoffs -= DB_PRIVATE(symtab)->relbase;
diff = ~0UL;
match = NULL;
- stoffs = DB_STOFFS(off);
for (sym = (Elf_Sym*)symtab->start; (char*)sym < symtab->end; sym++) {
if (sym->st_name == 0 || sym->st_shndx == SHN_UNDEF)
continue;
@@ -171,15 +182,17 @@
*valp = (db_expr_t)lval.value;
} else {
if (namep != NULL)
- *namep = (const char *)symtab->private +
+ *namep = (const char *)DB_PRIVATE(symtab)->strtab +
((const Elf_Sym *)sym)->st_name;
if (valp != NULL)
- *valp = (db_expr_t)((const Elf_Sym *)sym)->st_value;
+ *valp = (db_expr_t)((const Elf_Sym *)sym)->st_value +
+ DB_PRIVATE(symtab)->relbase;
}
}
int
-db_fetch_ksymtab(vm_offset_t ksym_start, vm_offset_t ksym_end)
+db_fetch_ksymtab(vm_offset_t ksym_start, vm_offset_t ksym_end,
+ vm_offset_t relbase)
{
Elf_Size strsz;
@@ -190,9 +203,11 @@
kstrtab = ksymtab + ksymtab_size;
strsz = *(Elf_Size*)kstrtab;
kstrtab += sizeof(Elf_Size);
+ ksymtab_relbase = relbase;
if (kstrtab + strsz > ksym_end) {
/* Sizes doesn't match, unset everything. */
- ksymtab = ksymtab_size = kstrtab = 0;
+ ksymtab = ksymtab_size = kstrtab = ksymtab_relbase
+ = 0;
}
}
@@ -209,8 +224,10 @@
db_command_init();
if (ksymtab != 0 && kstrtab != 0 && ksymtab_size != 0) {
+ ksymtab_private.strtab = (char *)kstrtab;
+ ksymtab_private.relbase = ksymtab_relbase;
db_add_symbol_table((char *)ksymtab,
- (char *)(ksymtab + ksymtab_size), "elf", (char *)kstrtab);
+ (char *)(ksymtab + ksymtab_size), "elf", (char *)&ksymtab_private);
}
db_add_symbol_table(NULL, NULL, "kld", NULL);
return (1); /* We're the default debugger. */
Index: head/sys/ddb/ddb.h
===================================================================
--- head/sys/ddb/ddb.h
+++ head/sys/ddb/ddb.h
@@ -72,10 +72,6 @@
#define DB_MAXSCRIPTRECURSION 3
#endif
-#ifndef DB_STOFFS
-#define DB_STOFFS(offs) (offs)
-#endif
-
#ifndef DB_CALL
#define DB_CALL db_fncall_generic
#else
@@ -87,7 +83,7 @@
* Most users should use db_fetch_symtab in order to set them from the
* boot loader provided values.
*/
-extern vm_offset_t ksymtab, kstrtab, ksymtab_size;
+extern vm_offset_t ksymtab, kstrtab, ksymtab_size, ksymtab_relbase;
/*
* There are three "command tables":
@@ -232,7 +228,8 @@
int db_write_bytes(vm_offset_t addr, size_t size, char *data);
void db_command_register(struct command_table *, struct command *);
void db_command_unregister(struct command_table *, struct command *);
-int db_fetch_ksymtab(vm_offset_t ksym_start, vm_offset_t ksym_end);
+int db_fetch_ksymtab(vm_offset_t ksym_start, vm_offset_t ksym_end,
+ vm_offset_t relbase);
db_cmdfcn_t db_breakpoint_cmd;
db_cmdfcn_t db_capture_cmd;
Index: head/sys/dev/ksyms/ksyms.c
===================================================================
--- head/sys/dev/ksyms/ksyms.c
+++ head/sys/dev/ksyms/ksyms.c
@@ -202,7 +202,7 @@
strsz = LINKER_STRTAB_GET(lf, &strtab);
symsz = numsyms * sizeof(Elf_Sym);
-#ifdef __powerpc__
+#ifdef RELOCATABLE_KERNEL
fixup = true;
#else
fixup = lf->id > 1;
Index: head/sys/i386/i386/machdep.c
===================================================================
--- head/sys/i386/i386/machdep.c
+++ head/sys/i386/i386/machdep.c
@@ -2180,7 +2180,7 @@
i386_kdb_init(void)
{
#ifdef DDB
- db_fetch_ksymtab(bootinfo.bi_symtab, bootinfo.bi_esymtab);
+ db_fetch_ksymtab(bootinfo.bi_symtab, bootinfo.bi_esymtab, 0);
#endif
kdb_init();
#ifdef KDB
Index: head/sys/kern/link_elf.c
===================================================================
--- head/sys/kern/link_elf.c
+++ head/sys/kern/link_elf.c
@@ -389,6 +389,21 @@
}
#ifdef RELOCATABLE_KERNEL
+/*
+ * __startkernel and __endkernel are symbols set up as relocation canaries.
+ *
+ * They are defined in locore to reference linker script symbols at the
+ * beginning and end of the LOAD area. This has the desired side effect of
+ * giving us variables that have relative relocations pointing at them, so
+ * relocation of the kernel object will cause the variables to be updated
+ * automatically by the runtime linker when we initialize.
+ *
+ * There are two main reasons to relocate the kernel:
+ * 1) If the loader needed to load the kernel at an alternate load address.
+ * 2) If the kernel is switching address spaces on machines like POWER9
+ * under Radix where the high bits of the effective address are used to
+ * differentiate between hypervisor, host, guest, and problem state.
+ */
extern vm_offset_t __startkernel, __endkernel;
#endif
@@ -427,6 +442,7 @@
ef = (elf_file_t) linker_kernel_file;
ef->preloaded = 1;
#ifdef RELOCATABLE_KERNEL
+ /* Compute relative displacement */
ef->address = (caddr_t) (__startkernel - KERNBASE);
#else
ef->address = 0;
Index: head/sys/mips/mips/machdep.c
===================================================================
--- head/sys/mips/mips/machdep.c
+++ head/sys/mips/mips/machdep.c
@@ -447,7 +447,7 @@
kernel_kseg0_end += symtabsize;
/* end of .strtab */
ksym_end = kernel_kseg0_end;
- db_fetch_ksymtab(ksym_start, ksym_end);
+ db_fetch_ksymtab(ksym_start, ksym_end, 0);
}
#endif
}
Index: head/sys/powerpc/powerpc/machdep.c
===================================================================
--- head/sys/powerpc/powerpc/machdep.c
+++ head/sys/powerpc/powerpc/machdep.c
@@ -251,7 +251,6 @@
#ifdef DDB
static void load_external_symtab(void);
-static void displace_symbol_table(vm_offset_t, vm_offset_t, vm_offset_t);
#endif
uintptr_t
@@ -360,16 +359,8 @@
ksym_end = MD_FETCH(kmdp, MODINFOMD_ESYM, uintptr_t);
ksym_sz = *(Elf_Size*)ksym_start;
- /*
- * Loader already handled displacing to the load
- * address, but we still need to displace it to the
- * DMAP.
- */
- displace_symbol_table(
- (vm_offset_t)(ksym_start + sizeof(Elf_Size)),
- ksym_sz, md_offset);
-
- db_fetch_ksymtab(ksym_start, ksym_end);
+ db_fetch_ksymtab(ksym_start, ksym_end, md_offset);
+ /* Symbols provided by loader. */
symbols_provided = true;
#endif
}
@@ -509,45 +500,22 @@
#ifdef DDB
/*
- * XXX Figure out where to move this.
+ * On powernv and some booke systems, we might not have symbols loaded via
+ * loader. However, if the user passed the kernel in as the initrd as well,
+ * we can manually load it via reinterpreting the initrd copy of the kernel.
+ *
+ * In the BOOKE case, we don't actually have a DMAP yet, so we have to use
+ * temporary maps to inspect the memory, but write DMAP addresses to the
+ * configuration variables.
*/
static void
-displace_symbol_table(vm_offset_t ksym_start,
- vm_offset_t ksym_sz, vm_offset_t displacement) {
- Elf_Sym *sym;
-
- /*
- * Relocate the symbol table to our final load address.
- */
- for (sym = (Elf_Sym *)ksym_start;
- (vm_paddr_t)sym < (ksym_start + ksym_sz);
- sym++) {
- if (sym->st_name == 0 ||
- sym->st_shndx == SHN_UNDEF ||
- sym->st_value == 0)
- continue;
- if (ELF_ST_TYPE(sym->st_info) != STT_OBJECT &&
- ELF_ST_TYPE(sym->st_info) != STT_FUNC &&
- ELF_ST_TYPE(sym->st_info) != STT_NOTYPE)
- continue;
- /* Skip relocating any implausible symbols */
- if (sym->st_value > KERNBASE)
- sym->st_value += displacement;
- }
-}
-
-/*
- * On powernv, we might not have symbols loaded via loader. However, if the
- * user passed the kernel in as the initrd as well, we can manually load it
- * via reinterpreting the initrd copy of the kernel.
- */
-static void
load_external_symtab(void) {
phandle_t chosen;
vm_paddr_t start, end;
pcell_t cell[2];
ssize_t size;
- u_char *kernelimg;
+ u_char *kernelimg; /* Temporary map */
+ u_char *kernelimg_final; /* Final location */
int i;
@@ -555,7 +523,8 @@
Elf_Phdr *phdr;
Elf_Shdr *shdr;
- vm_offset_t ksym_start, ksym_sz, kstr_start, kstr_sz;
+ vm_offset_t ksym_start, ksym_sz, kstr_start, kstr_sz,
+ ksym_start_final, kstr_start_final;
if (!hw_direct_map)
return;
@@ -587,27 +556,48 @@
if (!(end - start > 0))
return;
- kernelimg = (u_char *) PHYS_TO_DMAP(start);
-
+ kernelimg_final = (u_char *) PHYS_TO_DMAP(start);
+#ifdef AIM
+ kernelimg = kernelimg_final;
+#else /* BOOKE */
+ kernelimg = (u_char *)pmap_early_io_map(start, PAGE_SIZE);
+#endif
ehdr = (Elf_Ehdr *)kernelimg;
- if (!IS_ELF(*ehdr))
+ if (!IS_ELF(*ehdr)) {
+#ifdef BOOKE
+ pmap_early_io_unmap(start, PAGE_SIZE);
+#endif
return;
+ }
+#ifdef BOOKE
+ pmap_early_io_unmap(start, PAGE_SIZE);
+ kernelimg = (u_char *)pmap_early_io_map(start, (end - start));
+#endif
+
phdr = (Elf_Phdr *)(kernelimg + ehdr->e_phoff);
shdr = (Elf_Shdr *)(kernelimg + ehdr->e_shoff);
ksym_start = 0;
ksym_sz = 0;
+ ksym_start_final = 0;
kstr_start = 0;
kstr_sz = 0;
+ kstr_start_final = 0;
for (i = 0; i < ehdr->e_shnum; i++) {
if (shdr[i].sh_type == SHT_SYMTAB) {
ksym_start = (vm_offset_t)(kernelimg +
shdr[i].sh_offset);
+ ksym_start_final = (vm_offset_t)
+ (kernelimg_final + shdr[i].sh_offset);
ksym_sz = (vm_offset_t)(shdr[i].sh_size);
kstr_start = (vm_offset_t)(kernelimg +
shdr[shdr[i].sh_link].sh_offset);
+ kstr_start_final = (vm_offset_t)
+ (kernelimg_final +
+ shdr[shdr[i].sh_link].sh_offset);
+
kstr_sz = (vm_offset_t)
(shdr[shdr[i].sh_link].sh_size);
}
@@ -615,13 +605,22 @@
if (ksym_start != 0 && kstr_start != 0 && ksym_sz != 0 &&
kstr_sz != 0 && ksym_start < kstr_start) {
-
- displace_symbol_table(ksym_start, ksym_sz,
- (__startkernel - KERNBASE));
- ksymtab = ksym_start;
+ /*
+ * We can't use db_fetch_ksymtab() here, because we need to
+ * feed in DMAP addresses that are not mapped yet on booke.
+ *
+ * Write the variables directly, where db_init() will pick
+ * them up later, after the DMAP is up.
+ */
+ ksymtab = ksym_start_final;
ksymtab_size = ksym_sz;
- kstrtab = kstr_start;
+ kstrtab = kstr_start_final;
+ ksymtab_relbase = (__startkernel - KERNBASE);
}
+
+#ifdef BOOKE
+ pmap_early_io_unmap(start, (end - start));
+#endif
};
#endif
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Feb 23, 5:19 AM (2 h, 40 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28951263
Default Alt Text
D25223.id73423.diff (12 KB)
Attached To
Mode
D25223: [PowerPC] More relocation fixes
Attached
Detach File
Event Timeline
Log In to Comment