aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/dwarf.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/dwarf.c')
-rw-r--r--arch/sh/kernel/dwarf.c135
1 files changed, 105 insertions, 30 deletions
diff --git a/arch/sh/kernel/dwarf.c b/arch/sh/kernel/dwarf.c
index 577302f31e6a..981315c6d656 100644
--- a/arch/sh/kernel/dwarf.c
+++ b/arch/sh/kernel/dwarf.c
@@ -655,7 +655,7 @@ bail:
655} 655}
656 656
657static int dwarf_parse_cie(void *entry, void *p, unsigned long len, 657static int dwarf_parse_cie(void *entry, void *p, unsigned long len,
658 unsigned char *end) 658 unsigned char *end, struct module *mod)
659{ 659{
660 struct dwarf_cie *cie; 660 struct dwarf_cie *cie;
661 unsigned long flags; 661 unsigned long flags;
@@ -751,6 +751,8 @@ static int dwarf_parse_cie(void *entry, void *p, unsigned long len,
751 cie->initial_instructions = p; 751 cie->initial_instructions = p;
752 cie->instructions_end = end; 752 cie->instructions_end = end;
753 753
754 cie->mod = mod;
755
754 /* Add to list */ 756 /* Add to list */
755 spin_lock_irqsave(&dwarf_cie_lock, flags); 757 spin_lock_irqsave(&dwarf_cie_lock, flags);
756 list_add_tail(&cie->link, &dwarf_cie_list); 758 list_add_tail(&cie->link, &dwarf_cie_list);
@@ -761,7 +763,7 @@ static int dwarf_parse_cie(void *entry, void *p, unsigned long len,
761 763
762static int dwarf_parse_fde(void *entry, u32 entry_type, 764static int dwarf_parse_fde(void *entry, u32 entry_type,
763 void *start, unsigned long len, 765 void *start, unsigned long len,
764 unsigned char *end) 766 unsigned char *end, struct module *mod)
765{ 767{
766 struct dwarf_fde *fde; 768 struct dwarf_fde *fde;
767 struct dwarf_cie *cie; 769 struct dwarf_cie *cie;
@@ -810,6 +812,8 @@ static int dwarf_parse_fde(void *entry, u32 entry_type,
810 fde->instructions = p; 812 fde->instructions = p;
811 fde->end = end; 813 fde->end = end;
812 814
815 fde->mod = mod;
816
813 /* Add to list. */ 817 /* Add to list. */
814 spin_lock_irqsave(&dwarf_fde_lock, flags); 818 spin_lock_irqsave(&dwarf_fde_lock, flags);
815 list_add_tail(&fde->link, &dwarf_fde_list); 819 list_add_tail(&fde->link, &dwarf_fde_list);
@@ -875,15 +879,15 @@ static void dwarf_unwinder_cleanup(void)
875} 879}
876 880
877/** 881/**
878 * dwarf_unwinder_init - initialise the dwarf unwinder 882 * dwarf_parse_section - parse DWARF section
883 * @eh_frame_start: start address of the .eh_frame section
884 * @eh_frame_end: end address of the .eh_frame section
885 * @mod: the kernel module containing the .eh_frame section
879 * 886 *
880 * Build the data structures describing the .dwarf_frame section to 887 * Parse the information in a .eh_frame section.
881 * make it easier to lookup CIE and FDE entries. Because the
882 * .eh_frame section is packed as tightly as possible it is not
883 * easy to lookup the FDE for a given PC, so we build a list of FDE
884 * and CIE entries that make it easier.
885 */ 888 */
886static int __init dwarf_unwinder_init(void) 889int dwarf_parse_section(char *eh_frame_start, char *eh_frame_end,
890 struct module *mod)
887{ 891{
888 u32 entry_type; 892 u32 entry_type;
889 void *p, *entry; 893 void *p, *entry;
@@ -891,29 +895,12 @@ static int __init dwarf_unwinder_init(void)
891 unsigned long len; 895 unsigned long len;
892 unsigned int c_entries, f_entries; 896 unsigned int c_entries, f_entries;
893 unsigned char *end; 897 unsigned char *end;
894 INIT_LIST_HEAD(&dwarf_cie_list);
895 INIT_LIST_HEAD(&dwarf_fde_list);
896 898
897 c_entries = 0; 899 c_entries = 0;
898 f_entries = 0; 900 f_entries = 0;
899 entry = &__start_eh_frame; 901 entry = eh_frame_start;
900
901 dwarf_frame_cachep = kmem_cache_create("dwarf_frames",
902 sizeof(struct dwarf_frame), 0, SLAB_PANIC, NULL);
903 dwarf_reg_cachep = kmem_cache_create("dwarf_regs",
904 sizeof(struct dwarf_reg), 0, SLAB_PANIC, NULL);
905
906 dwarf_frame_pool = mempool_create(DWARF_FRAME_MIN_REQ,
907 mempool_alloc_slab,
908 mempool_free_slab,
909 dwarf_frame_cachep);
910 902
911 dwarf_reg_pool = mempool_create(DWARF_REG_MIN_REQ, 903 while ((char *)entry < eh_frame_end) {
912 mempool_alloc_slab,
913 mempool_free_slab,
914 dwarf_reg_cachep);
915
916 while ((char *)entry < __stop_eh_frame) {
917 p = entry; 904 p = entry;
918 905
919 count = dwarf_entry_len(p, &len); 906 count = dwarf_entry_len(p, &len);
@@ -925,6 +912,7 @@ static int __init dwarf_unwinder_init(void)
925 * entry and move to the next one because 'len' 912 * entry and move to the next one because 'len'
926 * tells us where our next entry is. 913 * tells us where our next entry is.
927 */ 914 */
915 err = -EINVAL;
928 goto out; 916 goto out;
929 } else 917 } else
930 p += count; 918 p += count;
@@ -936,13 +924,14 @@ static int __init dwarf_unwinder_init(void)
936 p += 4; 924 p += 4;
937 925
938 if (entry_type == DW_EH_FRAME_CIE) { 926 if (entry_type == DW_EH_FRAME_CIE) {
939 err = dwarf_parse_cie(entry, p, len, end); 927 err = dwarf_parse_cie(entry, p, len, end, mod);
940 if (err < 0) 928 if (err < 0)
941 goto out; 929 goto out;
942 else 930 else
943 c_entries++; 931 c_entries++;
944 } else { 932 } else {
945 err = dwarf_parse_fde(entry, entry_type, p, len, end); 933 err = dwarf_parse_fde(entry, entry_type, p, len,
934 end, mod);
946 if (err < 0) 935 if (err < 0)
947 goto out; 936 goto out;
948 else 937 else
@@ -955,6 +944,92 @@ static int __init dwarf_unwinder_init(void)
955 printk(KERN_INFO "DWARF unwinder initialised: read %u CIEs, %u FDEs\n", 944 printk(KERN_INFO "DWARF unwinder initialised: read %u CIEs, %u FDEs\n",
956 c_entries, f_entries); 945 c_entries, f_entries);
957 946
947 return 0;
948
949out:
950 return err;
951}
952
953/**
954 * dwarf_module_unload - remove FDE/CIEs associated with @mod
955 * @mod: the module that is being unloaded
956 *
957 * Remove any FDEs and CIEs from the global lists that came from
958 * @mod's .eh_frame section because @mod is being unloaded.
959 */
960void dwarf_module_unload(struct module *mod)
961{
962 struct dwarf_fde *fde;
963 struct dwarf_cie *cie;
964 unsigned long flags;
965
966 spin_lock_irqsave(&dwarf_cie_lock, flags);
967
968again_cie:
969 list_for_each_entry(cie, &dwarf_cie_list, link) {
970 if (cie->mod == mod)
971 break;
972 }
973
974 if (&cie->link != &dwarf_cie_list) {
975 list_del(&cie->link);
976 kfree(cie);
977 goto again_cie;
978 }
979
980 spin_unlock_irqrestore(&dwarf_cie_lock, flags);
981
982 spin_lock_irqsave(&dwarf_fde_lock, flags);
983
984again_fde:
985 list_for_each_entry(fde, &dwarf_fde_list, link) {
986 if (fde->mod == mod)
987 break;
988 }
989
990 if (&fde->link != &dwarf_fde_list) {
991 list_del(&fde->link);
992 kfree(fde);
993 goto again_fde;
994 }
995
996 spin_unlock_irqrestore(&dwarf_fde_lock, flags);
997}
998
999/**
1000 * dwarf_unwinder_init - initialise the dwarf unwinder
1001 *
1002 * Build the data structures describing the .dwarf_frame section to
1003 * make it easier to lookup CIE and FDE entries. Because the
1004 * .eh_frame section is packed as tightly as possible it is not
1005 * easy to lookup the FDE for a given PC, so we build a list of FDE
1006 * and CIE entries that make it easier.
1007 */
1008static int __init dwarf_unwinder_init(void)
1009{
1010 int err;
1011 INIT_LIST_HEAD(&dwarf_cie_list);
1012 INIT_LIST_HEAD(&dwarf_fde_list);
1013
1014 dwarf_frame_cachep = kmem_cache_create("dwarf_frames",
1015 sizeof(struct dwarf_frame), 0, SLAB_PANIC, NULL);
1016 dwarf_reg_cachep = kmem_cache_create("dwarf_regs",
1017 sizeof(struct dwarf_reg), 0, SLAB_PANIC, NULL);
1018
1019 dwarf_frame_pool = mempool_create(DWARF_FRAME_MIN_REQ,
1020 mempool_alloc_slab,
1021 mempool_free_slab,
1022 dwarf_frame_cachep);
1023
1024 dwarf_reg_pool = mempool_create(DWARF_REG_MIN_REQ,
1025 mempool_alloc_slab,
1026 mempool_free_slab,
1027 dwarf_reg_cachep);
1028
1029 err = dwarf_parse_section(__start_eh_frame, __stop_eh_frame, NULL);
1030 if (err)
1031 goto out;
1032
958 err = unwinder_register(&dwarf_unwinder); 1033 err = unwinder_register(&dwarf_unwinder);
959 if (err) 1034 if (err)
960 goto out; 1035 goto out;