aboutsummaryrefslogtreecommitdiffstats
path: root/scripts
diff options
context:
space:
mode:
Diffstat (limited to 'scripts')
-rw-r--r--scripts/mod/modpost.c242
1 files changed, 137 insertions, 105 deletions
diff --git a/scripts/mod/modpost.c b/scripts/mod/modpost.c
index 902ee55f327f..e4630135979c 100644
--- a/scripts/mod/modpost.c
+++ b/scripts/mod/modpost.c
@@ -937,19 +937,19 @@ static void warn_sec_mismatch(const char *modname, const char *fromsec,
937} 937}
938 938
939static unsigned int *reloc_location(struct elf_info *elf, 939static unsigned int *reloc_location(struct elf_info *elf,
940 int rsection, Elf_Rela *r) 940 Elf_Shdr *sechdr, Elf_Rela *r)
941{ 941{
942 Elf_Shdr *sechdrs = elf->sechdrs; 942 Elf_Shdr *sechdrs = elf->sechdrs;
943 int section = sechdrs[rsection].sh_info; 943 int section = sechdr->sh_info;
944 944
945 return (void *)elf->hdr + sechdrs[section].sh_offset + 945 return (void *)elf->hdr + sechdrs[section].sh_offset +
946 (r->r_offset - sechdrs[section].sh_addr); 946 (r->r_offset - sechdrs[section].sh_addr);
947} 947}
948 948
949static int addend_386_rel(struct elf_info *elf, int rsection, Elf_Rela *r) 949static int addend_386_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
950{ 950{
951 unsigned int r_typ = ELF_R_TYPE(r->r_info); 951 unsigned int r_typ = ELF_R_TYPE(r->r_info);
952 unsigned int *location = reloc_location(elf, rsection, r); 952 unsigned int *location = reloc_location(elf, sechdr, r);
953 953
954 switch (r_typ) { 954 switch (r_typ) {
955 case R_386_32: 955 case R_386_32:
@@ -965,7 +965,7 @@ static int addend_386_rel(struct elf_info *elf, int rsection, Elf_Rela *r)
965 return 0; 965 return 0;
966} 966}
967 967
968static int addend_arm_rel(struct elf_info *elf, int rsection, Elf_Rela *r) 968static int addend_arm_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
969{ 969{
970 unsigned int r_typ = ELF_R_TYPE(r->r_info); 970 unsigned int r_typ = ELF_R_TYPE(r->r_info);
971 971
@@ -978,8 +978,8 @@ static int addend_arm_rel(struct elf_info *elf, int rsection, Elf_Rela *r)
978 case R_ARM_PC24: 978 case R_ARM_PC24:
979 /* From ARM ABI: ((S + A) | T) - P */ 979 /* From ARM ABI: ((S + A) | T) - P */
980 r->r_addend = (int)(long)(elf->hdr + 980 r->r_addend = (int)(long)(elf->hdr +
981 elf->sechdrs[rsection].sh_offset + 981 sechdr->sh_offset +
982 (r->r_offset - elf->sechdrs[rsection].sh_addr)); 982 (r->r_offset - sechdr->sh_addr));
983 break; 983 break;
984 default: 984 default:
985 return 1; 985 return 1;
@@ -987,10 +987,10 @@ static int addend_arm_rel(struct elf_info *elf, int rsection, Elf_Rela *r)
987 return 0; 987 return 0;
988} 988}
989 989
990static int addend_mips_rel(struct elf_info *elf, int rsection, Elf_Rela *r) 990static int addend_mips_rel(struct elf_info *elf, Elf_Shdr *sechdr, Elf_Rela *r)
991{ 991{
992 unsigned int r_typ = ELF_R_TYPE(r->r_info); 992 unsigned int r_typ = ELF_R_TYPE(r->r_info);
993 unsigned int *location = reloc_location(elf, rsection, r); 993 unsigned int *location = reloc_location(elf, sechdr, r);
994 unsigned int inst; 994 unsigned int inst;
995 995
996 if (r_typ == R_MIPS_HI16) 996 if (r_typ == R_MIPS_HI16)
@@ -1010,6 +1010,128 @@ static int addend_mips_rel(struct elf_info *elf, int rsection, Elf_Rela *r)
1010 return 0; 1010 return 0;
1011} 1011}
1012 1012
1013static void section_rela(const char *modname, struct elf_info *elf,
1014 Elf_Shdr *sechdr, int section(const char *),
1015 int section_ref_ok(const char *))
1016{
1017 Elf_Sym *sym;
1018 Elf_Rela *rela;
1019 Elf_Rela r;
1020 unsigned int r_sym;
1021 const char *fromsec;
1022 const char * tosec;
1023
1024 Elf_Ehdr *hdr = elf->hdr;
1025 Elf_Rela *start = (void *)hdr + sechdr->sh_offset;
1026 Elf_Rela *stop = (void *)start + sechdr->sh_size;
1027
1028 const char *secstrings = (void *)hdr +
1029 elf->sechdrs[hdr->e_shstrndx].sh_offset;
1030
1031 fromsec = secstrings + sechdr->sh_name;
1032 fromsec += strlen(".rela");
1033 /* if from section (name) is know good then skip it */
1034 if (section_ref_ok(fromsec))
1035 return;
1036
1037 for (rela = start; rela < stop; rela++) {
1038 r.r_offset = TO_NATIVE(rela->r_offset);
1039#if KERNEL_ELFCLASS == ELFCLASS64
1040 if (hdr->e_machine == EM_MIPS) {
1041 unsigned int r_typ;
1042 r_sym = ELF64_MIPS_R_SYM(rela->r_info);
1043 r_sym = TO_NATIVE(r_sym);
1044 r_typ = ELF64_MIPS_R_TYPE(rela->r_info);
1045 r.r_info = ELF64_R_INFO(r_sym, r_typ);
1046 } else {
1047 r.r_info = TO_NATIVE(rela->r_info);
1048 r_sym = ELF_R_SYM(r.r_info);
1049 }
1050#else
1051 r.r_info = TO_NATIVE(rela->r_info);
1052 r_sym = ELF_R_SYM(r.r_info);
1053#endif
1054 r.r_addend = TO_NATIVE(rela->r_addend);
1055 sym = elf->symtab_start + r_sym;
1056 /* Skip special sections */
1057 if (sym->st_shndx >= SHN_LORESERVE)
1058 continue;
1059
1060 tosec = secstrings +
1061 elf->sechdrs[sym->st_shndx].sh_name;
1062 if (section(tosec))
1063 warn_sec_mismatch(modname, fromsec, elf, sym, r);
1064 }
1065}
1066
1067static void section_rel(const char *modname, struct elf_info *elf,
1068 Elf_Shdr *sechdr, int section(const char *),
1069 int section_ref_ok(const char *))
1070{
1071 Elf_Sym *sym;
1072 Elf_Rel *rel;
1073 Elf_Rela r;
1074 unsigned int r_sym;
1075 const char *fromsec;
1076 const char * tosec;
1077
1078 Elf_Ehdr *hdr = elf->hdr;
1079 Elf_Rel *start = (void *)hdr + sechdr->sh_offset;
1080 Elf_Rel *stop = (void *)start + sechdr->sh_size;
1081
1082 const char *secstrings = (void *)hdr +
1083 elf->sechdrs[hdr->e_shstrndx].sh_offset;
1084
1085 fromsec = secstrings + sechdr->sh_name;
1086 fromsec += strlen(".rel");
1087 /* if from section (name) is know good then skip it */
1088 if (section_ref_ok(fromsec))
1089 return;
1090
1091 for (rel = start; rel < stop; rel++) {
1092 r.r_offset = TO_NATIVE(rel->r_offset);
1093#if KERNEL_ELFCLASS == ELFCLASS64
1094 if (hdr->e_machine == EM_MIPS) {
1095 unsigned int r_typ;
1096 r_sym = ELF64_MIPS_R_SYM(rel->r_info);
1097 r_sym = TO_NATIVE(r_sym);
1098 r_typ = ELF64_MIPS_R_TYPE(rel->r_info);
1099 r.r_info = ELF64_R_INFO(r_sym, r_typ);
1100 } else {
1101 r.r_info = TO_NATIVE(rel->r_info);
1102 r_sym = ELF_R_SYM(r.r_info);
1103 }
1104#else
1105 r.r_info = TO_NATIVE(rel->r_info);
1106 r_sym = ELF_R_SYM(r.r_info);
1107#endif
1108 r.r_addend = 0;
1109 switch (hdr->e_machine) {
1110 case EM_386:
1111 if (addend_386_rel(elf, sechdr, &r))
1112 continue;
1113 break;
1114 case EM_ARM:
1115 if (addend_arm_rel(elf, sechdr, &r))
1116 continue;
1117 break;
1118 case EM_MIPS:
1119 if (addend_mips_rel(elf, sechdr, &r))
1120 continue;
1121 break;
1122 }
1123 sym = elf->symtab_start + r_sym;
1124 /* Skip special sections */
1125 if (sym->st_shndx >= SHN_LORESERVE)
1126 continue;
1127
1128 tosec = secstrings +
1129 elf->sechdrs[sym->st_shndx].sh_name;
1130 if (section(tosec))
1131 warn_sec_mismatch(modname, fromsec, elf, sym, r);
1132 }
1133}
1134
1013/** 1135/**
1014 * A module includes a number of sections that are discarded 1136 * A module includes a number of sections that are discarded
1015 * either when loaded or when used as built-in. 1137 * either when loaded or when used as built-in.
@@ -1028,108 +1150,18 @@ static void check_sec_ref(struct module *mod, const char *modname,
1028 int section_ref_ok(const char *)) 1150 int section_ref_ok(const char *))
1029{ 1151{
1030 int i; 1152 int i;
1031 Elf_Sym *sym;
1032 Elf_Ehdr *hdr = elf->hdr; 1153 Elf_Ehdr *hdr = elf->hdr;
1033 Elf_Shdr *sechdrs = elf->sechdrs; 1154 Elf_Shdr *sechdrs = elf->sechdrs;
1034 const char *secstrings = (void *)hdr +
1035 sechdrs[hdr->e_shstrndx].sh_offset;
1036 1155
1037 /* Walk through all sections */ 1156 /* Walk through all sections */
1038 for (i = 0; i < hdr->e_shnum; i++) { 1157 for (i = 0; i < hdr->e_shnum; i++) {
1039 const char *name = secstrings + sechdrs[i].sh_name;
1040 const char *secname;
1041 Elf_Rela r;
1042 unsigned int r_sym;
1043 /* We want to process only relocation sections and not .init */ 1158 /* We want to process only relocation sections and not .init */
1044 if (sechdrs[i].sh_type == SHT_RELA) { 1159 if (sechdrs[i].sh_type == SHT_RELA)
1045 Elf_Rela *rela; 1160 section_rela(modname, elf, &elf->sechdrs[i],
1046 Elf_Rela *start = (void *)hdr + sechdrs[i].sh_offset; 1161 section, section_ref_ok);
1047 Elf_Rela *stop = (void *)start + sechdrs[i].sh_size; 1162 else if (sechdrs[i].sh_type == SHT_REL)
1048 name += strlen(".rela"); 1163 section_rel(modname, elf, &elf->sechdrs[i],
1049 if (section_ref_ok(name)) 1164 section, section_ref_ok);
1050 continue;
1051
1052 for (rela = start; rela < stop; rela++) {
1053 r.r_offset = TO_NATIVE(rela->r_offset);
1054#if KERNEL_ELFCLASS == ELFCLASS64
1055 if (hdr->e_machine == EM_MIPS) {
1056 unsigned int r_typ;
1057 r_sym = ELF64_MIPS_R_SYM(rela->r_info);
1058 r_sym = TO_NATIVE(r_sym);
1059 r_typ = ELF64_MIPS_R_TYPE(rela->r_info);
1060 r.r_info = ELF64_R_INFO(r_sym, r_typ);
1061 } else {
1062 r.r_info = TO_NATIVE(rela->r_info);
1063 r_sym = ELF_R_SYM(r.r_info);
1064 }
1065#else
1066 r.r_info = TO_NATIVE(rela->r_info);
1067 r_sym = ELF_R_SYM(r.r_info);
1068#endif
1069 r.r_addend = TO_NATIVE(rela->r_addend);
1070 sym = elf->symtab_start + r_sym;
1071 /* Skip special sections */
1072 if (sym->st_shndx >= SHN_LORESERVE)
1073 continue;
1074
1075 secname = secstrings +
1076 sechdrs[sym->st_shndx].sh_name;
1077 if (section(secname))
1078 warn_sec_mismatch(modname, name,
1079 elf, sym, r);
1080 }
1081 } else if (sechdrs[i].sh_type == SHT_REL) {
1082 Elf_Rel *rel;
1083 Elf_Rel *start = (void *)hdr + sechdrs[i].sh_offset;
1084 Elf_Rel *stop = (void *)start + sechdrs[i].sh_size;
1085 name += strlen(".rel");
1086 if (section_ref_ok(name))
1087 continue;
1088
1089 for (rel = start; rel < stop; rel++) {
1090 r.r_offset = TO_NATIVE(rel->r_offset);
1091#if KERNEL_ELFCLASS == ELFCLASS64
1092 if (hdr->e_machine == EM_MIPS) {
1093 unsigned int r_typ;
1094 r_sym = ELF64_MIPS_R_SYM(rel->r_info);
1095 r_sym = TO_NATIVE(r_sym);
1096 r_typ = ELF64_MIPS_R_TYPE(rel->r_info);
1097 r.r_info = ELF64_R_INFO(r_sym, r_typ);
1098 } else {
1099 r.r_info = TO_NATIVE(rel->r_info);
1100 r_sym = ELF_R_SYM(r.r_info);
1101 }
1102#else
1103 r.r_info = TO_NATIVE(rel->r_info);
1104 r_sym = ELF_R_SYM(r.r_info);
1105#endif
1106 r.r_addend = 0;
1107 switch (hdr->e_machine) {
1108 case EM_386:
1109 if (addend_386_rel(elf, i, &r))
1110 continue;
1111 break;
1112 case EM_ARM:
1113 if (addend_arm_rel(elf, i, &r))
1114 continue;
1115 break;
1116 case EM_MIPS:
1117 if (addend_mips_rel(elf, i, &r))
1118 continue;
1119 break;
1120 }
1121 sym = elf->symtab_start + r_sym;
1122 /* Skip special sections */
1123 if (sym->st_shndx >= SHN_LORESERVE)
1124 continue;
1125
1126 secname = secstrings +
1127 sechdrs[sym->st_shndx].sh_name;
1128 if (section(secname))
1129 warn_sec_mismatch(modname, name,
1130 elf, sym, r);
1131 }
1132 }
1133 } 1165 }
1134} 1166}
1135 1167