Index: kernel/arch/abs32le/_link.ld.in
===================================================================
--- kernel/arch/abs32le/_link.ld.in	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/arch/abs32le/_link.ld.in	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -12,10 +12,9 @@
 		*(COMMON);                      /* global variables */
 
-		*(.rodata*);
+		*(.rodata .rodata.*);
+		*(.eh_frame .eh_frame.*);       /* stack unwinding data */
+		*(.eh_frame_hdr .eh_frame_hdr.*);
 		*(.sdata);
 		*(.reginfo);
-		. = ALIGN(8);
-		symbol_table = .;
-		*(symtab.*);
 	}
 	.sbss : {
@@ -26,4 +25,35 @@
 	kdata_end = .;
 
+	.comment 0 : { *(.comment); }
+	.debug_abbrev 0 : { *(.debug_abbrev); }
+	.debug_abbrev.dwo 0 : { *(	.debug_abbrev.dwo); }
+	.debug_addr 0 : { *(.debug_addr); }
+	.debug_aranges 0 : { *(.debug_aranges); }
+	.debug_cu_index 0 : { *(.debug_cu_index); }
+	.debug_frame 0 : { *(.debug_frame); }
+	.debug_frame_hdr 0 : { *(.debug_frame_hdr); }
+	.debug_info 0 : { *(.debug_info); }
+	.debug_info.dwo 0 : { *(.debug_info.dwo); }
+	.debug_line 0 : { *(.debug_line); }
+	.debug_line.dwo 0 : { *(.debug_line.dwo); }
+	.debug_line_str 0 : { *(.debug_line_str); }
+	.debug_loc 0 : { *(.debug_loc); }
+	.debug_loclists 0 : { *(.debug_loclists); }
+	.debug_loclists.dwo 0 : { *(.debug_loclists.dwo); }
+	.debug_macinfo 0 : { *(.debug_macinfo); }
+	.debug_macro 0 : { *(.debug_macro); }
+	.debug_macro.dwo 0 : { *(.debug_macro.dwo); }
+	.debug_names 0 : { *(.debug_names); }
+	.debug_pubnames 0 : { *(.debug_pubnames); }
+	.debug_pubtypes 0 : { *(.debug_pubtypes); }
+	.debug_ranges 0 : { *(.debug_ranges); }
+	.debug_rnglists 0 : { *(.debug_rnglists); }
+	.debug_str 0 : { *(.debug_str); }
+	.debug_str.dwo 0 : { *(.debug_str.dwo); }
+	.debug_str_offsets 0 : { *(.debug_str_offsets); }
+	.debug_str_offsets.dwo 0 : { *(.debug_str_offsets.dwo); }
+	.debug_tu_index 0 : { *(.debug_tu_index); }
+	.debug_types 0 : { *(.debug_types); }
+
 	/DISCARD/ : {
 		*(.mdebug*);
Index: kernel/arch/amd64/_link.ld.in
===================================================================
--- kernel/arch/amd64/_link.ld.in	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/arch/amd64/_link.ld.in	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -30,29 +30,44 @@
 		kdata_start = .;
 		*(.data);              /* initialized data */
-		*(.rodata .rodata.*);  /* string literals */
+		*(.rodata .rodata.*);
+		*(.eh_frame .eh_frame.*);       /* stack unwinding data */
+		*(.eh_frame_hdr .eh_frame_hdr.*);
 		*(COMMON);      /* global variables */
 
 		/* bss can't be omitted from the ELF image. */
 		*(.bss);        /* uninitialized static variables */
-
-		. = ALIGN(8);
-		symbol_table = .;
-		*(symtab.*);    /* Symbol table, must be LAST symbol!*/
-
 		kdata_end = .;
 	}
 
-#ifdef CONFIG_LINE_DEBUG
 	.comment 0 : { *(.comment); }
 	.debug_abbrev 0 : { *(.debug_abbrev); }
+	.debug_abbrev.dwo 0 : { *(	.debug_abbrev.dwo); }
+	.debug_addr 0 : { *(.debug_addr); }
 	.debug_aranges 0 : { *(.debug_aranges); }
+	.debug_cu_index 0 : { *(.debug_cu_index); }
+	.debug_frame 0 : { *(.debug_frame); }
+	.debug_frame_hdr 0 : { *(.debug_frame_hdr); }
 	.debug_info 0 : { *(.debug_info); }
+	.debug_info.dwo 0 : { *(.debug_info.dwo); }
 	.debug_line 0 : { *(.debug_line); }
+	.debug_line.dwo 0 : { *(.debug_line.dwo); }
+	.debug_line_str 0 : { *(.debug_line_str); }
 	.debug_loc 0 : { *(.debug_loc); }
+	.debug_loclists 0 : { *(.debug_loclists); }
+	.debug_loclists.dwo 0 : { *(.debug_loclists.dwo); }
+	.debug_macinfo 0 : { *(.debug_macinfo); }
+	.debug_macro 0 : { *(.debug_macro); }
+	.debug_macro.dwo 0 : { *(.debug_macro.dwo); }
+	.debug_names 0 : { *(.debug_names); }
 	.debug_pubnames 0 : { *(.debug_pubnames); }
 	.debug_pubtypes 0 : { *(.debug_pubtypes); }
 	.debug_ranges 0 : { *(.debug_ranges); }
+	.debug_rnglists 0 : { *(.debug_rnglists); }
 	.debug_str 0 : { *(.debug_str); }
-#endif
+	.debug_str.dwo 0 : { *(.debug_str.dwo); }
+	.debug_str_offsets 0 : { *(.debug_str_offsets); }
+	.debug_str_offsets.dwo 0 : { *(.debug_str_offsets.dwo); }
+	.debug_tu_index 0 : { *(.debug_tu_index); }
+	.debug_types 0 : { *(.debug_types); }
 
 	/DISCARD/ : {
Index: kernel/arch/arm32/_link.ld.in
===================================================================
--- kernel/arch/arm32/_link.ld.in	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/arch/arm32/_link.ld.in	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -37,10 +37,9 @@
 		*(COMMON);                      /* global variables */
 
-		*(.rodata*);
+		*(.rodata .rodata.*);
+		*(.eh_frame .eh_frame.*);       /* stack unwinding data */
+		*(.eh_frame_hdr .eh_frame_hdr.*);
 		*(.sdata);
 		*(.reginfo);
-		. = ALIGN(8);
-		symbol_table = .;
-		*(symtab.*);
 	}
 	.sbss : {
@@ -51,4 +50,35 @@
 	kdata_end = .;
 
+	.comment 0 : { *(.comment); }
+	.debug_abbrev 0 : { *(.debug_abbrev); }
+	.debug_abbrev.dwo 0 : { *(	.debug_abbrev.dwo); }
+	.debug_addr 0 : { *(.debug_addr); }
+	.debug_aranges 0 : { *(.debug_aranges); }
+	.debug_cu_index 0 : { *(.debug_cu_index); }
+	.debug_frame 0 : { *(.debug_frame); }
+	.debug_frame_hdr 0 : { *(.debug_frame_hdr); }
+	.debug_info 0 : { *(.debug_info); }
+	.debug_info.dwo 0 : { *(.debug_info.dwo); }
+	.debug_line 0 : { *(.debug_line); }
+	.debug_line.dwo 0 : { *(.debug_line.dwo); }
+	.debug_line_str 0 : { *(.debug_line_str); }
+	.debug_loc 0 : { *(.debug_loc); }
+	.debug_loclists 0 : { *(.debug_loclists); }
+	.debug_loclists.dwo 0 : { *(.debug_loclists.dwo); }
+	.debug_macinfo 0 : { *(.debug_macinfo); }
+	.debug_macro 0 : { *(.debug_macro); }
+	.debug_macro.dwo 0 : { *(.debug_macro.dwo); }
+	.debug_names 0 : { *(.debug_names); }
+	.debug_pubnames 0 : { *(.debug_pubnames); }
+	.debug_pubtypes 0 : { *(.debug_pubtypes); }
+	.debug_ranges 0 : { *(.debug_ranges); }
+	.debug_rnglists 0 : { *(.debug_rnglists); }
+	.debug_str 0 : { *(.debug_str); }
+	.debug_str.dwo 0 : { *(.debug_str.dwo); }
+	.debug_str_offsets 0 : { *(.debug_str_offsets); }
+	.debug_str_offsets.dwo 0 : { *(.debug_str_offsets.dwo); }
+	.debug_tu_index 0 : { *(.debug_tu_index); }
+	.debug_types 0 : { *(.debug_types); }
+
 	/DISCARD/ : {
 	  *(.mdebug*);
Index: kernel/arch/arm64/_link.ld.in
===================================================================
--- kernel/arch/arm64/_link.ld.in	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/arch/arm64/_link.ld.in	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -32,26 +32,41 @@
 		*(COMMON);                      /* global variables */
 
-		*(.rodata*);
-		. = ALIGN(8);
-		symbol_table = .;
-		*(symtab.*);
+		*(.rodata .rodata.*);
+		*(.eh_frame .eh_frame.*);       /* stack unwinding data */
+		*(.eh_frame_hdr .eh_frame_hdr.*);
 
 		kdata_end = .;
 	}
 
-#ifdef CONFIG_LINE_DEBUG
 	.comment 0 : { *(.comment); }
 	.debug_abbrev 0 : { *(.debug_abbrev); }
+	.debug_abbrev.dwo 0 : { *(	.debug_abbrev.dwo); }
+	.debug_addr 0 : { *(.debug_addr); }
 	.debug_aranges 0 : { *(.debug_aranges); }
+	.debug_cu_index 0 : { *(.debug_cu_index); }
 	.debug_frame 0 : { *(.debug_frame); }
+	.debug_frame_hdr 0 : { *(.debug_frame_hdr); }
 	.debug_info 0 : { *(.debug_info); }
+	.debug_info.dwo 0 : { *(.debug_info.dwo); }
 	.debug_line 0 : { *(.debug_line); }
+	.debug_line.dwo 0 : { *(.debug_line.dwo); }
+	.debug_line_str 0 : { *(.debug_line_str); }
 	.debug_loc 0 : { *(.debug_loc); }
+	.debug_loclists 0 : { *(.debug_loclists); }
+	.debug_loclists.dwo 0 : { *(.debug_loclists.dwo); }
 	.debug_macinfo 0 : { *(.debug_macinfo); }
+	.debug_macro 0 : { *(.debug_macro); }
+	.debug_macro.dwo 0 : { *(.debug_macro.dwo); }
+	.debug_names 0 : { *(.debug_names); }
 	.debug_pubnames 0 : { *(.debug_pubnames); }
 	.debug_pubtypes 0 : { *(.debug_pubtypes); }
 	.debug_ranges 0 : { *(.debug_ranges); }
+	.debug_rnglists 0 : { *(.debug_rnglists); }
 	.debug_str 0 : { *(.debug_str); }
-#endif
+	.debug_str.dwo 0 : { *(.debug_str.dwo); }
+	.debug_str_offsets 0 : { *(.debug_str_offsets); }
+	.debug_str_offsets.dwo 0 : { *(.debug_str_offsets.dwo); }
+	.debug_tu_index 0 : { *(.debug_tu_index); }
+	.debug_types 0 : { *(.debug_types); }
 
 	/DISCARD/ : {
Index: kernel/arch/ia32/_link.ld.in
===================================================================
--- kernel/arch/ia32/_link.ld.in	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/arch/ia32/_link.ld.in	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -29,28 +29,44 @@
 		kdata_start = .;
 		*(.data);               /* initialized data */
-		*(.rodata .rodata.*);   /* string literals */
+		*(.rodata .rodata.*);
+		*(.eh_frame .eh_frame.*);       /* stack unwinding data */
+		*(.eh_frame_hdr .eh_frame_hdr.*);
 		*(COMMON);              /* global variables */
 
 		/* bss can't be omitted from the ELF image. */
 		*(.bss);                /* uninitialized static variables */
-
-		. = ALIGN(8);
-		symbol_table = .;
-		*(symtab.*);            /* Symbol table, must be LAST symbol! */
 		kdata_end = .;
 	}
 
-#ifdef CONFIG_LINE_DEBUG
 	.comment 0 : { *(.comment); }
 	.debug_abbrev 0 : { *(.debug_abbrev); }
+	.debug_abbrev.dwo 0 : { *(	.debug_abbrev.dwo); }
+	.debug_addr 0 : { *(.debug_addr); }
 	.debug_aranges 0 : { *(.debug_aranges); }
+	.debug_cu_index 0 : { *(.debug_cu_index); }
+	.debug_frame 0 : { *(.debug_frame); }
+	.debug_frame_hdr 0 : { *(.debug_frame_hdr); }
 	.debug_info 0 : { *(.debug_info); }
+	.debug_info.dwo 0 : { *(.debug_info.dwo); }
 	.debug_line 0 : { *(.debug_line); }
+	.debug_line.dwo 0 : { *(.debug_line.dwo); }
+	.debug_line_str 0 : { *(.debug_line_str); }
 	.debug_loc 0 : { *(.debug_loc); }
+	.debug_loclists 0 : { *(.debug_loclists); }
+	.debug_loclists.dwo 0 : { *(.debug_loclists.dwo); }
+	.debug_macinfo 0 : { *(.debug_macinfo); }
+	.debug_macro 0 : { *(.debug_macro); }
+	.debug_macro.dwo 0 : { *(.debug_macro.dwo); }
+	.debug_names 0 : { *(.debug_names); }
 	.debug_pubnames 0 : { *(.debug_pubnames); }
 	.debug_pubtypes 0 : { *(.debug_pubtypes); }
 	.debug_ranges 0 : { *(.debug_ranges); }
+	.debug_rnglists 0 : { *(.debug_rnglists); }
 	.debug_str 0 : { *(.debug_str); }
-#endif
+	.debug_str.dwo 0 : { *(.debug_str.dwo); }
+	.debug_str_offsets 0 : { *(.debug_str_offsets); }
+	.debug_str_offsets.dwo 0 : { *(.debug_str_offsets.dwo); }
+	.debug_tu_index 0 : { *(.debug_tu_index); }
+	.debug_types 0 : { *(.debug_types); }
 
 	/DISCARD/ : {
Index: kernel/arch/ia64/_link.ld.in
===================================================================
--- kernel/arch/ia64/_link.ld.in	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/arch/ia64/_link.ld.in	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -24,5 +24,7 @@
 		kdata_start = .;
 		*(K_DATA_START)
-		*(.rodata .rodata.*)
+		*(.rodata .rodata.*);
+		*(.eh_frame .eh_frame.*);       /* stack unwinding data */
+		*(.eh_frame_hdr .eh_frame_hdr.*);
 		*(.opd)
 		*(.data .data.*)
@@ -34,11 +36,37 @@
 		*(.bss)
 		*(COMMON);
-
-		. = ALIGN(8);
-		symbol_table = .;
-		*(symtab.*);            /* Symbol table, must be LAST symbol!*/
-
 		kdata_end = .;
 	}
+
+	.comment 0 : { *(.comment); }
+	.debug_abbrev 0 : { *(.debug_abbrev); }
+	.debug_abbrev.dwo 0 : { *(	.debug_abbrev.dwo); }
+	.debug_addr 0 : { *(.debug_addr); }
+	.debug_aranges 0 : { *(.debug_aranges); }
+	.debug_cu_index 0 : { *(.debug_cu_index); }
+	.debug_frame 0 : { *(.debug_frame); }
+	.debug_frame_hdr 0 : { *(.debug_frame_hdr); }
+	.debug_info 0 : { *(.debug_info); }
+	.debug_info.dwo 0 : { *(.debug_info.dwo); }
+	.debug_line 0 : { *(.debug_line); }
+	.debug_line.dwo 0 : { *(.debug_line.dwo); }
+	.debug_line_str 0 : { *(.debug_line_str); }
+	.debug_loc 0 : { *(.debug_loc); }
+	.debug_loclists 0 : { *(.debug_loclists); }
+	.debug_loclists.dwo 0 : { *(.debug_loclists.dwo); }
+	.debug_macinfo 0 : { *(.debug_macinfo); }
+	.debug_macro 0 : { *(.debug_macro); }
+	.debug_macro.dwo 0 : { *(.debug_macro.dwo); }
+	.debug_names 0 : { *(.debug_names); }
+	.debug_pubnames 0 : { *(.debug_pubnames); }
+	.debug_pubtypes 0 : { *(.debug_pubtypes); }
+	.debug_ranges 0 : { *(.debug_ranges); }
+	.debug_rnglists 0 : { *(.debug_rnglists); }
+	.debug_str 0 : { *(.debug_str); }
+	.debug_str.dwo 0 : { *(.debug_str.dwo); }
+	.debug_str_offsets 0 : { *(.debug_str_offsets); }
+	.debug_str_offsets.dwo 0 : { *(.debug_str_offsets.dwo); }
+	.debug_tu_index 0 : { *(.debug_tu_index); }
+	.debug_types 0 : { *(.debug_types); }
 
 	/DISCARD/ : {
Index: kernel/arch/mips32/_link.ld.in
===================================================================
--- kernel/arch/mips32/_link.ld.in	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/arch/mips32/_link.ld.in	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -34,5 +34,7 @@
 		kdata_start = .;
 		*(.data);                       /* initialized data */
-		*(.rodata*);
+		*(.rodata .rodata.*);
+		*(.eh_frame .eh_frame.*);       /* stack unwinding data */
+		*(.eh_frame_hdr .eh_frame_hdr.*);
 		*(.sdata);
 		*(.reginfo);
@@ -41,7 +43,4 @@
 		*(.bss);                        /* uninitialized static variables */
 		*(COMMON);                      /* global variables */
-		. = ALIGN(8);
-		symbol_table = .;
-		*(symtab.*);
 	}
 	_gp = . + 0x8000;
@@ -50,4 +49,35 @@
 
 	kdata_end = .;
+
+	.comment 0 : { *(.comment); }
+	.debug_abbrev 0 : { *(.debug_abbrev); }
+	.debug_abbrev.dwo 0 : { *(	.debug_abbrev.dwo); }
+	.debug_addr 0 : { *(.debug_addr); }
+	.debug_aranges 0 : { *(.debug_aranges); }
+	.debug_cu_index 0 : { *(.debug_cu_index); }
+	.debug_frame 0 : { *(.debug_frame); }
+	.debug_frame_hdr 0 : { *(.debug_frame_hdr); }
+	.debug_info 0 : { *(.debug_info); }
+	.debug_info.dwo 0 : { *(.debug_info.dwo); }
+	.debug_line 0 : { *(.debug_line); }
+	.debug_line.dwo 0 : { *(.debug_line.dwo); }
+	.debug_line_str 0 : { *(.debug_line_str); }
+	.debug_loc 0 : { *(.debug_loc); }
+	.debug_loclists 0 : { *(.debug_loclists); }
+	.debug_loclists.dwo 0 : { *(.debug_loclists.dwo); }
+	.debug_macinfo 0 : { *(.debug_macinfo); }
+	.debug_macro 0 : { *(.debug_macro); }
+	.debug_macro.dwo 0 : { *(.debug_macro.dwo); }
+	.debug_names 0 : { *(.debug_names); }
+	.debug_pubnames 0 : { *(.debug_pubnames); }
+	.debug_pubtypes 0 : { *(.debug_pubtypes); }
+	.debug_ranges 0 : { *(.debug_ranges); }
+	.debug_rnglists 0 : { *(.debug_rnglists); }
+	.debug_str 0 : { *(.debug_str); }
+	.debug_str.dwo 0 : { *(.debug_str.dwo); }
+	.debug_str_offsets 0 : { *(.debug_str_offsets); }
+	.debug_str_offsets.dwo 0 : { *(.debug_str_offsets.dwo); }
+	.debug_tu_index 0 : { *(.debug_tu_index); }
+	.debug_types 0 : { *(.debug_types); }
 
 	/DISCARD/ : {
Index: kernel/arch/ppc32/_link.ld.in
===================================================================
--- kernel/arch/ppc32/_link.ld.in	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/arch/ppc32/_link.ld.in	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -34,4 +34,6 @@
 		*(K_DATA_START);
 		*(.rodata .rodata.*);
+		*(.eh_frame .eh_frame.*);       /* stack unwinding data */
+		*(.eh_frame_hdr .eh_frame_hdr.*);
 		*(.data);       /* initialized data */
 		*(.sdata);
@@ -40,11 +42,37 @@
 		*(.bss);        /* uninitialized static variables */
 		*(COMMON);      /* global variables */
-
-		. = ALIGN(8);
-		symbol_table = .;
-		*(symtab.*);    /* Symbol table, must be LAST symbol!*/
-
 		kdata_end = .;
 	}
+
+	.comment 0 : { *(.comment); }
+	.debug_abbrev 0 : { *(.debug_abbrev); }
+	.debug_abbrev.dwo 0 : { *(	.debug_abbrev.dwo); }
+	.debug_addr 0 : { *(.debug_addr); }
+	.debug_aranges 0 : { *(.debug_aranges); }
+	.debug_cu_index 0 : { *(.debug_cu_index); }
+	.debug_frame 0 : { *(.debug_frame); }
+	.debug_frame_hdr 0 : { *(.debug_frame_hdr); }
+	.debug_info 0 : { *(.debug_info); }
+	.debug_info.dwo 0 : { *(.debug_info.dwo); }
+	.debug_line 0 : { *(.debug_line); }
+	.debug_line.dwo 0 : { *(.debug_line.dwo); }
+	.debug_line_str 0 : { *(.debug_line_str); }
+	.debug_loc 0 : { *(.debug_loc); }
+	.debug_loclists 0 : { *(.debug_loclists); }
+	.debug_loclists.dwo 0 : { *(.debug_loclists.dwo); }
+	.debug_macinfo 0 : { *(.debug_macinfo); }
+	.debug_macro 0 : { *(.debug_macro); }
+	.debug_macro.dwo 0 : { *(.debug_macro.dwo); }
+	.debug_names 0 : { *(.debug_names); }
+	.debug_pubnames 0 : { *(.debug_pubnames); }
+	.debug_pubtypes 0 : { *(.debug_pubtypes); }
+	.debug_ranges 0 : { *(.debug_ranges); }
+	.debug_rnglists 0 : { *(.debug_rnglists); }
+	.debug_str 0 : { *(.debug_str); }
+	.debug_str.dwo 0 : { *(.debug_str.dwo); }
+	.debug_str_offsets 0 : { *(.debug_str_offsets); }
+	.debug_str_offsets.dwo 0 : { *(.debug_str_offsets.dwo); }
+	.debug_tu_index 0 : { *(.debug_tu_index); }
+	.debug_types 0 : { *(.debug_types); }
 
 	/DISCARD/ : {
Index: kernel/arch/riscv64/_link.ld.in
===================================================================
--- kernel/arch/riscv64/_link.ld.in	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/arch/riscv64/_link.ld.in	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -24,5 +24,7 @@
 		kdata_start = .;
 		*(.data);                       /* initialized data */
-		*(.rodata*);
+		*(.rodata .rodata.*);
+		*(.eh_frame .eh_frame.*);       /* stack unwinding data */
+		*(.eh_frame_hdr .eh_frame_hdr.*);
 		*(.sdata);
 		*(.reginfo);
@@ -31,9 +33,37 @@
 		*(.bss);                        /* uninitialized static variables */
 		*(COMMON);                      /* global variables */
-		. = ALIGN(8);
-		symbol_table = .;
-		*(symtab.*);
 		kdata_end = .;
 	}
+
+	.comment 0 : { *(.comment); }
+	.debug_abbrev 0 : { *(.debug_abbrev); }
+	.debug_abbrev.dwo 0 : { *(	.debug_abbrev.dwo); }
+	.debug_addr 0 : { *(.debug_addr); }
+	.debug_aranges 0 : { *(.debug_aranges); }
+	.debug_cu_index 0 : { *(.debug_cu_index); }
+	.debug_frame 0 : { *(.debug_frame); }
+	.debug_frame_hdr 0 : { *(.debug_frame_hdr); }
+	.debug_info 0 : { *(.debug_info); }
+	.debug_info.dwo 0 : { *(.debug_info.dwo); }
+	.debug_line 0 : { *(.debug_line); }
+	.debug_line.dwo 0 : { *(.debug_line.dwo); }
+	.debug_line_str 0 : { *(.debug_line_str); }
+	.debug_loc 0 : { *(.debug_loc); }
+	.debug_loclists 0 : { *(.debug_loclists); }
+	.debug_loclists.dwo 0 : { *(.debug_loclists.dwo); }
+	.debug_macinfo 0 : { *(.debug_macinfo); }
+	.debug_macro 0 : { *(.debug_macro); }
+	.debug_macro.dwo 0 : { *(.debug_macro.dwo); }
+	.debug_names 0 : { *(.debug_names); }
+	.debug_pubnames 0 : { *(.debug_pubnames); }
+	.debug_pubtypes 0 : { *(.debug_pubtypes); }
+	.debug_ranges 0 : { *(.debug_ranges); }
+	.debug_rnglists 0 : { *(.debug_rnglists); }
+	.debug_str 0 : { *(.debug_str); }
+	.debug_str.dwo 0 : { *(.debug_str.dwo); }
+	.debug_str_offsets 0 : { *(.debug_str_offsets); }
+	.debug_str_offsets.dwo 0 : { *(.debug_str_offsets.dwo); }
+	.debug_tu_index 0 : { *(.debug_tu_index); }
+	.debug_types 0 : { *(.debug_types); }
 
 	/DISCARD/ : {
Index: kernel/arch/sparc64/_link.ld.in
===================================================================
--- kernel/arch/sparc64/_link.ld.in	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/arch/sparc64/_link.ld.in	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -23,4 +23,6 @@
 		*(K_DATA_START)
 		*(.rodata .rodata.*);
+		*(.eh_frame .eh_frame.*);       /* stack unwinding data */
+		*(.eh_frame_hdr .eh_frame_hdr.*);
 		*(.data);                   /* initialized data */
 		*(.sdata);
@@ -30,11 +32,37 @@
 		*(.bss);                    /* uninitialized static variables */
 		*(COMMON);                  /* global variables */
-
-		. = ALIGN(8);
-		symbol_table = .;
-		*(symtab.*);                /* Symbol table, must be LAST symbol!*/
-
 		kdata_end = .;
 	}
+
+	.comment 0 : { *(.comment); }
+	.debug_abbrev 0 : { *(.debug_abbrev); }
+	.debug_abbrev.dwo 0 : { *(	.debug_abbrev.dwo); }
+	.debug_addr 0 : { *(.debug_addr); }
+	.debug_aranges 0 : { *(.debug_aranges); }
+	.debug_cu_index 0 : { *(.debug_cu_index); }
+	.debug_frame 0 : { *(.debug_frame); }
+	.debug_frame_hdr 0 : { *(.debug_frame_hdr); }
+	.debug_info 0 : { *(.debug_info); }
+	.debug_info.dwo 0 : { *(.debug_info.dwo); }
+	.debug_line 0 : { *(.debug_line); }
+	.debug_line.dwo 0 : { *(.debug_line.dwo); }
+	.debug_line_str 0 : { *(.debug_line_str); }
+	.debug_loc 0 : { *(.debug_loc); }
+	.debug_loclists 0 : { *(.debug_loclists); }
+	.debug_loclists.dwo 0 : { *(.debug_loclists.dwo); }
+	.debug_macinfo 0 : { *(.debug_macinfo); }
+	.debug_macro 0 : { *(.debug_macro); }
+	.debug_macro.dwo 0 : { *(.debug_macro.dwo); }
+	.debug_names 0 : { *(.debug_names); }
+	.debug_pubnames 0 : { *(.debug_pubnames); }
+	.debug_pubtypes 0 : { *(.debug_pubtypes); }
+	.debug_ranges 0 : { *(.debug_ranges); }
+	.debug_rnglists 0 : { *(.debug_rnglists); }
+	.debug_str 0 : { *(.debug_str); }
+	.debug_str.dwo 0 : { *(.debug_str.dwo); }
+	.debug_str_offsets 0 : { *(.debug_str_offsets); }
+	.debug_str_offsets.dwo 0 : { *(.debug_str_offsets.dwo); }
+	.debug_tu_index 0 : { *(.debug_tu_index); }
+	.debug_types 0 : { *(.debug_types); }
 
 	/DISCARD/ : {
Index: kernel/generic/include/debug.h
===================================================================
--- kernel/generic/include/debug.h	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/generic/include/debug.h	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -37,5 +37,4 @@
 
 #include <log.h>
-#include <symtab_lookup.h>
 #include <printf/verify.h>
 
@@ -43,5 +42,5 @@
 
 /* An empty printf function to ensure syntactic correctness of disabled debug prints. */
-_HELENOS_PRINTF_ATTRIBUTE(1, 2)
+static inline void dummy_printf(const char *fmt, ...) _HELENOS_PRINTF_ATTRIBUTE(1, 2);
 static inline void dummy_printf(const char *fmt, ...)
 {
Index: kernel/generic/include/debug/register.h
===================================================================
--- kernel/generic/include/debug/register.h	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
+++ kernel/generic/include/debug/register.h	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2023 Jiří Zárevúcky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DEBUG_REGISTER_H_
+#define DEBUG_REGISTER_H_
+
+/** Accepts data of an ELF file containing debug sections. */
+void register_debug_data(const void *data, size_t data_size);
+
+#endif /* DEBUG_REGISTER_H_ */
Index: kernel/generic/include/debug/sections.h
===================================================================
--- kernel/generic/include/debug/sections.h	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
+++ kernel/generic/include/debug/sections.h	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2023 Jiří Zárevúcky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef DEBUG_SECTIONS_H_
+#define DEBUG_SECTIONS_H_
+
+#include <abi/elf.h>
+#include <stddef.h>
+
+extern const void *debug_aranges;
+extern size_t debug_aranges_size;
+
+extern const void *debug_info;
+extern size_t debug_info_size;
+
+extern const void *debug_abbrev;
+extern size_t debug_abbrev_size;
+
+extern const void *debug_line;
+extern size_t debug_line_size;
+
+extern const char *debug_str;
+extern size_t debug_str_size;
+
+extern const char *debug_line_str;
+extern size_t debug_line_str_size;
+
+extern const void *debug_rnglists;
+extern size_t debug_rnglists_size;
+
+extern const void *eh_frame_hdr;
+extern size_t eh_frame_hdr_size;
+
+extern const void *eh_frame;
+extern size_t eh_frame_size;
+
+extern const elf_symbol_t *symtab;
+extern size_t symtab_size;
+
+extern const char *strtab;
+extern size_t strtab_size;
+
+#endif /* DEBUG_SECTIONS_H_ */
Index: kernel/generic/include/symtab.h
===================================================================
--- kernel/generic/include/symtab.h	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/generic/include/symtab.h	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -36,9 +36,11 @@
 #define KERN_SYMTAB_H_
 
-#include <symtab_lookup.h>
-#include <console/chardev.h>
+#include <typedefs.h>
 
 extern void symtab_print_search(const char *);
 extern const char *symtab_hints_enum(const char *, const char **, void **);
+extern const char *symtab_fmt_name_lookup(uintptr_t);
+extern errno_t symtab_addr_lookup(const char *, uintptr_t *);
+extern const char *symtab_name_lookup(uintptr_t, uintptr_t *);
 
 #endif
Index: kernel/generic/include/symtab_lookup.h
===================================================================
--- kernel/generic/include/symtab_lookup.h	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ 	(revision )
@@ -1,63 +1,0 @@
-/*
- * Copyright (c) 2005 Ondrej Palkovsky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kernel_generic
- * @{
- */
-/** @file
- */
-
-#ifndef KERN_SYMTAB_LOOKUP_H_
-#define KERN_SYMTAB_LOOKUP_H_
-
-#include <typedefs.h>
-
-#define MAX_SYMBOL_NAME  64
-
-struct symtab_entry {
-	uint64_t address_le;
-	char symbol_name[MAX_SYMBOL_NAME];
-};
-
-extern errno_t symtab_name_lookup(uintptr_t, const char **, uintptr_t *);
-extern const char *symtab_fmt_name_lookup(uintptr_t);
-extern errno_t symtab_addr_lookup(const char *, uintptr_t *);
-
-#ifdef CONFIG_SYMTAB
-
-/** Symtable linked together by build process
- *
- */
-extern struct symtab_entry symbol_table[];
-
-#endif /* CONFIG_SYMTAB */
-
-#endif
-
-/** @}
- */
Index: kernel/generic/meson.build
===================================================================
--- kernel/generic/meson.build	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/generic/meson.build	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -46,6 +46,7 @@
 	'src/cpu/cpu_mask.c',
 	'src/ddi/irq.c',
-	'src/debug/debug.c',
 	'src/debug/panic.c',
+	'src/debug/profile.c',
+	'src/debug/sections.c',
 	'src/debug/stacktrace.c',
 	'src/debug/symtab.c',
Index: kernel/generic/src/console/kconsole.c
===================================================================
--- kernel/generic/src/console/kconsole.c	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/generic/src/console/kconsole.c	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -85,4 +85,6 @@
 SPINLOCK_INITIALIZE(cmd_lock);  /**< Lock protecting command list. */
 LIST_INITIALIZE(cmd_list);      /**< Command list. */
+
+#define MAX_SYMBOL_NAME 64
 
 static char32_t history[KCONSOLE_HISTORY][MAX_CMDLINE] = { };
Index: kernel/generic/src/debug/debug.c
===================================================================
--- kernel/generic/src/debug/debug.c	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ 	(revision )
@@ -1,78 +1,0 @@
-/*
- * Copyright (c) 2010 Martin Decky
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * - Redistributions of source code must retain the above copyright
- *   notice, this list of conditions and the following disclaimer.
- * - Redistributions in binary form must reproduce the above copyright
- *   notice, this list of conditions and the following disclaimer in the
- *   documentation and/or other materials provided with the distribution.
- * - The name of the author may not be used to endorse or promote products
- *   derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
- * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
- * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
- * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
- * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/** @addtogroup kernel_generic_debug
- * @{
- */
-
-/**
- * @file
- * @brief Kernel instrumentation functions.
- */
-
-#ifdef CONFIG_TRACE
-
-#include <debug.h>
-#include <symtab.h>
-#include <errno.h>
-#include <stdio.h>
-
-void __cyg_profile_func_enter(void *fn, void *call_site)
-{
-	const char *fn_sym = symtab_fmt_name_lookup((uintptr_t) fn);
-
-	const char *call_site_sym;
-	uintptr_t call_site_off;
-
-	if (symtab_name_lookup((uintptr_t) call_site, &call_site_sym,
-	    &call_site_off) == EOK)
-		printf("%s()+%p->%s()\n", call_site_sym,
-		    (void *) call_site_off, fn_sym);
-	else
-		printf("->%s()\n", fn_sym);
-}
-
-void __cyg_profile_func_exit(void *fn, void *call_site)
-{
-	const char *fn_sym = symtab_fmt_name_lookup((uintptr_t) fn);
-
-	const char *call_site_sym;
-	uintptr_t call_site_off;
-
-	if (symtab_name_lookup((uintptr_t) call_site, &call_site_sym,
-	    &call_site_off) == EOK)
-		printf("%s()+%p<-%s()\n", call_site_sym,
-		    (void *) call_site_off, fn_sym);
-	else
-		printf("<-%s()\n", fn_sym);
-}
-
-#endif /* CONFIG_TRACE */
-
-/** @}
- */
Index: kernel/generic/src/debug/profile.c
===================================================================
--- kernel/generic/src/debug/profile.c	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
+++ kernel/generic/src/debug/profile.c	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2010 Martin Decky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @addtogroup kernel_generic_debug
+ * @{
+ */
+
+/**
+ * @file
+ * @brief Kernel instrumentation functions.
+ */
+
+#ifdef CONFIG_TRACE
+
+#include <debug.h>
+#include <symtab.h>
+#include <errno.h>
+#include <stdio.h>
+
+void __cyg_profile_func_enter(void *fn, void *call_site)
+{
+	const char *fn_sym = symtab_fmt_name_lookup((uintptr_t) fn);
+
+	const char *call_site_sym;
+	uintptr_t call_site_off;
+
+	if (symtab_name_lookup((uintptr_t) call_site, &call_site_sym,
+	    &call_site_off) == EOK)
+		printf("%s()+%p->%s()\n", call_site_sym,
+		    (void *) call_site_off, fn_sym);
+	else
+		printf("->%s()\n", fn_sym);
+}
+
+void __cyg_profile_func_exit(void *fn, void *call_site)
+{
+	const char *fn_sym = symtab_fmt_name_lookup((uintptr_t) fn);
+
+	const char *call_site_sym;
+	uintptr_t call_site_off;
+
+	if (symtab_name_lookup((uintptr_t) call_site, &call_site_sym,
+	    &call_site_off) == EOK)
+		printf("%s()+%p<-%s()\n", call_site_sym,
+		    (void *) call_site_off, fn_sym);
+	else
+		printf("<-%s()\n", fn_sym);
+}
+
+#endif /* CONFIG_TRACE */
+
+/** @}
+ */
Index: kernel/generic/src/debug/sections.c
===================================================================
--- kernel/generic/src/debug/sections.c	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
+++ kernel/generic/src/debug/sections.c	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2023 Jiří Zárevúcky
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <debug/sections.h>
+#include <debug/register.h>
+
+#include <stdio.h>
+#include <str.h>
+
+const void *debug_aranges = NULL;
+size_t debug_aranges_size = 0;
+
+const void *debug_info = NULL;
+size_t debug_info_size = 0;
+
+const void *debug_abbrev = NULL;
+size_t debug_abbrev_size = 0;
+
+const void *debug_line = NULL;
+size_t debug_line_size = 0;
+
+const char *debug_str = NULL;
+size_t debug_str_size = 0;
+
+const char *debug_line_str = NULL;
+size_t debug_line_str_size = 0;
+
+const void *debug_rnglists = NULL;
+size_t debug_rnglists_size = 0;
+
+// TODO: get this from the program image
+const void *eh_frame_hdr = NULL;
+size_t eh_frame_hdr_size = 0;
+
+const void *eh_frame = NULL;
+size_t eh_frame_size = 0;
+
+const elf_symbol_t *symtab = NULL;
+size_t symtab_size = 0;
+
+const char *strtab = NULL;
+size_t strtab_size = 0;
+
+struct section_manifest {
+	const char *name;
+	const void **address_field;
+	size_t *size_field;
+};
+
+#define section(name) { "." #name, (const void **)&name, &name##_size }
+
+static const struct section_manifest manifest[] = {
+	section(debug_aranges),
+	section(debug_info),
+	section(debug_abbrev),
+	section(debug_line),
+	section(debug_str),
+	section(debug_line_str),
+	section(debug_rnglists),
+	section(eh_frame_hdr),
+	section(eh_frame),
+	section(symtab),
+	section(strtab),
+};
+
+#undef section
+
+static const size_t manifest_len = sizeof(manifest) / sizeof(struct section_manifest);
+
+void register_debug_data(const void *data, size_t data_size)
+{
+	const void *data_end = data + data_size;
+
+	/*
+	 * While this data is technically "trusted", insofar as it is provided
+	 * by the bootloader, it's not critical, so we try to make sure malformed or
+	 * misconfigured debug data doesn't crash the kernel.
+	 */
+
+	if (data_size < sizeof(elf_header_t)) {
+		printf("bad debug data: too short\n");
+		return;
+	}
+
+	if (((uintptr_t) data) % 8 != 0) {
+		printf("bad debug data: unaligned input\n");
+		return;
+	}
+
+	const elf_header_t *hdr = data;
+
+	if (hdr->e_ident[0] != ELFMAG0 || hdr->e_ident[1] != ELFMAG1 ||
+	    hdr->e_ident[2] != ELFMAG2 || hdr->e_ident[3] != ELFMAG3) {
+		printf("bad debug data: wrong ELF magic bytes\n");
+		return;
+	}
+
+	if (hdr->e_shentsize != sizeof(elf_section_header_t)) {
+		printf("bad debug data: wrong e_shentsize\n");
+		return;
+	}
+
+	/* Get section header table. */
+	const elf_section_header_t *shdr = data + hdr->e_shoff;
+	size_t shdr_len = hdr->e_shnum;
+
+	if ((void *) &shdr[shdr_len] > data_end) {
+		printf("bad debug data: truncated section header table\n");
+		return;
+	}
+
+	if (hdr->e_shstrndx >= shdr_len) {
+		printf("bad debug data: string table index out of range\n");
+		return;
+	}
+
+	/* Get data on section name string table. */
+	const elf_section_header_t *shstr = &shdr[hdr->e_shstrndx];
+	const char *shstrtab = data + shstr->sh_offset;
+	size_t shstrtab_size = shstr->sh_size;
+
+	if ((void *) shstrtab + shstrtab_size > data_end) {
+		printf("bad debug data: truncated string table\n");
+		return;
+	}
+
+	/* Check NUL-terminator. */
+	while (shstrtab_size > 0 && shstrtab[shstrtab_size - 1] != 0) {
+		shstrtab_size--;
+	}
+
+	if (shstrtab_size == 0) {
+		printf("bad debug data: empty or non-null-terminated string table\n");
+		return;
+	}
+
+	/* List all present sections. */
+	for (size_t i = 0; i < shdr_len; i++) {
+		if (shdr[i].sh_type == SHT_NULL || shdr[i].sh_type == SHT_NOBITS)
+			continue;
+
+		if (shdr[i].sh_name >= shstrtab_size) {
+			printf("bad debug data: string table index out of range\n");
+			return;
+		}
+
+		const char *name = shstrtab + shdr[i].sh_name;
+		size_t offset = shdr[i].sh_offset;
+		size_t size = shdr[i].sh_size;
+
+		printf("section '%s': offset %zd (%zd bytes)\n", name, offset, size);
+
+		if (data + offset + size > data_end) {
+			printf("bad debug data: truncated section %s\n", name);
+			continue;
+		}
+
+		for (size_t i = 0; i < manifest_len; i++) {
+			if (str_cmp(manifest[i].name, name) == 0) {
+				*manifest[i].address_field = data + offset;
+				*manifest[i].size_field = size;
+				break;
+			}
+		}
+	}
+
+	/* Check NUL-terminator in .strtab, .debug_str and .debug_line_str */
+	while (strtab_size > 0 && strtab[strtab_size - 1] != 0) {
+		strtab_size--;
+	}
+
+	while (debug_str_size > 0 && debug_str[debug_str_size - 1] != 0) {
+		debug_str_size--;
+	}
+
+	while (debug_line_str_size > 0 && debug_str[debug_line_str_size - 1] != 0) {
+		debug_line_str_size--;
+	}
+}
Index: kernel/generic/src/debug/stacktrace.c
===================================================================
--- kernel/generic/src/debug/stacktrace.c	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/generic/src/debug/stacktrace.c	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -106,5 +106,8 @@
 kernel_symbol_resolve(uintptr_t addr, const char **sp, uintptr_t *op)
 {
-	return (symtab_name_lookup(addr, sp, op) == 0);
+	uintptr_t symbol_addr = 0;
+	*sp = symtab_name_lookup(addr, &symbol_addr);
+	*op = addr - symbol_addr;
+	return symbol_addr != 0;
 }
 
Index: kernel/generic/src/debug/symtab.c
===================================================================
--- kernel/generic/src/debug/symtab.c	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/generic/src/debug/symtab.c	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -44,39 +44,76 @@
 #include <console/prompt.h>
 
-/** Get name of a symbol that seems most likely to correspond to address.
- *
- * @param addr   Address.
- * @param name   Place to store pointer to the symbol name.
- * @param offset Place to store offset from the symbol address.
- *
- * @return Zero on success or an error code, ENOENT if not found,
- *         ENOTSUP if symbol table not available.
- *
- */
-errno_t symtab_name_lookup(uintptr_t addr, const char **name, uintptr_t *offset)
-{
-#ifdef CONFIG_SYMTAB
-	size_t i;
-
-	for (i = 1; symbol_table[i].address_le; i++) {
-		if (addr < uint64_t_le2host(symbol_table[i].address_le))
+#include <abi/elf.h>
+#include <debug/sections.h>
+
+static inline size_t symtab_len()
+{
+	return symtab_size / sizeof(elf_symbol_t);
+}
+
+static inline const char *symtab_entry_name(int entry)
+{
+	size_t index = symtab[entry].st_name;
+
+	if (index >= strtab_size)
+		return NULL;
+
+	return strtab + index;
+}
+
+static inline size_t symtab_next(size_t i)
+{
+	for (; i < symtab_len(); i++) {
+		const char *name = symtab_entry_name(i);
+		int st_bind = elf_st_bind(symtab[i].st_info);
+		int st_type = elf_st_type(symtab[i].st_info);
+
+		if (st_bind == STB_LOCAL)
+			continue;
+
+		if (name == NULL || *name == '\0')
+			continue;
+
+		if (st_type == STT_FUNC || st_type == STT_OBJECT)
 			break;
 	}
 
-	if (addr >= uint64_t_le2host(symbol_table[i - 1].address_le)) {
-		*name = symbol_table[i - 1].symbol_name;
-		if (offset)
-			*offset = addr -
-			    uint64_t_le2host(symbol_table[i - 1].address_le);
-		return EOK;
-	}
-
-	*name = NULL;
-	return ENOENT;
-
-#else
-	*name = NULL;
-	return ENOTSUP;
-#endif
+	return i;
+}
+
+const char *symtab_name_lookup(uintptr_t addr, uintptr_t *symbol_addr)
+{
+	if (symtab == NULL || strtab == NULL)
+		return NULL;
+
+	uintptr_t closest_symbol_addr = 0;
+	uintptr_t closest_symbol_name = 0;
+
+	for (size_t i = symtab_next(0); i < symtab_len(); i = symtab_next(i + 1)) {
+		if (symtab[i].st_value > addr)
+			continue;
+
+		if (symtab[i].st_value + symtab[i].st_size > addr) {
+			closest_symbol_addr = symtab[i].st_value;
+			closest_symbol_name = symtab[i].st_name;
+			break;
+		}
+
+		if (symtab[i].st_value > closest_symbol_addr) {
+			closest_symbol_addr = symtab[i].st_value;
+			closest_symbol_name = symtab[i].st_name;
+		}
+	}
+
+	if (closest_symbol_addr == 0)
+		return NULL;
+
+	if (symbol_addr)
+		*symbol_addr = closest_symbol_addr;
+
+	if (closest_symbol_name >= strtab_size)
+		return NULL;
+
+	return strtab + closest_symbol_name;
 }
 
@@ -95,53 +132,9 @@
 const char *symtab_fmt_name_lookup(uintptr_t addr)
 {
-	const char *name;
-	errno_t rc = symtab_name_lookup(addr, &name, NULL);
-
-	switch (rc) {
-	case EOK:
-		return name;
-	case ENOENT:
-		return "unknown";
-	default:
-		return "N/A";
-	}
-}
-
-#ifdef CONFIG_SYMTAB
-
-/** Find symbols that match the parameter forward and print them.
- *
- * @param name     Search string
- * @param startpos Starting position, changes to found position
- *
- * @return Pointer to the part of string that should be completed or NULL.
- *
- */
-static const char *symtab_search_one(const char *name, size_t *startpos)
-{
-	size_t namelen = str_length(name);
-
-	size_t pos;
-	for (pos = *startpos; symbol_table[pos].address_le; pos++) {
-		const char *curname = symbol_table[pos].symbol_name;
-
-		/* Find a ':' in curname */
-		const char *colon = str_chr(curname, ':');
-		if (colon == NULL)
-			continue;
-
-		if (str_length(curname) < namelen)
-			continue;
-
-		if (str_lcmp(name, curname, namelen) == 0) {
-			*startpos = pos;
-			return (curname + str_lsize(curname, namelen));
-		}
-	}
-
-	return NULL;
-}
-
-#endif
+	const char *name = symtab_name_lookup(addr, NULL);
+	if (name == NULL)
+		name = "<unknown>";
+	return name;
+}
 
 /** Return address that corresponds to the entry.
@@ -152,34 +145,17 @@
  * @param addr Place to store symbol address
  *
- * @return Zero on success, ENOENT - not found, EOVERFLOW - duplicate
- *         symbol, ENOTSUP - no symbol information available.
+ * @return Zero on success, ENOENT - not found
  *
  */
 errno_t symtab_addr_lookup(const char *name, uintptr_t *addr)
 {
-#ifdef CONFIG_SYMTAB
-	size_t found = 0;
-	size_t pos = 0;
-	const char *hint;
-
-	while ((hint = symtab_search_one(name, &pos))) {
-		if (str_length(hint) == 0) {
-			*addr = uint64_t_le2host(symbol_table[pos].address_le);
-			found++;
-		}
-		pos++;
-	}
-
-	if (found > 1)
-		return EOVERFLOW;
-
-	if (found < 1)
-		return ENOENT;
-
-	return EOK;
-
-#else
-	return ENOTSUP;
-#endif
+	for (size_t i = symtab_next(0); i < symtab_len(); i = symtab_next(i + 1)) {
+		if (str_cmp(name, symtab_entry_name(i)) == 0) {
+			*addr = symtab[i].st_value;
+			return EOK;
+		}
+	}
+
+	return ENOENT;
 }
 
@@ -187,44 +163,35 @@
 void symtab_print_search(const char *name)
 {
-#ifdef CONFIG_SYMTAB
-	size_t pos = 0;
-	while (symtab_search_one(name, &pos)) {
-		uintptr_t addr = uint64_t_le2host(symbol_table[pos].address_le);
-		char *realname = symbol_table[pos].symbol_name;
-		printf("%p: %s\n", (void *) addr, realname);
-		pos++;
-	}
-
-#else
-	printf("No symbol information available.\n");
-#endif
+	if (symtab == NULL || strtab == NULL) {
+		printf("No symbol information available.\n");
+		return;
+	}
+
+	size_t namelen = str_length(name);
+
+	for (size_t i = symtab_next(0); i < symtab_len(); i = symtab_next(i + 1)) {
+		const char *n = symtab_entry_name(i);
+
+		if (str_lcmp(name, n, namelen) == 0) {
+			printf("%p: %s\n", (void *) symtab[i].st_value, n);
+		}
+	}
 }
 
 /** Symtab completion enum, see kernel/generic/include/kconsole.h */
-const char *symtab_hints_enum(const char *input, const char **help,
-    void **ctx)
-{
-#ifdef CONFIG_SYMTAB
+const char *symtab_hints_enum(const char *input, const char **help, void **ctx)
+{
+	if (symtab == NULL || strtab == NULL)
+		return NULL;
+
+	if (help)
+		*help = NULL;
+
 	size_t len = str_length(input);
-	struct symtab_entry **entry = (struct symtab_entry **)ctx;
-
-	if (*entry == NULL)
-		*entry = symbol_table;
-
-	for (; (*entry)->address_le; (*entry)++) {
-		const char *curname = (*entry)->symbol_name;
-
-		/* Find a ':' in curname */
-		const char *colon = str_chr(curname, ':');
-		if (colon == NULL)
-			continue;
-
-		if (str_length(curname) < len)
-			continue;
+	for (size_t i = symtab_next((size_t) *ctx); i < symtab_len(); i = symtab_next(i + 1)) {
+		const char *curname = symtab_entry_name(i);
 
 		if (str_lcmp(input, curname, len) == 0) {
-			(*entry)++;
-			if (help)
-				*help = NULL;
+			*ctx = (void *) (i + 1);
 			return (curname + str_lsize(curname, len));
 		}
@@ -232,8 +199,4 @@
 
 	return NULL;
-
-#else
-	return NULL;
-#endif
 }
 
Index: kernel/generic/src/main/kinit.c
===================================================================
--- kernel/generic/src/main/kinit.c	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/generic/src/main/kinit.c	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -73,4 +73,5 @@
 #include <align.h>
 #include <stdlib.h>
+#include <debug/register.h>
 
 #ifdef CONFIG_SMP
@@ -182,5 +183,5 @@
 	 */
 	size_t i;
-	program_t programs[CONFIG_INIT_TASKS];
+	program_t programs[CONFIG_INIT_TASKS] = { };
 
 	// FIXME: do not propagate arguments through sysinfo
@@ -237,4 +238,16 @@
 		    PAGE_READ | PAGE_WRITE | PAGE_CACHEABLE);
 		assert(page);
+
+		if (str_cmp(name, "kernel.dbg") == 0) {
+			/*
+			 * Not an actual init task, but rather debug sections extracted
+			 * from the kernel ELF file and handed to us here so we can use
+			 * it for debugging.
+			 */
+
+			register_debug_data((void *) page, init.tasks[i].size);
+			programs[i].task = NULL;
+			continue;
+		}
 
 		if (str_cmp(name, "loader") == 0) {
Index: kernel/meson.build
===================================================================
--- kernel/meson.build	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ kernel/meson.build	(revision da139823a6e0523217c1ab89cf8936eb8fd62ea2)
@@ -41,8 +41,4 @@
 # Defines test_src
 subdir('test')
-
-## Cross-platform assembly to start a symtab.data section
-#
-symtab_section = '.section symtab.data, "a", ' + atsign + 'progbits;'
 
 kernel_include_dirs = include_directories(
@@ -97,9 +93,4 @@
 endif
 
-if CONFIG_STRIP_BINARIES
-	# TODO: do this after disassembling
-	kernel_link_args += [ '-s' ]
-endif
-
 kernel_c_args = arch_kernel_c_args + kernel_defs + [
 	'-ffreestanding',
@@ -149,78 +140,51 @@
 all_kernel_objects = [ instrumentables, noninstrumentables ]
 
-# We iterate the build several times to get symbol table right.
-# Three times is sufficient to get correct even symbols after symtab.
+kernel_name = 'kernel.elf'
+kernel_map_name = kernel_name + '.map'
+kernel_map_path = meson.current_build_dir() / kernel_map_name
+
+kernel_elf = executable(kernel_name,
+	include_directories: kernel_include_dirs,
+	implicit_include_directories: false,
+	c_args: kernel_c_args,
+	link_args: kernel_c_args + kernel_link_args + [
+		'-Wl,-Map,' + kernel_map_path,
+	],
+	link_depends: kernel_ldscript,
+	link_whole: all_kernel_objects,
+	pie: false,
+)
+
+kernel_dbg = custom_target('kernel.dbg',
+	output: 'kernel.dbg',
+	input: kernel_elf,
+	command: [
+		objcopy,
+		'--only-keep-debug',
+		'@INPUT@',
+		'@OUTPUT@',
+	],
+)
+
+kernel_elf_stripped = custom_target(kernel_name + '.stripped',
+	output: kernel_name + '.stripped',
+	input: kernel_elf,
+	command: [
+		objcopy,
+		'--strip-unneeded',
+		'@INPUT@',
+		'@OUTPUT@',
+	],
+)
+
+rd_init_binaries += [[ kernel_elf_stripped, 'boot/kernel.elf' ]]
+install_files += [[ 'boot', kernel_elf_stripped.full_path(), 'kernel.elf' ]]
+install_deps += [ kernel_elf_stripped ]
 
 if CONFIG_SYMTAB
-	# Iterate build three times.
-	iterations = [ 1, 2, 3 ]
-
-	# Generates symbol table information as an object file.
-	genmap = find_program('tools/genmap.py')
-
-	# Symbol table dump needed for genmap.
-	kernel_syms = custom_target('kernel_syms.txt',
-		input: all_kernel_objects,
-		output: 'kernel_syms.txt',
-		command: [ objdump, '-t', '@INPUT@' ],
-		capture: true,
-	)
-else
-	# Build just once.
-	iterations = [ 1 ]
-endif
-
-# Empty symbol map for first iteration.
-kernel_map_S = custom_target('empty_map.S',
-	output: 'empty_map.S',
-	capture: true,
-	command: [ 'echo', kernel_as_prolog + symtab_section ],
-)
-
-foreach iter : iterations
-	is_last = (iter == iterations.length())
-	kernel_name = 'kernel.@0@.elf'.format(iter)
-	kernel_map_name = kernel_name + '.map'
-	kernel_map_path = meson.current_build_dir() / kernel_map_name
-
-	kernel_elf = executable(kernel_name, kernel_map_S,
-		include_directories: kernel_include_dirs,
-		implicit_include_directories: false,
-		c_args: kernel_c_args,
-		link_args: kernel_c_args + kernel_link_args + [
-			'-Wl,-Map,' + kernel_map_path,
-		],
-		link_depends: kernel_ldscript,
-		link_whole: all_kernel_objects,
-		pie: false,
-	)
-
-	# Generate symbol table if this is not the final iteration.
-	if not is_last
-
-		# TODO: Teach kernel to read its own ELF symbol table and get rid of this nonsense.
-		# Need to first make sure all architectures (even future ones with dumb bootloaders) can use ELF formatted kernel.
-
-		kernel_map_bin = custom_target(kernel_map_name + '.bin',
-			output: kernel_map_name + '.bin',
-			input: [ kernel_elf, kernel_syms ],
-			command: [ genmap, kernel_map_path, '@INPUT1@', '@OUTPUT@' ],
-		)
-
-		kernel_map_S_name = kernel_name + '.map.S'
-
-		kernel_map_S = custom_target(kernel_map_S_name,
-			input: kernel_map_bin,
-			output: kernel_map_S_name,
-			capture: true,
-			command: [ 'echo', kernel_as_prolog + symtab_section + ' .incbin "@INPUT@"' ],
-		)
-	endif
-endforeach
-
-rd_init_binaries += [[ kernel_elf, 'boot/kernel.elf' ]]
-
-install_files += [[ 'boot', kernel_elf.full_path(), 'kernel.elf' ]]
-install_deps += [ kernel_elf ]
+	rd_init_binaries += [[ kernel_dbg, 'kernel.dbg' ]]
+	install_files += [[ 'boot', kernel_dbg.full_path(), 'kernel.dbg' ]]
+	install_deps += [ kernel_dbg ]
+endif
 
 kernel_disasm = custom_target('kernel.elf.disasm',
Index: kernel/tools/genmap.py
===================================================================
--- kernel/tools/genmap.py	(revision d28bdbe75cc46051fcb1dd433ed83437fd3320c0)
+++ 	(revision )
@@ -1,124 +1,0 @@
-#!/usr/bin/env python
-#
-# Copyright (c) 2006 Ondrej Palkovsky
-# All rights reserved.
-#
-# Redistribution and use in source and binary forms, with or without
-# modification, are permitted provided that the following conditions
-# are met:
-#
-# - Redistributions of source code must retain the above copyright
-#   notice, this list of conditions and the following disclaimer.
-# - Redistributions in binary form must reproduce the above copyright
-#   notice, this list of conditions and the following disclaimer in the
-#   documentation and/or other materials provided with the distribution.
-# - The name of the author may not be used to endorse or promote products
-#   derived from this software without specific prior written permission.
-#
-# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
-# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
-# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
-# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
-
-"""
-Create binary symbol map out of linker map file
-"""
-
-import sys
-import struct
-import re
-
-MAXSTRING = 63
-symtabfmt = "<Q%ds" % (MAXSTRING + 1)
-
-funcline = re.compile(r'([0-9a-f]+)\s+[lg]\s+.\s+\.text\s+([0-9a-f]+)\s+(.*)$')
-bssline = re.compile(r'([0-9a-f]+)\s+[lg]\s+[a-zA-Z]\s+\.bss\s+([0-9a-f]+)\s+(.*)$')
-dataline = re.compile(r'([0-9a-f]+)\s+[lg]\s+[a-zA-Z]\s+\.data\s+([0-9a-f]+)\s+(.*)$')
-fileexp = re.compile(r'([^\s]+):\s+file format')
-startfile = re.compile(r'\.(text|bss|data)\s+(0x[0-9a-f]+)\s+0x[0-9a-f]+\s+(.*)$')
-
-def read_obdump(inp):
-	"Parse input"
-
-	funcs = {}
-	data = {}
-	bss = {}
-	fname = ''
-
-	for line in inp:
-		line = line.strip()
-		res = funcline.match(line)
-		if (res):
-			funcs.setdefault(fname, []).append((int(res.group(1), 16), res.group(3)))
-			continue
-
-		res = bssline.match(line)
-		if (res):
-			start = int(res.group(1), 16)
-			end = int(res.group(2), 16)
-			if (end):
-				bss.setdefault(fname, []).append((start, res.group(3)))
-
-		res = dataline.match(line)
-		if (res):
-			start = int(res.group(1), 16)
-			end = int(res.group(2), 16)
-			if (end):
-				data.setdefault(fname, []).append((start, res.group(3)))
-
-		res = fileexp.match(line)
-		if (res):
-			fname = res.group(1)
-			continue
-
-	return {'text' : funcs, 'bss' : bss, 'data' : data}
-
-def generate(kmapf, obmapf, out):
-	"Generate output file"
-
-	obdump = read_obdump(obmapf)
-
-	def key_sorter(x):
-		return x[0]
-
-	for line in kmapf:
-		line = line.strip()
-		res = startfile.match(line)
-
-		if ((res) and (res.group(3) in obdump[res.group(1)])):
-			offset = int(res.group(2), 16)
-			fname = res.group(3)
-			symbols = obdump[res.group(1)][fname]
-			symbols.sort(key = key_sorter)
-			for addr, symbol in symbols:
-				value = fname + ':' + symbol
-				value_bytes = value.encode('ascii')
-				data = struct.pack(symtabfmt, addr + offset, value_bytes[:MAXSTRING])
-				out.write(data)
-
-	out.write(struct.pack(symtabfmt, 0, b''))
-
-def main():
-	if (len(sys.argv) != 4):
-		print("Usage: %s <kernel.map> <nm dump> <output.bin>" % sys.argv[0])
-		return 1
-
-	kmapf = open(sys.argv[1], 'r')
-	obmapf = open(sys.argv[2], 'r')
-	out = open(sys.argv[3], 'wb')
-
-	generate(kmapf, obmapf, out)
-
-	kmapf.close()
-	obmapf.close()
-	out.close()
-
-if __name__ == '__main__':
-	sys.exit(main())
