Index: devel/gdb/files/kgdb/kgdb-main.c =================================================================== --- devel/gdb/files/kgdb/kgdb-main.c +++ devel/gdb/files/kgdb/kgdb-main.c @@ -383,6 +383,38 @@ add_arg(&args, "-iex"); add_arg(&args, "set osabi FreeBSD/kernel"); + /* + * PowerPC kernels are fully relocatable and may be loaded + * at any memory address. In order to resolve symbols properly, + * GDB must load the kernel symbol file relative to the base + * offset where the it was loaded in memory. + */ +#ifdef __powerpc__ + { + unsigned long long offs; + + unsigned long long ppcfbsd_get_startkernel( + const char *, const char *); + + offs = ppcfbsd_get_startkernel(kernel, vmcore); + + /* Set executable file but don't load it yet. */ + add_arg(&args, "-e"); + add_arg(&args, kernel); + + add_arg(&args, "-ex"); + add_arg(&args, "set confirm off"); + + /* Load symbols at proper offsets. */ + add_arg(&args, "-ex"); + asprintf(&s, "symbol-file -o 0x%llx %s", offs, kernel); + add_arg(&args, s); + + add_arg(&args, "-ex"); + add_arg(&args, "set confirm on"); + } +#endif + /* Open the vmcore if requested. */ if (vmcore != NULL) { add_arg(&args, "-ex"); @@ -400,7 +432,10 @@ add_arg(&args, s); } + /* Avoid loading symbols twice on PowerPC. */ +#ifndef __powerpc__ add_arg(&args, kernel); +#endif /* The libgdb code uses optind too. Reset it... */ optind = 0; Index: devel/gdb/files/kgdb/ppcfbsd-kern.c =================================================================== --- devel/gdb/files/kgdb/ppcfbsd-kern.c +++ devel/gdb/files/kgdb/ppcfbsd-kern.c @@ -39,8 +39,13 @@ #include "ppc64-tdep.h" #ifdef __powerpc__ +#include +#include +#include + #include #include +#include #endif #include "kgdb.h" @@ -246,3 +251,68 @@ gdbarch_register_osabi (bfd_arch_rs6000, 0, GDB_OSABI_FREEBSD_KERNEL, ppcfbsd_kernel_init_abi); } + +#ifdef __powerpc__ + +#define KERNBASE 0x100100ULL + +/* + * Find kernel start address in memory. + */ +unsigned long long +ppcfbsd_get_startkernel(const char *kernel, const char *vmcore) +{ + struct minidumphdr hdr; + struct nlist nl[2]; + int fd = -1; + kvm_t *kd = NULL; + const char *errmsg = NULL; + + /* Look for startkernel in minidump file. */ + if (vmcore && strcmp(vmcore, _PATH_MEM) != 0) { + if ((fd = open(vmcore, O_RDONLY)) == -1) { + errmsg = "Failed to open core file"; + goto failed; + } + + if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { + errmsg = "Failed to read core file"; + goto failed; + } + + if (strcmp(hdr.magic, MINIDUMP_MAGIC) != 0) { + errmsg = "Wrong minudump magic"; + goto failed; + } + + close(fd); + return hdr.startkernel - KERNBASE; + /* For live kernels, use kvm to get kernel start address. */ + } else { + if ((kd = kvm_open(kernel, NULL, NULL, O_RDONLY, "kgdb")) == + NULL) { + errmsg = "kvm_open failed"; + goto failed; + } + + nl[0].n_name = "btext"; + nl[1].n_name = NULL; + if (kvm_nlist(kd, nl) != 0) { + errmsg = "Failed to locate kernel start symbol"; + goto failed; + } + + kvm_close(kd); + return nl[0].n_value - KERNBASE; + } + +failed: + if (fd != -1) + close(fd); + if (kd != NULL) + kvm_close(kd); + warnx("warning: %s", errmsg); + warnx("warning: Symbol resolution may not work\n"); + return 0; +} +#endif