diff options
| author | Atsushi Nemoto <anemo@mba.ocn.ne.jp> | 2007-05-16 12:14:38 -0400 |
|---|---|---|
| committer | Sam Ravnborg <sam@ravnborg.org> | 2007-05-19 03:11:57 -0400 |
| commit | f892b7d480eec809a5dfbd6e65742b3f3155e50e (patch) | |
| tree | 5c762c6d1049973204acc3997d26bdc44ba9bdcb /scripts/mod | |
| parent | 2560120997403581dd824e5bd2389c719edcbf12 (diff) | |
kbuild: make better section mismatch reports on i386, arm and mips
On i386, ARM and MIPS, warn_sec_mismatch() sometimes fails to show
usefull symbol name. This is because empty 'refsym' due to 0 r_addend
value. This patch is to adjust r_addend value, consulting with
apply_relocate() routine in kernel code.
Without this patch:
MODPOST vmlinux
WARNING: init/built-in.o - Section mismatch: reference to .init.text: from .text between 'rest_init' (at offset 0xf4) and 'try_name'
WARNING: mm/built-in.o - Section mismatch: reference to .init.text: from .text between 'kmem_cache_create' (at offset 0x18a39) and 'cache_reap'
WARNING: mm/built-in.o - Section mismatch: reference to .init.text: from .text between 'kmem_cache_create' (at offset 0x18a6b) and 'cache_reap'
With this patch:
MODPOST vmlinux
WARNING: mm/built-in.o - Section mismatch: reference to .init.text:set_up_list3s from .text between 'kmem_cache_create' (at offset 0x18a39) and 'cache_reap'
WARNING: mm/built-in.o - Section mismatch: reference to .init.text:set_up_list3s from .text between 'kmem_cache_create' (at offset 0x18a6b) and 'cache_reap'
Now modpost can detect "kernel_init" name (and whitelist it) and show
"set_up_list3s" name.
Signed-off-by: Atsushi Nemoto <anemo@mba.ocn.ne.jp>
Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Diffstat (limited to 'scripts/mod')
| -rw-r--r-- | scripts/mod/modpost.c | 79 | ||||
| -rw-r--r-- | scripts/mod/modpost.h | 3 |
2 files changed, 82 insertions, 0 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c index 2fcdbc7a1ee5..ce7e0d17bae2 100644 --- a/scripts/mod/modpost.c +++ b/scripts/mod/modpost.c | |||
| @@ -384,6 +384,7 @@ static int parse_elf(struct elf_info *info, const char *filename) | |||
| 384 | sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); | 384 | sechdrs[i].sh_size = TO_NATIVE(sechdrs[i].sh_size); |
| 385 | sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); | 385 | sechdrs[i].sh_link = TO_NATIVE(sechdrs[i].sh_link); |
| 386 | sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name); | 386 | sechdrs[i].sh_name = TO_NATIVE(sechdrs[i].sh_name); |
| 387 | sechdrs[i].sh_info = TO_NATIVE(sechdrs[i].sh_info); | ||
| 387 | } | 388 | } |
| 388 | /* Find symbol table. */ | 389 | /* Find symbol table. */ |
| 389 | for (i = 1; i < hdr->e_shnum; i++) { | 390 | for (i = 1; i < hdr->e_shnum; i++) { |
| @@ -773,6 +774,8 @@ static Elf_Sym *find_elf_symbol(struct elf_info *elf, Elf_Addr addr, | |||
| 773 | for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { | 774 | for (sym = elf->symtab_start; sym < elf->symtab_stop; sym++) { |
| 774 | if (sym->st_shndx != relsym->st_shndx) | 775 | if (sym->st_shndx != relsym->st_shndx) |
| 775 | continue; | 776 | continue; |
| 777 | if (ELF_ST_TYPE(sym->st_info) == STT_SECTION) | ||
| 778 | continue; | ||
| 776 | if (sym->st_value == addr) | 779 | if (sym->st_value == addr) |
| 777 | return sym; | 780 | return sym; |
| 778 | } | 781 | } |
| @@ -910,6 +913,68 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec, | |||
| 910 | } | 913 | } |
| 911 | } | 914 | } |
| 912 | 915 | ||
| 916 | static void addend_386_rel(struct elf_info *elf, int section, Elf_Rela *r) | ||
| 917 | { | ||
| 918 | Elf_Shdr *sechdrs = elf->sechdrs; | ||
| 919 | unsigned int r_typ; | ||
| 920 | unsigned int *location; | ||
| 921 | |||
| 922 | r_typ = ELF_R_TYPE(r->r_info); | ||
| 923 | location = (void *)elf->hdr + | ||
| 924 | sechdrs[sechdrs[section].sh_info].sh_offset + r->r_offset; | ||
| 925 | switch (r_typ) { | ||
| 926 | case R_386_32: | ||
| 927 | r->r_addend = TO_NATIVE(*location); | ||
| 928 | break; | ||
| 929 | case R_386_PC32: | ||
| 930 | r->r_addend = TO_NATIVE(*location) + 4; | ||
| 931 | break; | ||
| 932 | } | ||
| 933 | } | ||
| 934 | |||
| 935 | static void addend_arm_rel(struct elf_info *elf, int section, Elf_Rela *r) | ||
| 936 | { | ||
| 937 | Elf_Shdr *sechdrs = elf->sechdrs; | ||
| 938 | unsigned int r_typ; | ||
| 939 | unsigned int *location; | ||
| 940 | |||
| 941 | r_typ = ELF_R_TYPE(r->r_info); | ||
| 942 | location = (void *)elf->hdr + | ||
| 943 | sechdrs[sechdrs[section].sh_info].sh_offset + r->r_offset; | ||
| 944 | switch (r_typ) { | ||
| 945 | case R_ARM_ABS32: | ||
| 946 | r->r_addend = TO_NATIVE(*location); | ||
| 947 | break; | ||
| 948 | case R_ARM_PC24: | ||
| 949 | r->r_addend = ((TO_NATIVE(*location) & 0x00ffffff) << 2) + 8; | ||
| 950 | break; | ||
| 951 | } | ||
| 952 | } | ||
| 953 | |||
| 954 | static int addend_mips_rel(struct elf_info *elf, int section, Elf_Rela *r) | ||
| 955 | { | ||
| 956 | Elf_Shdr *sechdrs = elf->sechdrs; | ||
| 957 | unsigned int r_typ; | ||
| 958 | unsigned int *location; | ||
| 959 | unsigned int inst; | ||
| 960 | |||
| 961 | r_typ = ELF_R_TYPE(r->r_info); | ||
| 962 | if (r_typ == R_MIPS_HI16) | ||
| 963 | return 1; /* skip this */ | ||
| 964 | location = (void *)elf->hdr + | ||
| 965 | sechdrs[sechdrs[section].sh_info].sh_offset + r->r_offset; | ||
| 966 | inst = TO_NATIVE(*location); | ||
| 967 | switch (r_typ) { | ||
| 968 | case R_MIPS_LO16: | ||
| 969 | r->r_addend = ((inst & 0xffff) ^ 0x8000) - 0x8000; | ||
| 970 | break; | ||
| 971 | case R_MIPS_26: | ||
| 972 | r->r_addend = (inst & 0x03ffffff) << 2; | ||
| 973 | break; | ||
| 974 | } | ||
| 975 | return 0; | ||
| 976 | } | ||
| 977 | |||
| 913 | /** | 978 | /** |
| 914 | * A module includes a number of sections that are discarded | 979 | * A module includes a number of sections that are discarded |
| 915 | * either when loaded or when used as built-in. | 980 | * either when loaded or when used as built-in. |
| @@ -953,8 +1018,11 @@ static void check_sec_ref(struct module *mod, const char *modname, | |||
| 953 | r.r_offset = TO_NATIVE(rela->r_offset); | 1018 | r.r_offset = TO_NATIVE(rela->r_offset); |
| 954 | #if KERNEL_ELFCLASS == ELFCLASS64 | 1019 | #if KERNEL_ELFCLASS == ELFCLASS64 |
| 955 | if (hdr->e_machine == EM_MIPS) { | 1020 | if (hdr->e_machine == EM_MIPS) { |
| 1021 | unsigned int r_typ; | ||
| 956 | r_sym = ELF64_MIPS_R_SYM(rela->r_info); | 1022 | r_sym = ELF64_MIPS_R_SYM(rela->r_info); |
| 957 | r_sym = TO_NATIVE(r_sym); | 1023 | r_sym = TO_NATIVE(r_sym); |
| 1024 | r_typ = ELF64_MIPS_R_TYPE(rela->r_info); | ||
| 1025 | r.r_info = ELF64_R_INFO(r_sym, r_typ); | ||
| 958 | } else { | 1026 | } else { |
| 959 | r.r_info = TO_NATIVE(rela->r_info); | 1027 | r.r_info = TO_NATIVE(rela->r_info); |
| 960 | r_sym = ELF_R_SYM(r.r_info); | 1028 | r_sym = ELF_R_SYM(r.r_info); |
| @@ -987,8 +1055,11 @@ static void check_sec_ref(struct module *mod, const char *modname, | |||
| 987 | r.r_offset = TO_NATIVE(rel->r_offset); | 1055 | r.r_offset = TO_NATIVE(rel->r_offset); |
| 988 | #if KERNEL_ELFCLASS == ELFCLASS64 | 1056 | #if KERNEL_ELFCLASS == ELFCLASS64 |
| 989 | if (hdr->e_machine == EM_MIPS) { | 1057 | if (hdr->e_machine == EM_MIPS) { |
| 1058 | unsigned int r_typ; | ||
| 990 | r_sym = ELF64_MIPS_R_SYM(rel->r_info); | 1059 | r_sym = ELF64_MIPS_R_SYM(rel->r_info); |
| 991 | r_sym = TO_NATIVE(r_sym); | 1060 | r_sym = TO_NATIVE(r_sym); |
| 1061 | r_typ = ELF64_MIPS_R_TYPE(rel->r_info); | ||
| 1062 | r.r_info = ELF64_R_INFO(r_sym, r_typ); | ||
| 992 | } else { | 1063 | } else { |
| 993 | r.r_info = TO_NATIVE(rel->r_info); | 1064 | r.r_info = TO_NATIVE(rel->r_info); |
| 994 | r_sym = ELF_R_SYM(r.r_info); | 1065 | r_sym = ELF_R_SYM(r.r_info); |
| @@ -998,6 +1069,14 @@ static void check_sec_ref(struct module *mod, const char *modname, | |||
| 998 | r_sym = ELF_R_SYM(r.r_info); | 1069 | r_sym = ELF_R_SYM(r.r_info); |
| 999 | #endif | 1070 | #endif |
| 1000 | r.r_addend = 0; | 1071 | r.r_addend = 0; |
| 1072 | if (hdr->e_machine == EM_386) | ||
| 1073 | addend_386_rel(elf, i, &r); | ||
| 1074 | else if (hdr->e_machine == EM_ARM) | ||
| 1075 | addend_arm_rel(elf, i, &r); | ||
| 1076 | else if (hdr->e_machine == EM_MIPS) { | ||
| 1077 | if (addend_mips_rel(elf, i, &r)) | ||
| 1078 | continue; | ||
| 1079 | } | ||
| 1001 | sym = elf->symtab_start + r_sym; | 1080 | sym = elf->symtab_start + r_sym; |
| 1002 | /* Skip special sections */ | 1081 | /* Skip special sections */ |
| 1003 | if (sym->st_shndx >= SHN_LORESERVE) | 1082 | if (sym->st_shndx >= SHN_LORESERVE) |
diff --git a/scripts/mod/modpost.h b/scripts/mod/modpost.h index 0858caa9c03f..4156dd34c5de 100644 --- a/scripts/mod/modpost.h +++ b/scripts/mod/modpost.h | |||
| @@ -60,6 +60,9 @@ typedef union | |||
| 60 | #define ELF64_MIPS_R_SYM(i) \ | 60 | #define ELF64_MIPS_R_SYM(i) \ |
| 61 | ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_sym) | 61 | ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_sym) |
| 62 | 62 | ||
| 63 | #define ELF64_MIPS_R_TYPE(i) \ | ||
| 64 | ((__extension__ (_Elf64_Mips_R_Info_union)(i)).r_info_fields.r_type1) | ||
| 65 | |||
| 63 | #if KERNEL_ELFDATA != HOST_ELFDATA | 66 | #if KERNEL_ELFDATA != HOST_ELFDATA |
| 64 | 67 | ||
| 65 | static inline void __endian(const void *src, void *dest, unsigned int size) | 68 | static inline void __endian(const void *src, void *dest, unsigned int size) |
