diff --git a/sys/conf/files b/sys/conf/files --- a/sys/conf/files +++ b/sys/conf/files @@ -771,6 +771,8 @@ ddb/db_variables.c optional ddb ddb/db_watch.c optional ddb ddb/db_write_cmd.c optional ddb +ddb/db_pprint.c optional ddb +ddb/db_ctf.c optional ddb dev/aac/aac.c optional aac dev/aac/aac_cam.c optional aacp aac dev/aac/aac_debug.c optional aac diff --git a/sys/conf/kern.post.mk b/sys/conf/kern.post.mk --- a/sys/conf/kern.post.mk +++ b/sys/conf/kern.post.mk @@ -201,7 +201,37 @@ .if ${MK_CTF} != "no" @echo ${CTFMERGE} ${CTFFLAGS} -o ${.TARGET} ... @${CTFMERGE} ${CTFFLAGS} -o ${.TARGET} ${SYSTEM_OBJS} vers.o +.if defined(SUNW_LOADABLE) + @echo "Integrating .SUNW_ctf into the kernel" +# Dump merged ctf data + @${OBJCOPY} --set-section-flags .SUNW_ctf=alloc,load,readonly ${.TARGET} + @${OBJCOPY} -O binary -j ".SUNW_ctf" ${.TARGET} ctf.raw + +# Create a temporary file to hold ctf data + @touch ctf.c + @${CC} -c ctf.c + @${OBJCOPY} --add-section .SUNW_ctf=ctf.raw ctf.o + @${OBJCOPY} --set-section-flags .SUNW_ctf=alloc,load,readonly ctf.o + +# Re-link the kernel + @echo Re-linking ${.TARGET} + ${SYSTEM_LD} ctf.o + +.if !empty(MD_ROOT_SIZE_CONFIGURED) && defined(MFS_IMAGE) + @sh ${S}/tools/embed_mfs.sh ${.TARGET} ${MFS_IMAGE} .endif + +# Remove "old" .SUNW_ctf + @${OBJCOPY} -R ".SUNW_ctf" ${.TARGET} +# Rename loadable ctf section + @objcopy --rename-section .kern_SUNW_ctf=.SUNW_ctf ${.TARGET} +# Cleanup + @rm ctf.raw + @rm ctf.o + @rm ctf.c +.endif +.endif + .if !defined(DEBUG) ${OBJCOPY} --strip-debug ${.TARGET} .endif diff --git a/sys/conf/ldscript.amd64 b/sys/conf/ldscript.amd64 --- a/sys/conf/ldscript.amd64 +++ b/sys/conf/ldscript.amd64 @@ -176,6 +176,8 @@ This way it can be mapped using non-executable large pages. */ . = ALIGN(0x200000); } + _ctf = .; + .kern_SUNW_ctf : { ctf.o(.SUNW_ctf) } _end = .; PROVIDE (end = .); . = DATA_SEGMENT_END (.); /* Stabs debugging sections. */ diff --git a/sys/kern/kern_ctf.c b/sys/kern/kern_ctf.c --- a/sys/kern/kern_ctf.c +++ b/sys/kern/kern_ctf.c @@ -290,3 +290,32 @@ return (error); } + +static int +link_elf_ctf_get_ddb(linker_file_t lf, linker_ctf_t *lc) +{ +#ifdef DDB_CTF + elf_file_t ef = (elf_file_t) lf; + + if (lf == NULL || lc == NULL) + return (EINVAL); + + if (ef->ctftab == 0 || ef->ctfcnt == 0){ + return (EINVAL); + } + + bzero(lc, sizeof(*lc)); + + lc->ctftab = ef->ctftab; + lc->ctfcnt = ef->ctfcnt; + lc->symtab = ef->ddbsymtab; + lc->nsym = ef->ddbsymcnt; + lc->strtab = ef->ddbstrtab; + lc->strcnt = ef->ddbstrcnt; + + return (0); + +#else + return (EOPNOTSUPP); +#endif +} diff --git a/sys/kern/kern_linker.c b/sys/kern/kern_linker.c --- a/sys/kern/kern_linker.c +++ b/sys/kern/kern_linker.c @@ -778,6 +778,12 @@ return (LINKER_CTF_GET(file, lc)); } +int +linker_ctf_get_ddb(linker_file_t file, linker_ctf_t *lc) +{ + return (LINKER_CTF_GET_DDB(file, lc)); +} + static int linker_file_add_dependency(linker_file_t file, linker_file_t dep) { diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -73,6 +73,11 @@ #include "linker_if.h" +#ifdef DDB_CTF +#include +#include +#endif + #define MAXSEGS 4 typedef struct elf_file { @@ -180,6 +185,7 @@ KOBJMETHOD(linker_each_function_name, link_elf_each_function_name), KOBJMETHOD(linker_each_function_nameval, link_elf_each_function_nameval), KOBJMETHOD(linker_ctf_get, link_elf_ctf_get), + KOBJMETHOD(linker_ctf_get_ddb, link_elf_ctf_get_ddb), KOBJMETHOD(linker_symtab_get, link_elf_symtab_get), KOBJMETHOD(linker_strtab_get, link_elf_strtab_get), KOBJMETHOD_END @@ -334,6 +340,76 @@ } #endif /* GDB */ +#ifdef DDB_CTF +static void +link_elf_init_kernel_ctf(elf_file_t ef) +{ + extern uint8_t _ctf; + vm_offset_t sunw_addr = + (vm_offset_t)&_ctf; /* kernel sunw_ctf ldscript symbol */ + vm_offset_t data_end_addr = + (vm_offset_t)&_end; /* data segment end ldscript symbol */ + ctf_header_t *hp; + uint8_t *ctftab; + size_t ctfcnt; + int error; + + ef->ctftab = 0; + ef->ctfcnt = 0; + + /* Check if .SUNW_ctf was loaded */ + if (sunw_addr == data_end_addr) { + printf("%s: %s: .SUNW_ctf was not loaded\n", __func__, + "kernel"); + return; + } + + printf("%s: %s: .SUNW_ctf at %p\n", __func__, "kernel", + (void *)sunw_addr); + + hp = (ctf_header_t *)sunw_addr; + + /* Sanity check. */ + if (hp->cth_magic != CTF_MAGIC) { + printf("%s: bad kernel CTF magic value\n", __func__); + return; + } + + if (hp->cth_version != CTF_VERSION_3) { + printf("%s: CTF V2 data encountered\n", __func__); + return; + } + + ctfcnt = data_end_addr - sunw_addr; + /* Uncompress if necessary */ + if (hp->cth_flags & CTF_F_COMPRESS) { + size_t decomp_size = hp->cth_stroff + hp->cth_strlen; + + /* Allocate memory for the CTF header + decompressed data */ + ctftab = malloc(decomp_size + sizeof(ctf_header_t), M_LINKER, + M_WAITOK); + + /* Copy the ctf header into the buffer */ + bcopy(hp, ctftab, sizeof(ctf_header_t)); + + /* Decompress rest of CTF data */ + error = uncompress(ctftab + sizeof(ctf_header_t), &decomp_size, + (uint8_t *)sunw_addr + sizeof(ctf_header_t), + ctfcnt - sizeof(ctf_header_t)); + if (error != Z_OK) { + printf("%s(%d): zlib uncompress returned %d\n", + __func__, __LINE__, error); + return; + } + } else { + ctftab = (uint8_t *)sunw_addr; + } + + ef->ctftab = ctftab; + ef->ctfcnt = ctfcnt; +} +#endif + /* * The kernel symbol table starts here. */ @@ -493,6 +569,10 @@ } (void)link_elf_preload_parse_symbols(ef); +#ifdef DDB_CTF + link_elf_init_kernel_ctf(ef); +#endif + #ifdef GDB r_debug.r_map = NULL; r_debug.r_brk = r_debug_state; diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c --- a/sys/kern/link_elf_obj.c +++ b/sys/kern/link_elf_obj.c @@ -170,6 +170,7 @@ KOBJMETHOD(linker_each_function_name, link_elf_each_function_name), KOBJMETHOD(linker_each_function_nameval, link_elf_each_function_nameval), KOBJMETHOD(linker_ctf_get, link_elf_ctf_get), + KOBJMETHOD(linker_ctf_get_ddb, link_elf_ctf_get_ddb), KOBJMETHOD(linker_symtab_get, link_elf_symtab_get), KOBJMETHOD(linker_strtab_get, link_elf_strtab_get), KOBJMETHOD_END diff --git a/sys/kern/linker_if.m b/sys/kern/linker_if.m --- a/sys/kern/linker_if.m +++ b/sys/kern/linker_if.m @@ -116,6 +116,11 @@ linker_ctf_t *lc; }; +METHOD int ctf_get_ddb { + linker_file_t file; + linker_ctf_t *lc; +}; + # # Get the symbol table, returning it in **symtab. Return the # number of symbols, otherwise zero. diff --git a/sys/sys/linker.h b/sys/sys/linker.h --- a/sys/sys/linker.h +++ b/sys/sys/linker.h @@ -321,6 +321,7 @@ } linker_ctf_t; int linker_ctf_get(linker_file_t, linker_ctf_t *); +int linker_ctf_get_ddb(linker_file_t, linker_ctf_t *); int elf_cpu_load_file(linker_file_t); int elf_cpu_unload_file(linker_file_t);